Please suggest strategy for Part counting and identification

asked 2019-02-03 03:19:54 -0600

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

berak gravatar image

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

edit retag flag offensive close merge delete

Comments

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?

Chris gravatar imageChris ( 2019-03-01 10:17:50 -0600 )edit