Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting small circles with OpenCV (bad image quality)

I'm trying to detect the four dots you can see in the center of this picture: enter image description here This one is converted to png, I actually use a ppm format (after conversion from raw output from the camera). The actual processed image is available here

I'm new to opencv and therefore have a huge problem detecting those dots. Here's my so far best result: enter image description here

As you can see, I've detected 3 of the dots, but aside from that also lots of other things in the picture are recognized as circles.

And here's the code:

    IplImage* img;
    if((img = cvLoadImage( "photos/img-000012.ppm", 1)) == 0 )
    {
        perror("cvLoadImage");
        return 1;
    }
    cvNamedWindow( "Image view", 1 );
    cvShowImage( "Image view", img );
//  cvWaitKey(0);

    IplImage* gray = cvCreateImage( cvGetSize(img), 8, 1 ); // allocate a 1 channel byte image
    CvMemStorage* storage = cvCreateMemStorage(0);
    cvCvtColor( img, gray, CV_BGR2GRAY );
    cvShowImage( "Image view", gray );
//  cvWaitKey(0);

    cvSmooth( gray, gray, CV_GAUSSIAN, 3, 3, 0, 0 );
    cvShowImage( "Image view", gray );
    cvWaitKey(0);

    CvSeq* circles = cvHoughCircles(gray, storage, CV_HOUGH_GRADIENT,
            4,      // inverse ratio of the accumulator resolution
            1,      // minimum distance between circle centres
            100,    // higher threshold value for Canny
            20,     // accumulator threshold for the circle centers; smaller->more false circles
            1,  // minimum radius
            10 );   // maximum radius

    printf("circles == %d\n", circles->total);
    int i;
    for (i = 0; i < circles->total; i++) {
        float *p = (float*)cvGetSeqElem(circles, i);
        CvPoint center = cvPoint(cvRound(p[0]),cvRound(p[1]));
        CvScalar val = cvGet2D(gray, center.y, center.x);
        if (val.val[0] < 1) continue;
        printf("%d %d %d\n", cvRound(p[0]),cvRound(p[1]), cvRound(p[2]));
        cvCircle(img,  center, cvRound(p[2]),             CV_RGB(0,255,0), 1, CV_AA, 0);
    }
    cvShowImage( "Image view", img );
    cvWaitKey(0);

Do you have any idea how to help that? I would be most grateful. I think it's quite easy for a human eye to spot the dots, so I hope I can detect them using a computer.

like image 322
Wojtek Avatar asked Oct 08 '22 00:10

Wojtek


1 Answers

You should have a look at this post.

With the application I am developing based on it, I got:

enter image description here

You could basically adapt this method to you case and make it much more efficient: "5." ("validate or invalidate contours on the grant of their shape (size, area, convexity..."). In your case could be much more stringent since you do not have clusters of circles. You could just map objects that are almost perfect circles. In addition, you know that your circles have the same size/relative intensity...

Tell me if anything is not clear,

Good luck,

like image 157
Quentin Geissmann Avatar answered Oct 13 '22 10:10

Quentin Geissmann