首页 文章

OpenCV cvFindContours - 如何分离轮廓的组件

提问于
浏览
13

我一直在玩OpenCV,并且有很多试验和错误已经设法学习如何检测照片中的圆圈(硬币) . 一切都很好,除非我直接将硬币放在一起(如下所示,忽略了第二张图像倒置的事实) .

Original Photo

Contours Found

看起来因为硬币是如此接近,cvFindContours认为它们是同一个对象 . 我的问题是如何将这些轮廓分成单独的对象,或者获得已经分离的轮廓列表 .

我用于cvFindContours的参数是:

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

任何帮助或建议将不胜感激 .

2 回答

  • 3

    这不是很好,但它显示了如何到达那里:

    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

  • 13

    您可以尝试阈值处理(cvThreshold)图像,然后侵蚀(cvErode)生成的二进制图像以分离硬币 . 然后找到侵蚀图像的轮廓 .

相关问题