By Grinneh


2011-05-18 11:44:01 8 Comments

I've been playing around with OpenCV and with alot of trial and error have managed to learn how to detect circles (coins) in a photo. Everything is working great, except when I place coins directly next to each other (as seen below, ignore the fact that the 2nd image is upside down).

Original Photo Contours Found

It seems because the coins are so close together cvFindContours think they are the same object. My question is how can I separate these contours into their separate objects, or get a list of contours that are already separated.

The parameters I used for cvFindContours are:

cvFindContours( img, storage, &contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0) );

Any help or advice would be greatly appreciated.

2 comments

@karlphillip 2011-08-03 18:11:40

This is not great, but it shows how to get there:

IplImage* src = cvLoadImage(argv[1], CV_LOAD_IMAGE_UNCHANGED);
IplImage* gray = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1); 
cvCvtColor(src, gray, CV_BGR2GRAY);
cvSmooth(gray, gray, CV_GAUSSIAN, 7, 7); 

IplImage* cc_img = cvCreateImage(cvGetSize(gray), gray->depth, 3); 
cvSetZero(cc_img);
CvScalar(ext_color);

cvCanny(gray, gray, 10, 30, 3); 

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* circles = cvHoughCircles(gray, storage, CV_HOUGH_GRADIENT, 1, src->height/6, 100, 50);
cvCvtColor(gray, src, CV_GRAY2BGR);
for (size_t i = 0; i < circles->total; i++)
{   
     // round the floats to an int
     float* p = (float*)cvGetSeqElem(circles, i); 
     cv::Point center(cvRound(p[0]), cvRound(p[1]));
     int radius = cvRound(p[2]);

     // draw the circle center
     //cvCircle(cc_img, center, 3, CV_RGB(0,255,0), -1, 8, 0 );

     // draw the circle outline
     cvCircle(cc_img, center, radius+1, CV_RGB(0,0,255), 2, 8, 0 );

     //printf("x: %d y: %d r: %d\n", center.x, center.y, radius);
}   

CvMemStorage *mem;
mem = cvCreateMemStorage(0);
CvSeq *contours = 0;
cvCvtColor(cc_img, gray, CV_BGR2GRAY);
// Use either this:
int n = cvFindContours(gray, mem, &contours, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
// Or this:
//int n = cvFindContours(gray, mem, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

for (; contours != 0; contours = contours->h_next)
{
    ext_color = CV_RGB( rand()&255, rand()&255, rand()&255 ); //randomly coloring different contours
    cvDrawContours(cc_img, contours, ext_color, CV_RGB(0,0,0), -1, CV_FILLED, 8, cvPoint(0,0));
}

cvSaveImage("out.png", cc_img);

enter image description here

@Grinneh 2011-08-04 05:12:55

Thanks for your reply, what I failed to mention in the first post is that preserving the size of each coin was important, as the project was meant to determine what value each coin was based on its size. I'll see if I can tweak it somehow for accuracy. Thanks again

@karlphillip 2011-08-04 13:23:41

Ok, great. Whenever you find an answer interesting you can upvote it. Enjoy our site.

@Karl Voigtland 2011-05-18 11:55:58

You could try thresholding (cvThreshold) the image and then erode (cvErode) the resulting binary image to separate the coins. Then find the contours of the eroded image.

@Grinneh 2011-05-18 21:07:56

Thanks for the suggestion, but I found to erode the image to the point where I could separate the contours resulted in the coins not looking like circles anymore. Losing a little bit of circle accuracy is ok, but overall I want to preserve it as much as possible

@Valentin Heinitz 2012-05-29 12:18:11

Yes, this way is also suggested in OpenCV book for separating cells on a microscope image .

Related Questions

Sponsored Content

10 Answered Questions

26 Answered Questions

[SOLVED] How do you set, clear, and toggle a single bit?

12 Answered Questions

[SOLVED] How do function pointers in C work?

  • 2009-05-08 15:49:17
  • Yuval Adam
  • 717020 View
  • 1047 Score
  • 12 Answer
  • Tags:   c function-pointers

5 Answered Questions

[SOLVED] How do I find Waldo with Mathematica?

1 Answered Questions

How to detect an image between shapes from camera

2 Answered Questions

[SOLVED] OpenCV cvFindContours finds only one contour

1 Answered Questions

[SOLVED] How to get separate contours (and fill them) in OpenCV?

  • 2013-04-14 02:26:14
  • Gerardo Galarza
  • 11820 View
  • 7 Score
  • 1 Answer
  • Tags:   c opencv

0 Answered Questions

OpenCV cvFindContours - how do i find ellipse contour in image

2 Answered Questions

[SOLVED] cvFindContours() not detecting separate components

1 Answered Questions

Sponsored Content