凸缺陷 C++ OpenCv
Posted
技术标签:
【中文标题】凸缺陷 C++ OpenCv【英文标题】:Convexity defects C++ OpenCv 【发布时间】:2011-10-12 00:10:57 【问题描述】:如果您能帮我解决这个问题,我将不胜感激:)
关于这个问题cvConvexityDefects in OpenCV 2.X / C++?,我也有同样的问题。 OpenCV C++ wrapper 没有 C 版本中出现的函数 cvConvexityDefects,所以我尝试编写自己的版本。
部分代码是(请注意countour和hull都是向量
CvSeq* contourPoints;
CvSeq* hullPoints;
CvSeq* defects;
CvMemStorage* storage;
CvMemStorage* strDefects;
CvMemStorage* contourStr;
CvMemStorage* hullStr;
CvConvexityDefect *defectArray = 0;
strDefects = cvCreateMemStorage();
defects = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq),sizeof(CvPoint), strDefects );
//We start converting vector<Point> resulting from findContours
contourStr = cvCreateMemStorage();
contourPoints = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), contourStr);
printf("Metiendo valores\n");
for(int i=0; i<(int)contour.size(); i++)
CvPoint cp = contour[i].x, contour[i].y;
cvSeqPush(contourPoints, &cp);
//Now, the hull points obtained from convexHull c++
hullStr = cvCreateMemStorage(0);
hullPoints = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), hullStr);
for(int i=0; i<(int)hull.size(); i++)
CvPoint cp = hull[i].x, hull[i].y;
cvSeqPush(hullPoints, &cp);
//And we compute convexity defects
storage = cvCreateMemStorage(0);
defects = cvConvexityDefects(contourPoints, hullPoints, storage);
输出为Convex hull must represented as a sequence of indices or sequence of pointers in function cvConvexityDefects
。我真的不知道如何以正确的方式进行转换,我一直在网上搜索并尝试改编/复制/理解一些代码,但它总是使用 C 语法。
我希望我很清楚。提前谢谢!
【问题讨论】:
因为你是用C++写的,所以不适合标记C。 对不起,我放了 C 标签,因为我发布的是 C 代码,我想为 C++ 的 cvConvexityDefects 做某种包装 @cabreracanal 嘿,我在类似的领域遇到了问题,你能看看这里吗***.com/questions/12526179/… 【参考方案1】:我提出这个问题是因为我无法找到解决方案(不仅仅是今天我在处理这件事嘿嘿),但毕竟我能够解决这个问题!
我不得不改变计算凸包的方式,使用索引数组形式。所以现在我们有一个向量 而不是一个向量。
这是我使用的代码(它可以在图像上绘制点):
void HandDetection::findConvexityDefects(vector<Point>& contour, vector<int>& hull, vector<Point>& convexDefects)
if(hull.size() > 0 && contour.size() > 0)
CvSeq* contourPoints;
CvSeq* defects;
CvMemStorage* storage;
CvMemStorage* strDefects;
CvMemStorage* contourStr;
CvConvexityDefect *defectArray = 0;
strDefects = cvCreateMemStorage();
defects = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq),sizeof(CvPoint), strDefects );
//We transform our vector<Point> into a CvSeq* object of CvPoint.
contourStr = cvCreateMemStorage();
contourPoints = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), contourStr);
for(int i=0; i<(int)contour.size(); i++)
CvPoint cp = contour[i].x, contour[i].y;
cvSeqPush(contourPoints, &cp);
//Now, we do the same thing with the hull index
int count = (int)hull.size();
//int hullK[count];
int* hullK = (int*)malloc(count*sizeof(int));
for(int i=0; i<count; i++)hullK[i] = hull.at(i);
CvMat hullMat = cvMat(1, count, CV_32SC1, hullK);
//We calculate convexity defects
storage = cvCreateMemStorage(0);
defects = cvConvexityDefects(contourPoints, &hullMat, storage);
defectArray = (CvConvexityDefect*)malloc(sizeof(CvConvexityDefect)*defects->total);
cvCvtSeqToArray(defects, defectArray, CV_WHOLE_SEQ);
//printf("DefectArray %i %i\n",defectArray->end->x, defectArray->end->y);
//We store defects points in the convexDefects parameter.
for(int i = 0; i<defects->total; i++)
CvPoint ptf;
ptf.x = defectArray[i].depth_point->x;
ptf.y = defectArray[i].depth_point->y;
convexDefects.push_back(ptf);
//We release memory
cvReleaseMemStorage(contourStr);
cvReleaseMemStorage(strDefects);
cvReleaseMemStorage(storage);
这对我有用。如果您发现有问题或有其他管理方法,请告诉我!
【讨论】:
嘿只是想知道,但是为什么你在 cvConvexityDefects() 中使用 CvMat 而不是序列作为 hull 参数?谢谢。 嗨,这是因为我需要 cvConvexityDefects 某种类型的任何类型的序列(const void* convehull)和 CvMat 出现在我的脑海中,但实际上,我在网上找到的示例使用一个 CvSeq*,所以我认为你可以使用它。 谢谢。还有一个问题。与其将 hullK 设为指针,不如仅使用普通数组来实现?例如,使用“int hullK [hull.size ()]”代替你所做的工作吗?我只是想知道,因为我现在无法访问编译器,所以无法对其进行测试。 您这么说是因为注释行“//int hullK[count];”?我现在也没有 C 编译器,但是我声明数组的方式是声明动态数组的 C 方式。在实践中,在其中获取和设置元素时没有区别。不同之处在于,按照我的做法,您必须手动释放分配的内存。希望这可以帮助你:) 从 openCV 2.4 开始,有一个 C++ API 版本的方法:opencv.itseez.com/modules/imgproc/doc/…【参考方案2】:找到了一些使用 cpp convexityDefects 的直接方法。 通过convexHull 函数进行类型处理。它按类型填充,int* 返回 indizes,Point* 返回坐标。
void WorkFrame( Mat img, double minArea )
//assumption:
// img already preprocessed, threshold, gray, smooth, morphology whatever..
//get some contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( img, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );
for( int i=0; i<contours.size(); i++ )
vector<Point>& c=contours[i];
double area = contourArea( c );
if( area<minArea ) continue; //filter remaining noise
//convexHull works typedependent.
//std::vector<Point> ptHull1; //uncomment and compare to ptHull2
//convexHull( c, ptHull1 ); //convexHull is smart and fills direct coordinates
std::vector<int> ihull;
convexHull( c, ihull ); //convexHull is smart and fills in contourIndices
std::vector<Vec4i> defects;
convexityDefects( c, ihull, defects ); //expects indexed hull (internal assertion mat.channels()==1)
std::vector< Point > ptHull2;
std::vector<int>::iterator ii=ihull.begin();
while( ii!=ihull.end() )
int idx=(*ii);
ptHull2.push_back( c[idx] );
ii++;
cv::polylines( mat, c, true, Scalar( 0xCC,0xCC,0xCC ), 1 );
cv::polylines( mat, ptHull2, true, Scalar( 0xFF, 0x20, 0x20 ), 1 );
std::vector<Vec4i>::iterator d=defects.begin();
while( d!=defects.end() )
Vec4i& v=(*d); d++;
int startidx=v[0]; Point ptStart( c[startidx] );
int endidx=v[1]; Point ptEnd( c[endidx] );
int faridx=v[2]; Point ptFar( c[faridx] );
cv::circle( img, ptStart, 4, Scalar( 0x02,0x60,0xFF ), 2 );
cv::circle( img, ptEnd, 4, Scalar( 0xFF,0x60,0x02 ), 2 );
cv::circle( img, ptFar, 4, Scalar( 0x60,0xFF,0x02 ), 2 );
【讨论】:
以上是关于凸缺陷 C++ OpenCv的主要内容,如果未能解决你的问题,请参考以下文章
opencv使用convexityDefects计算轮廓凸缺陷