Another Contour Example

In this example, we find contours on an input image and then proceed to draw them one by one. This is a good example to tinker with on your own to explore the effects of changing either the contour finding mode (CV_RETR_LIST in the code) or the max_depth that is used to draw the contours (0 in the code). If you set max_depth to a larger number, notice that the example code steps through the contours returned by cvFindContours() by means of h_next. Thus, for some topologies (CV_RETR_TREE, CV_RETR_CCOMP, etc.), you may see the same contour more than once as you step through. See Example 8-3.

Example 8-3. Finding and drawing contours on an input image

int main(int argc, char* argv[]) {

  cvNamedWindow( argv[0], 1 );

  IplImage* img_8uc1 = cvLoadImage( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
  IplImage* img_edge = cvCreateImage( cvGetSize(img_8uc1), 8, 1 );
  IplImage* img_8uc3 = cvCreateImage( cvGetSize(img_8uc1), 8, 3 );

  cvThreshold( img_8uc1, img_edge, 128, 255, CV_THRESH_BINARY );

  CvMemStorage* storage = cvCreateMemStorage();
  CvSeq* first_contour  = NULL;
  int Nc = cvFindContours(
    img_edge,
    storage,
    &first_contour,
    sizeof(CvContour),
    CV_RETR_LIST // Try all four values and see what happens
 );

 int n=0;
 printf( "Total Contours Detected: %d\n", Nc );
 for( CvSeq* c=first_contour; c!=NULL; c=c->h_next ) {
   cvCvtColor( img_8uc1, img_8uc3, CV_GRAY2BGR );
   cvDrawContours(
     img_8uc3,
     c,
     CVX_RED,
     CVX_BLUE,
     0,        // Try different values of max_level, and see what happens
     2,
     8
   );
   printf("Contour #%d\n", n );
   cvShowImage( argv[0], img_8uc3 );
   printf(" %d elements:\n", c->total );
   for( int i=0; i<c->total; ++i ) {
   CvPoint* p = CV_GET_SEQ_ELEM( CvPoint, c, i );
     printf(" (%d,%d)\n", p->x, p->y );
   }
   cvWaitKey(0);
   n++;
  }

  printf("Finished all contours.\n");
  cvCvtColor( img_8uc1, img_8uc3, CV_GRAY2BGR );
  cvShowImage( argv[0], img_8uc3 );
  cvWaitKey(0);

  cvDestroyWindow( argv[0] );
 
  cvReleaseImage( &img_8uc1 );
  cvReleaseImage( &img_8uc3 );
  cvReleaseImage( &img_edge );

  return 0;
 }