Ask Your Question

Revision history [back]

Please suggest strategy for Part counting and identification

I am new to openCV and i am trying to acheive two things. 1. idetify type of each part kept in crate 2. count number of parts of each type.

the sample image is attached.

I am applying following strategy to achieve the goals 1. convert image to HSV and use Hue plane to threshold the image to eliminate background(and to locate the ROI for more difficult images) 2. with ROI selected apply threshold to saturation or value plane to isolate each parts mask. (may be i can apply distance watershed for actual separation) 3. isolate each image area and do template match to actually identify and count the objects

the problem i am facing is that i am not able to apply proper threshold to isolate the parts from white separator sheets. does my strategy seems to be fine or is there any other robust way i should go with. if my strategy is correct then what should i do to isolate objects.

My code is as follows

int ImageProcessor::findObjects(QString imageName, QString templateName) { Mat dispImg; Mat frame; Mat hsvImg; Mat tmplateImg; Mat result;

dispImg = imread(imageName.toStdString(),CV_LOAD_IMAGE_COLOR);
frame = imread(imageName.toStdString(),CV_LOAD_IMAGE_COLOR);
cvtColor(frame,hsvImg,COLOR_BGR2HSV);

//get separate HSV Planes
vector<Mat> hsv_planes;
split(hsvImg,hsv_planes);

//hue plane will act like mask. this will isolate crate boundry
//and turn everything which is outside the crate to black color
Mat op;
Mat binImg;
medianBlur(hsv_planes[0],op,3);

threshold( op, binImg, 95, 190,0);//default threashold = 80;

// Floodfill from point (0, 0)
Mat im_floodfill = binImg.clone();
floodFill(im_floodfill, cv::Point(0,0), Scalar(255));

// Invert floodfilled image
Mat im_floodfill_inv;
bitwise_not(im_floodfill, im_floodfill_inv);

Mat HuePlane = hsv_planes[1].clone();
Mat clImg;
Mat invImg ;

threshold( HuePlane, invImg, 70, 255,1);

Mat cleanImg;
medianBlur(invImg,cleanImg,3);

imwrite("clean.png",cleanImg);

int numErosions =3;

Mat element = getStructuringElement( MORPH_RECT,
                                         Size( 2*numErosions + 1, 2*numErosions+1 ),
                                         Point( numErosions, numErosions ) );
Mat dilatedImg;
dilate(cleanImg,dilatedImg,element);
erode(dilatedImg, cleanImg, element);


imshow("result2", cleanImg);

// invImg.copyTo(clImg, im_floodfill_inv);

// imwrite("hue.png",hsv_planes[0]); // imwrite("Saturation.png",hsv_planes[1]); // imwrite("value.png",hsv_planes[2]); // imshow("result", clImg);

Mat dist;
distanceTransform(cleanImg, dist, DIST_L2, 3);
// Normalize the distance image for range = {0.0, 1.0}
// so we can visualize and threshold it
normalize(dist, dist, 0, 1.0, NORM_MINMAX);
imshow("Distance Transform Image", dist);
imwrite("dist.png",dist);

// Threshold to obtain the peaks
// This will be the markers for the foreground objects
threshold(dist, dist, 0.1, 1.0, THRESH_BINARY);
// Dilate a bit the dist image
Mat kernel1 = Mat::ones(3, 3, CV_8U);
dilate(dist, dist, kernel1);
imshow("Peaks", dist);
imwrite("Peaks.png",dist);

}

C:\fakepath\orignal.JPG C:\fakepath\clean.png C:\fakepath\dist.png C:\fakepath\Peaks.png

click to hide/show revision 2
None

updated 2019-02-03 03:24:53 -0500

berak gravatar image

Please suggest strategy for Part counting and identification

I am new to openCV and i am trying to acheive two things. 1. idetify type of each part kept in crate 2. count number of parts of each type.

the sample image is attached.

I am applying following strategy to achieve the goals 1. convert image to HSV and use Hue plane to threshold the image to eliminate background(and to locate the ROI for more difficult images) 2. with ROI selected apply threshold to saturation or value plane to isolate each parts mask. (may be i can apply distance watershed for actual separation) 3. isolate each image area and do template match to actually identify and count the objects

the problem i am facing is that i am not able to apply proper threshold to isolate the parts from white separator sheets. does my strategy seems to be fine or is there any other robust way i should go with. if my strategy is correct then what should i do to isolate objects.

My code is as follows

int ImageProcessor::findObjects(QString imageName, QString templateName)
{
    Mat dispImg;
    Mat frame;
    Mat hsvImg;
    Mat tmplateImg;
    Mat result;

result;

    dispImg = imread(imageName.toStdString(),CV_LOAD_IMAGE_COLOR);
 frame = imread(imageName.toStdString(),CV_LOAD_IMAGE_COLOR);
 cvtColor(frame,hsvImg,COLOR_BGR2HSV);

 //get separate HSV Planes
 vector<Mat> hsv_planes;
 split(hsvImg,hsv_planes);

 //hue plane will act like mask. this will isolate crate boundry
 //and turn everything which is outside the crate to black color
 Mat op;
 Mat binImg;
 medianBlur(hsv_planes[0],op,3);

 threshold( op, binImg, 95, 190,0);//default threashold = 80;

 // Floodfill from point (0, 0)
 Mat im_floodfill = binImg.clone();
 floodFill(im_floodfill, cv::Point(0,0), Scalar(255));

 // Invert floodfilled image
 Mat im_floodfill_inv;
 bitwise_not(im_floodfill, im_floodfill_inv);

 Mat HuePlane = hsv_planes[1].clone();
 Mat clImg;
 Mat invImg ;

 threshold( HuePlane, invImg, 70, 255,1);

 Mat cleanImg;
 medianBlur(invImg,cleanImg,3);

 imwrite("clean.png",cleanImg);

 int numErosions =3;

 Mat element = getStructuringElement( MORPH_RECT,
                                          Size( 2*numErosions + 1, 2*numErosions+1 ),
                                          Point( numErosions, numErosions ) );
 Mat dilatedImg;
 dilate(cleanImg,dilatedImg,element);
 erode(dilatedImg, cleanImg, element);


 imshow("result2", cleanImg);

// invImg.copyTo(clImg, im_floodfill_inv);

im_floodfill_inv); // imwrite("hue.png",hsv_planes[0]); // imwrite("Saturation.png",hsv_planes[1]); // imwrite("value.png",hsv_planes[2]); // imshow("result", clImg);

clImg);

    Mat dist;
 distanceTransform(cleanImg, dist, DIST_L2, 3);
 // Normalize the distance image for range = {0.0, 1.0}
 // so we can visualize and threshold it
 normalize(dist, dist, 0, 1.0, NORM_MINMAX);
 imshow("Distance Transform Image", dist);
 imwrite("dist.png",dist);

 // Threshold to obtain the peaks
 // This will be the markers for the foreground objects
 threshold(dist, dist, 0.1, 1.0, THRESH_BINARY);
 // Dilate a bit the dist image
 Mat kernel1 = Mat::ones(3, 3, CV_8U);
 dilate(dist, dist, kernel1);
 imshow("Peaks", dist);
 imwrite("Peaks.png",dist);
}

}

C:\fakepath\orignal.JPG C:\fakepath\clean.png C:\fakepath\dist.png C:\fakepath\Peaks.png