在c ++中使用OpenCV 2.4计算凸性缺陷
我使用OpenCV 2.4来计算图像的凸包。
我也在做一些处理,从图像中去除一些噪音,这与问题无关。
计算凸面的代码如下:
... cv::Mat sourceImage; // assume something is already here please cv::vector<cv::Vec4i> hierarchy; std::vector<std::vector<cv::Point> > contours; cv::findContours( sourceImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,cv::Point(0, 0)); // Find the convex hull object for each contour vector<cv::vector<cv::Point> >hull( contours.size() ); for (int i = 0; i < contours.size(); i++) { convexHull( contours[i], hull[i], false ); } ...
现在,我想通过查看opencv文档来计算凸壳缺陷的凸凸缺陷和轮廓,我认为这将是这样的:
cv::Vec4i defects; convexityDefects(cv::Mat(contours), hull, defects);
这样做,我得到这个错误:
OpenCV Error: Assertion failed (ptnum > 3) in convexityDefects, file ./opencv/opencv/modules/imgproc/src/contours.cpp, line 1969
任何想法,我在做什么错误时使用凸性Defects?
Opencv凸性缺陷文档
提前致谢。
UPDATE
感谢Innuendo回答,我更新了主循环代码:
std::vector<Vec4i> defects; vector<cv::vector<cv::Point> >hull( contours.size() ); for (int i = 0; i < contours.size(); i++) { convexHull( contours[i], hull[i], false ); convexityDefects(contours[i], hull[i], defects[i]); }
使用这个,我现在得到的错误是:
OpenCV Error: Assertion failed (hull.checkVector(1, CV_32S) > 2) in convexityDefects
来自openCV wiki:
查找轮廓的凸面缺陷。
所以你应该把它包括在你的循环中。
std::vector<Vec4i> defects; vector<cv::vector<int> >hull( contours.size() ); for (int i = 0; i < contours.size(); i++) { convexHull( contours[i], hull[i], false ); convexityDefects(contours[i], hull[i], defects[i]); }
另外,正如你所提到的,在wiki中说:
船体 – 输出凸包。 它可以是指数的整数向量或点的向量。 在第一种情况下,船体元素是原始数组中的凸包点的基于0的索引(因为凸包点集合是原始点集合的子集)。 在第二种情况下,船体元素本身就是凸包点。
对于那些没有阅读评论或没有看到它的解决scheme是使用:
vector<cv::vector<int> >hull;
创build船体而不是:
vector<cv::vector<Point> >hull;
作为凸性缺陷仅适用于存储为一系列索引而不是一系列点的shell。
可悲的是,这给另一个问题,因为drawContours只绘制存储为一系列点的轮廓,而不是一系列的索引! 所以如果你想在稍后阶段画出你的船体,你可能需要在find船体时创build2个商店,一个用于绘图,一个用于查找缺陷。 沿着以下的作品的东西:
// create storage space vector<vector<int> > hullsI(contours.size()); vector<vector<Point> > hullsP(contours.size()); vector<vector<Vec4i> > defects(contours.size()); for(int i = 0; i <contours.size(); ++i){ //find the hulls convexHull(contours[i], hullsI[i], true); convexHull(contours[i], hullsP[i], true); //find the defects convexityDefects(contours[i], hullsI[i], defects[i]); }
使用不同的方法绘制船体而不是两次计算可能会更有效率,但这是我看到的最优雅的方法。
此外,我仍然得到C / C + +自己(Java人)的吊but,但我相信,如果您添加using namespace cv
的代码顶部,你可以保存必须有cv ::整个代码。
希望我没有踩脚尖Innuendo,而不是我的意图,如果我有。
我一直有同样的错误,直到解决scheme呈现给我。 在调用凸性缺陷之前,只需检查contours[i]
的大小contours[i]
/// Find the convex hull object for each contour vector<vector<int> > hullsI(contours.size()); vector<vector<Point> > hullsP(contours.size()); vector<vector<Vec4i> > defects(contours.size()); for(int i = 0; i <contours.size(); ++i){ //find the hulls convexHull(contours[i], hullsI[i], false, false); convexHull(contours[i], hullsP[i], false, true); //find the defects if (contours[i].size() >3 ) { convexityDefects(contours[i], hullsI[i], defects[i]); } }
希望能帮助到你 :)
我有上面提到的问题,但最后我写了正确的:)
vector<vector<Point>> hull( contours.size() ); vector<vector<int> > hullsI(contours.size()); vector<vector<Vec4i>> convdefect(contours.size()); for( int i = 0; i < contours.size(); i++ ) { convexHull( Mat(contours[i]), hull[i], false); convexHull( Mat(contours[i]), hullsI[i], false); if(hullsI[i].size() > 3 ) convexityDefects(contours[i],hullsI[i],convdefect[i]); } /// Draw contours + hull results Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 ); for( int i = 0; i< contours.size(); i++ ) { size_t count = contours[i].size(); if( count <300 ) continue; //Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255)); drawContours( drawing, contours, i, Scalar(255,0,0), 1, 8, vector<Vec4i>(), 0, Point()); drawContours( drawing, hull, i, Scalar(0,0,255), 1, 8, vector<Vec4i>(), 0, Point()); } /// Draw convexityDefects for( int i = 0; i< contours.size(); i++ ) { size_t count = contours[i].size(); if( count <300 ) continue; vector<Vec4i>::iterator d=convdefect[i].begin(); while( d!=convdefect[i].end() ) { Vec4i& v=(*d); int startidx=v[0]; Point ptStart( contours[i][startidx] ); int endidx=v[1]; Point ptEnd( contours[i][endidx] ); int faridx=v[2]; Point ptFar( contours[i][faridx] ); float depth = v[3] / 256; line( drawing, ptStart, ptEnd, Scalar(0,255,0), 1 ); line( drawing, ptStart, ptFar, Scalar(0,255,0), 1 ); line( drawing, ptEnd, ptFar, Scalar(0,255,0), 1 ); circle( drawing, ptFar, 4, Scalar(0,255,0), 2 ); d++; } }