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).
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.
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);