2

From the code below, I am able to draw the biggest contour with the centroid marked as a small circle and the hull as a yellow line. How do I draw the convexity defects? Should I use the circle() function or the drawContours() function?

Mat bw;
Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;

findContours( bw, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
int s = getBiggestContour(contours);

Mat drawing = Mat::zeros( src.size(), CV_8UC3 ); //UC1

Point2f mc = getCentroidPoint(contours[s]);
drawContours( drawing, contours, s, Scalar(255,255,255), -1, 8, hierarchy, 0, Point() );
circle( drawing, mc, 4, Scalar(0,0,255), 1, 8, 0 );

vector<vector<Point> >hull( contours[s].size() );
convexHull( Mat(contours[s]), hull[s], false );
drawContours( drawing, hull, s, Scalar(0,255,255), 1, 8, vector<Vec4i>(), 0, Point() );

The code above works but there's only one contour to be used which is the biggest contour so I think using vector> for hull is too much. How do I simplify that?

The code below is from another stackoverflow question but it doesn't show how to use the defects variable in drawing the convexity defect onto the Mat image. How can this be achieved?

vector<vector<int> > hullsI(contours.size());
vector<vector<Point> > hullsP(contours.size());
vector<vector<Vec4i> > defects(contours.size());

for(int i = 0; i <contours.size(); ++i){
    //find the hulls
    convexHull(contours[i], hullsI[i], false, false);
    convexHull(contours[i], hullsP[i], false, true);
    //find the defects
    if (contours[i].size() >3 ){
        convexityDefects(contours[i], hullsI[i], defects[i]);
    }
}

I do not want to use IplImage. I prefer Mat.

Og Namdik
  • 823
  • 4
  • 14
  • 22

1 Answers1

1

You can draw the result of a convex hull operation with 'cvDrawContours()', but you do need to set your parameters correct for that to be possible. I have an example but it uses 'cvConvexHull2()' and IplImages but it should work the same way for a Mat and the other convexHull operation:

IplImage* src; //the image where the contours are detected on
IplImage frm;  //the image you want the results to be drawn on

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours = NULL;
cvFindContours(src, storage, &contours, sizeof (CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
for (CvSeq* c = contours; c != NULL; c = c->h_next) {
            CvSeq* dest = NULL;
            CvMemStorage* hullStorage = cvCreateMemStorage(0);
            dest = cvConvexHull2(c, hullStorage, CV_CLOCKWISE, 1);
            cvDrawContours(frm, dest, cvScalarAll(255), cvScalarAll(255), 0, 2, 8);
            cvReleaseMemStorage(&hullStorage);
        }
cvReleaseMemStorage(&storage);
diip_thomas
  • 1,531
  • 13
  • 25
  • Do you have a sample code using Mat? I'm not very familiar with IplImage and CvSeq. – Og Namdik Oct 23 '12 at 13:29
  • You're going to have to use CvSeq anyway, but I'll check later how it works using Mat, in the meantime you can convert a Mat to IplImage* with: 'cv::Mat myMatrice;' 'IplImage myImage = myMatrice;' And back to a Mat: 'cv::Mat img(iplimg);' – diip_thomas Oct 23 '12 at 14:27