发现凸性缺陷的OpenCV? [崩溃根据给定的输入图像上.. [英] finding convexity defects in opencv? [crashes depending on the given input image..]
问题描述
我有计算的图像的凸包的程序。我试图用这个信息来算的手指的数量的是在输入图像present。从一些冲浪我发现的方式通过
做到这一点(算上手指)是- 查找轮廓
- 凸包
- 凸性缺陷
但我使用的凸性缺陷的功能有问题。它编译罚款,但在运行该程序具有一定的输入图像,但不与他人崩溃,我似乎无法找出原因。
这是输入图像
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应包含指针或索引到轮廓点获得凸包,而不是船体点本身
块引用>
在最简单的情况,其中
cvFindContours
返回一个简单的轮廓(第二个图像),你很幸运,你的code将提供正确的序列作为第一个参数。在案件
cvFindContours
中发现的轮廓孔(你的第三个图像),或者如果有几个简单的轮廓或轮廓与孔(你的第一个图像)的code:
查找依次在每个轮廓的凸包,但只记得最后一个(因为循环重写的每个迭代
retHulls
变量)通过轮廓的整个层次,这不符合指标的
retHulls
,到cvConvexityDefects
作为第一个参数。相反,你应该有:
通过
CV_RETR_EXTERNAL
到cvFindContour
只获取外部轮廓(你不关心孔缺陷)移动
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
- Finding contours
- Convex Hull
- 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
- this image causes a crash
- but this does not.
- 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 theconvexHull
sequence (second argument) to contain indices into thecontour
sequence (first argument):Convex hull obtained using ConvexHull2 that should contain pointers or indices to the contour points, not the hull points themselves
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.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:
finds a convex hull of each contour in turn, but only remembers the last one (since each iteration of the loop overwrites
retHulls
variable)passes the whole hierarchy of the contours, which doesn't correspond to indices in
retHulls
, tocvConvexityDefects
as the first argument.Instead, you should have:
passed
CV_RETR_EXTERNAL
to thecvFindContour
to only get the outer contours (you don't care for defects of holes)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屋!