trouver des défauts de convexité dans l’opencv?

J’ai un programme qui calcule la shell convexe d’une image. J’essaie d’utiliser cette information pour compter le nombre de doigts présents dans une image d’entrée. En surfant, j’ai découvert que la manière de le faire (compter les doigts) est de

  1. Trouver des contours
  2. Enveloppe convexe
  3. Défauts de convexité

Mais j’ai du mal à utiliser la fonction de défaut de convexité. Il comstack bien mais au moment de l’exécution, le programme se bloque avec certaines images d’entrée mais pas avec d’autres et je n’arrive pas à comprendre pourquoi.

Ce sont les images d’entrée

  1. cette image provoque un crash
  2. mais ce n’est pas le cas.
  3. cela provoque également un crash, même si son semblable à ce qui précède

code..

#include  #include  #include  #include  #define CVX_RED CV_RGB(0xff,0x00,0x00) #define CVX_GREEN CV_RGB(0x00,0xff,0x00) #define CVX_BLUE CV_RGB(0x00,0x00,0xff) int main(int argc, char* argv[]) { cvNamedWindow( "original", 1 ); cvNamedWindow( "contours", 1 ); cvNamedWindow( "hull", 1 ); IplImage* original_img = NULL; original_img = cvLoadImage("img.jpg", CV_LOAD_IMAGE_GRAYSCALE ); IplImage* img_edge = cvCreateImage( cvGetSize(original_img), 8, 1 ); IplImage* contour_img = cvCreateImage( cvGetSize(original_img), 8, 3 ); IplImage* hull_img = cvCreateImage( cvGetSize(original_img), 8, 3 ); cvThreshold( original_img, 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 ); for( CvSeq* c=first_contour; c!=NULL; c=c->h_next ) { cvCvtColor( original_img, contour_img, CV_GRAY2BGR ); cvDrawContours( contour_img, c, CVX_RED, CVX_BLUE, 0, 2, 8 ); } //----------------------------------------------------------------------Convex Hull CvMemStorage* hull_storage = cvCreateMemStorage(); CvSeq* retHulls = NULL; for(CvSeq* i = first_contour; i != NULL; i = i->h_next){ retHulls = cvConvexHull2(i,hull_storage,CV_CLOCKWISE,0); // with 1 it draws the Hull image but not with 0..? // however it needs to be 0 for convexitydefects to work? } printf(" %d elements:\n", retHulls->total ); // drawing hull for( CvSeq* j=retHulls; j!=NULL; j=j->h_next ) { cvCvtColor( original_img, hull_img, CV_GRAY2BGR ); cvDrawContours( hull_img, j, CVX_RED, CVX_BLUE, 0, 2, 8 ); } //----------------------------------------------------------------------Convexity Defects?? CvMemStorage* convexStorage = cvCreateMemStorage(); CvSeq* defect = NULL; defect = cvConvexityDefects(first_contour,retHulls, convexStorage); printf(" %d defect:\n", defect->total ); cvShowImage( "contours", contour_img ); cvShowImage( "original", original_img ); cvShowImage( "hull", hull_img ); cvWaitKey(0); cvDestroyWindow( "contours" ); cvDestroyWindow( "original" ); cvDestroyWindow( "hull" ); cvReleaseImage( &original_img ); cvReleaseImage( &contour_img ); cvReleaseImage( &hull_img ); cvReleaseImage( &img_edge ); return 0; } 

cvConvexityDefects s’attend à ce que la séquence convexHull (second argument) contienne des index dans la séquence de contour (premier argument):

Coque convexe obtenue à l’aide de ConvexHull2 qui devrait contenir des pointeurs ou des index vers les points de contour, pas les points de shell eux-mêmes

  1. Dans le cas le plus sortingvial, où cvFindContours renvoie un seul contour simple (votre deuxième image), vous avez de la chance et votre code fournira la séquence correcte en tant que premier paramètre.

  2. cvFindContours trouve des trous dans le contour (votre troisième image), ou s’il existe plusieurs contours simples ou des contours avec des trous (votre première image), votre code:

    1. trouve tour à tour une shell convexe de chaque contour, mais ne retient que le dernier (chaque itération de la boucle écrasant la variable retHulls )

    2. passe la totalité de la hiérarchie des contours, qui ne correspond pas aux index dans retHulls , à cvConvexityDefects tant que premier argument.

Au lieu de cela, vous devriez avoir:

  1. passé CV_RETR_EXTERNAL à cvFindContour pour obtenir uniquement les contours extérieurs (vous ne vous occupez pas des défauts de trous)

  2. déplacé le cvConvexityDefects dans la dernière boucle.

Quelque chose comme:

  /* ... */ if (argc < 2) { std::cerr << "Usage: convexity IMAGE\n"; exit(1); } cvNamedWindow( "original", 1 ); cvNamedWindow( "contours", 1 ); cvNamedWindow( "hull", 1 ); IplImage* original_img = NULL; original_img = cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE ); IplImage* img_edge = cvCreateImage( cvGetSize(original_img), 8, 1 ); IplImage* contour_img = cvCreateImage( cvGetSize(original_img), 8, 3 ); IplImage* hull_img = cvCreateImage( cvGetSize(original_img), 8, 3 ); cvThreshold( original_img, 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_EXTERNAL // Try all four values and see what happens ); cvCvtColor( original_img, contour_img, CV_GRAY2BGR ); for( CvSeq* c=first_contour; c!=NULL; c=c->h_next ) { cvDrawContours( contour_img, c, CVX_RED, CVX_BLUE, 0, 2, 8 ); } cvShowImage( "contours", contour_img ); //----------------------------------------------------------------------Convex Hull //-------------------------------------------------------------------Convex Defects CvMemStorage* hull_storage = cvCreateMemStorage(); CvSeq* retHulls = NULL; cvCvtColor( original_img, hull_img, CV_GRAY2BGR ); for(CvSeq* i = first_contour; i != NULL; i = i->h_next){ retHulls = cvConvexHull2(i,hull_storage,CV_CLOCKWISE,0); printf(" %d elements:\n", retHulls->total ); CvSeq* defect = NULL; defect = cvConvexityDefects(i,retHulls, NULL); // reuse storage of the contour printf(" %d defect:\n", defect->total ); // drawing hull.... you can't use the one returned above since it only // contains indices retHulls = cvConvexHull2(i,hull_storage,CV_CLOCKWISE,1); cvDrawContours( hull_img, retHulls, CVX_RED, CVX_BLUE, 0, 2, 8 ); } cvShowImage( "hull", hull_img ); /* ... */ 

L’exécution de votre application avec les images problématiques le bloque, mais je ne vois aucun crash avec OpenCV 2.4.2, et le problème se produit réellement à cvConvexityDefects() , selon gdb :

 (gdb) bt #0 0x00000001002b1491 in cvConvexityDefects () #1 0x0000000100001a8d in main () 

Je ne peux pas vous dire pourquoi, cependant. Étant donné que les parameters semblent corrects, vous pouvez enregistrer un nouveau problème ici .