发现凸性缺陷的OpenCV? [崩溃根据给定的输入图像上.. [英] finding convexity defects in opencv? [crashes depending on the given input image..]

查看:284
本文介绍了发现凸性缺陷的OpenCV? [崩溃根据给定的输入图像上..的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有计算的图像的凸包的程序。我试图用这个信息来算的手指的数量的是在输入图像present。从一些冲浪我发现的方式通过

做到这一点(算上手指)是

  1. 查找轮廓

  2. 凸包

  3. 凸性缺陷

但我使用的凸性缺陷的功能有问题。它编译罚款,但在运行该程序具有一定的输入图像,但不与他人崩溃,我似乎无法找出原因。

这是输入图像


  1. 这个图像会导致系统崩溃

  2. 这个没有。

  3. 也导致系统崩溃,即使其类似于上面

code ..

 的#include< OpenCV的/ cv.h>
#包括LT&; OpenCV的/ highgui.h>
#包括LT&; OpenCV的/ cxcore.h>
#包括LT&;&stdio.h中GT;#定义CVX_RED CV_RGB(0xFF的,0x00,0x00)
#定义CVX_GREEN CV_RGB(0x00,0xff,0×00)
#定义CVX_BLUE CV_RGB(0x00,0x00,0xff)INT主(INT ARGC,CHAR *的argv []){  cvNamedWindow(原始,1);
  cvNamedWindow(轮廓,1);
  cvNamedWindow(皮壳,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 *存储= cvCreateMemStorage();
  CvSeq * first_contour = NULL;  INT NC = cvFindContours(
     img_edge,
     存储,
     &安培; first_contour,
     的sizeof(CvContour)
     CV_RETR_LIST //尝试所有四个价值观,看看会发生什么
  );  对于(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
     );
  }  // ------------------------------------------------ ----------------------凸包  CvMemStorage * hull_storage = cvCreateMemStorage();
  CvSeq * retHulls = NULL;  对于(CvSeq * I = first_contour;!我= NULL; I = I-> h_next){
    retHulls = cvConvexHull2(ⅰ,hull_storage,CV_CLOCKWISE,0);
    // 1它绘制图像赫尔但不与0 ..?
    //然而它需要0 convexitydefects工作?
  }  的printf(%d个要素:\\ n,retHulls-个总);  //绘制船体  为(CvSeq * J = retHulls;!J = NULL; J = J-> h_next){
    cvCvtColor(original_img,hull_img,CV_GRAY2BGR);
    cvDrawContours(
        hull_img,
        Ĵ,
        CVX_RED,
        CVX_BLUE,
        0,
        2,
        8
     );  }
  // ------------------------------------------------ ----------------------凸缺陷?  CvMemStorage * convexStorage = cvCreateMemStorage();
  CvSeq *缺陷= NULL;
  缺陷= cvConvexityDefects(first_contour,retHulls,convexStorage);
  的printf(%d个缺陷:\\ n,基于缺陷个总);
  cvShowImage(轮廓,contour_img);
  cvShowImage(原始,original_img);
  cvShowImage(壳,hull_img);
  cvWaitKey(0);
  cvDestroyWindow(轮廓);
  cvDestroyWindow(原始);
  cvDestroyWindow(船体);
  cvReleaseImage(安培; original_img);
  cvReleaseImage(安培; contour_img);
  cvReleaseImage(安培; hull_img);
  cvReleaseImage(安培; img_edge);
  返回0;
}


解决方案

cvConvexityDefects 期望凸形轮廓序列(第二参数)包含指数到轮廓序列(第一个参数):


  使用ConvexHull2应包含指针或索引到轮廓点获得

凸包,而不是船体点本身



  1. 在最简单的情况,其中 cvFindContours 返回一个简单的轮廓(第二个图像),你很幸运,你的code将提供正确的序列作为第一个参数。


  2. 在案件 cvFindContours 中发现的轮廓孔(你的第三个图像),或者如果有几个简单的轮廓或轮廓与孔(你的第一个图像)的code:


    1. 查找依次在每个轮廓的凸包,但只记得最后一个(因为循环重写的每个迭代 retHulls 变量)


    2. 通过轮廓的整个层次,这不符合指标的 retHulls ,到 cvConvexityDefects 作为第一个参数。



相反,你应该有:


  1. 通过 CV_RETR_EXTERNAL cvFindContour 只获取外部轮廓(你不关心孔缺陷)


  2. 移动 cvConvexityDefects 最后的循环中。


是这样的:

  / * ... * /  如果(的argc 2){
      的std :: CERR<< 用法:凸图片\\ n;
      出口(1);
  }  cvNamedWindow(原始,1);
  cvNamedWindow(轮廓,1);
  cvNamedWindow(皮壳,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 *存储= cvCreateMemStorage();
  CvSeq * first_contour = NULL;  INT NC = cvFindContours(
     img_edge,
     存储,
     &安培; first_contour,
     的sizeof(CvContour)
     CV_RETR_EXTERNAL //尝试所有四个价值观,看看会发生什么
  );  cvCvtColor(original_img,contour_img,CV_GRAY2BGR);
  对于(CvSeq * C = first_contour;!C = NULL; C = C-> h_next){
     cvDrawContours(
        contour_img,
        C,
        CVX_RED,
        CVX_BLUE,
        0,
        2,
        8
     );
  }
  cvShowImage(轮廓,contour_img);  // ------------------------------------------------ ----------------------凸包
  // ------------------------------------------------ -------------------凸状缺陷  CvMemStorage * hull_storage = cvCreateMemStorage();
  CvSeq * retHulls = NULL;  cvCvtColor(original_img,hull_img,CV_GRAY2BGR);
  对于(CvSeq * I = first_contour;!我= NULL; I = I-> h_next){
    retHulls = cvConvexHull2(ⅰ,hull_storage,CV_CLOCKWISE,0);
    的printf(%d个要素:\\ n,retHulls-个总);    CvSeq *缺陷= NULL;
    缺陷= cvConvexityDefects(ⅰ,retHulls,NULL); //轮廓的重用存储
    的printf(%d个缺陷:\\ n,基于缺陷个总);    //绘制船体....你不能使用,因为它一个上面只返回
    //包含指数
    retHulls = cvConvexHull2(ⅰ,hull_storage,CV_CLOCKWISE,1);
    cvDrawContours(
        hull_img,
        retHulls,
        CVX_RED,
        CVX_BLUE,
        0,
        2,
        8
     );
  }  cvShowImage(壳,hull_img);
  / * ... * /

I have a program that calculates the convex hull of an image. I'm trying to use this information in order to count the number of fingers that are present in an input image. From some surfing I found out that the way to do this (count fingers) is by

  1. Finding contours
  2. Convex Hull
  3. Convexity defects

But I'm having trouble using the convexity defects function. It compiles fine but at runtime the program crashes with certain input images but not with others and I can't seem to figure out why.

These are the input images

  1. this image causes a crash
  2. but this does not.
  3. this also causes a crash even though its similar to the above

code..

#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv/cxcore.h>
#include <stdio.h>

#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 expects the convexHull sequence (second argument) to contain indices into the contour sequence (first argument):

Convex hull obtained using ConvexHull2 that should contain pointers or indices to the contour points, not the hull points themselves

  1. In the most trivial case, where cvFindContours returns a single simple contour (your second image) you got lucky and your code would supply the correct sequence as the first parameter.

  2. In case cvFindContours finds holes in the contour (your third image), or if there are several simple contours or contours with holes (your first image) your code:

    1. finds a convex hull of each contour in turn, but only remembers the last one (since each iteration of the loop overwrites retHulls variable)

    2. passes the whole hierarchy of the contours, which doesn't correspond to indices in retHulls, to cvConvexityDefects as the first argument.

Instead, you should have:

  1. passed CV_RETR_EXTERNAL to the cvFindContour to only get the outer contours (you don't care for defects of holes)

  2. moved the cvConvexityDefects inside the last loop.

Something like:

  /* ... */

  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 );
  /* ... */

这篇关于发现凸性缺陷的OpenCV? [崩溃根据给定的输入图像上..的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆