8

I'm trying to separate the contours of an image (in order to find uniform regions) so I applied cvCanny and then cvFindContours, then I use the following code to draw 1 contour each time I press a key:

for( ; contours2 != 0; contours2 = contours2->h_next ){
        cvSet(img6, cvScalar(0,0,0));
        CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );
        cvDrawContours(img6, contours2, color, cvScalarAll(255), 100);
        //cvFillConvexPoly(img6,(CvPoint *)contours2,sizeof (contours2),color);
        area=cvContourArea(contours2);
        cvShowImage("3",img6);
        printf(" %d", area);
        cvWaitKey();
    }

But in the first iteration it draws ALL the contours, in the second it draws ALL but one, the third draws all but two, and so on.

And if I use the cvFillConvexPoly function it fills most of the screen (although as I wrote this I realized a convex polygon won't work for me, I need to fill just the insideof the contour)

So, how can I take just 1 contour on each iteration of the for, instead of all the remaining contours?

Thanks.

Gerardo Galarza
  • 167
  • 1
  • 2
  • 12

1 Answers1

13

You need to change the last parameter you are passing to the function, which is currently 100, to either 0 or a negative value, depending on whether you want to draw the children.

According to the documentation (http://opencv.willowgarage.com/documentation/drawing_functions.html#drawcontours), the function has the following signature:

void cvDrawContours(CvArr *img, CvSeq* contour, CvScalar external_color,
CvScalar hole_color, int max_level, int thickness=1, int lineType=8)

From the same docs, max_level has the following purpose (most applicable part is in bold):

max_level – Maximal level for drawn contours. If 0, only contour is drawn. If 1, the contour and all contours following it on the same level are drawn. If 2, all contours following and all contours one level below the contours are drawn, and so forth. If the value is negative, the function does not draw the contours following after contour but draws the child contours of contour up to the $|\texttt{max_ level}|-1$ level.

Edit:

To fill the contour, use a negative value for the thickness parameter:

thickness – Thickness of lines the contours are drawn with. If it is negative (For example, =CV_FILLED), the contour interiors are drawn.

maditya
  • 8,626
  • 2
  • 28
  • 28
  • Thanks a lot, that was it, I hadn't noticed that parameter. Now I just need to fill them, is there any function for that? If not, how could i go about it? maybe watershed would work for the closed ones, but sometimes there are open contours as well. – Gerardo Galarza Apr 14 '13 at 04:25
  • 1
    Use a negative value for the thickness parameter. If that doesn't work for you, maybe one of these will help: http://stackoverflow.com/questions/12929197/opencv-closing-a-shape-and-filling-it , http://stackoverflow.com/questions/1716274/fill-the-holes-in-opencv – maditya Apr 14 '13 at 06:01
  • Thanks again, Using a negative thickness does the trick perfectly. – Gerardo Galarza Apr 14 '13 at 08:12
  • Gerardo, vote up and accept this answer if it worked for you. – LovaBill Apr 15 '13 at 12:25