Convex calculation Defects using OpenCV 2.4 in C ++

I am using OpenCV 2.4 to compute the convex hull of an image.

I also do some processing to remove some noise from the image, which is not relevant to the issue.

The code for calculating the convex hull is as follows:

... 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 ); } ... 

Having both a convex hull and contours, I now want to calculate the convexity of the Hull (s) defects, which, looking at the opencv documentation, I thought it would be like this:

 cv::Vec4i defects; convexityDefects(cv::Mat(contours), hull, defects); 

By doing this, I get this error:

 OpenCV Error: Assertion failed (ptnum > 3) in convexityDefects, file ./opencv/opencv/modules/imgproc/src/contours.cpp, line 1969 

Any ideas on what I'm doing wrong when using Defects bulge?

Opencv convexityDefects documentation

Thanks in advance.

UPDATE

Thanks to Innuendo's answer, I updated the main loop code to:

 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]); } 

Using this error, I get the following message:

 OpenCV Error: Assertion failed (hull.checkVector(1, CV_32S) > 2) in convexityDefects 
+4
source share
4 answers

From the openCV wiki:

Finds defects in the convexity of the contour.

So you should include it in your loop.

 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]); } 

Also, as you mentioned, the wiki says:

case - output convex case. This is either an integer index vector or a point vector. In the first case, hull elements are based on 0 indices of convex hull points in the original array (since the set of convex hull points is a subset of the original point set). in the second case, the hull elements are the convex points of the hull themselves.

+4
source

For those who do not read comments or see a solution, you should use:

vector<cv::vector<int> >hull;

to create a case instead of:

vector<cv::vector<Point> >hull;

how bulge Defects only works on cases stored as a series of indices, not on a series of points.

Unfortunately, this gives another problem: drawContours only draws contours stored as a series of points, and not as a series of indices! Therefore, if you want to paint your cases at a later stage, you may want to create 2 stores when you find the cases, one for drawing and one for detecting defects. Something like the following works:

  // 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]); } 

It might be more efficient to use a different method for drawing cases, rather than calculating them twice, but this was the most elegant way I've seen it.

Also, I still get C / C ++ freezing (Java guy), but I believe that if you add using namespace cv to the beginning of the code you can save to have cv :: in the whole code.

Hopefully I did not step on Innuendo's nose, and not on my intention at all, if I have.

+4
source

I had the same error for a while until a solution was presented to me. Just check the size of contours[i] before calling convexityDefects

 /// 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]); } } 

Hope this helps :)

+2
source

I had problems as mentioned above, but finally I wrote the correct one :)

 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++; } } 
+2
source

Source: https://habr.com/ru/post/1412803/


All Articles