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
Many machine vision problems can benefit as much or more from improved lighting than from complex algorithms. In the original image, the specular reflections and shadows are going to make this problem more challenging.
Try changing the lighting to something more like diffuse front lighting (http://www.looptechnology.com/Pages/M...)
What does the image look like when you try this?