Calculating convexityDefects using OpenCV 2.4 in c++

荒凉一梦 提交于 2019-12-17 07:38:35

问题


I'm using OpenCV 2.4 to calculate the convex hull of a image.

I'm also doing some processing to remove some noise from the image, which is not really relevant to the question.

The code to calculate the convexHull is the following:

...
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 the convexHull and the contours I now want to calculate the convexityDefects of the hull(s), which by looking at opencv documentation I thought it would be like this:

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

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 convexityDefects?

Opencv convexityDefects documentation

Thanks in advance.

UPDATE

Thanks to Innuendo 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, the error that I now get is:

OpenCV Error: Assertion failed (hull.checkVector(1, CV_32S) > 2) in convexityDefects

回答1:


From openCV wiki :

Finds the convexity defects of a 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, in wiki is said:

hull – Output convex hull. It is either an integer vector of indices or vector of points. In the first case, the hull elements are 0-based indices of the 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, hull elements are the convex hull points themselves.




回答2:


For those who don't read the comments or didn't see it the solution is to use:

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

to create the hull instead of:

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

as convexityDefects only works on hulls stored as a series of indices rather than a series of Points.

Sadly this gives another problem as drawContours only draws contours stored as a series of Points and not as a series of indices! So if you want to draw your hulls at a later stage you may want to create 2 stores when you are finding the hulls, one for drawing and one for finding defects from. Something along the lines of 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 may be more efficient to just use a different method to draw the hulls rather than calculating them twice but this was the most elegant way I saw of doing it.

Also I'm still getting the hang of C/C++ myself (Java guy) but I believe if you add using namespace cv to the top of the code you can save having to have cv:: throughout your code.

Hope I haven't stepped on toes Innuendo, not my intention at all if I have.




回答3:


I've been having the same error for a while until the 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 it helps :)




回答4:


i had problems like mentioned above but at last i write 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++;
    }
}


来源:https://stackoverflow.com/questions/10620981/calculating-convexitydefects-using-opencv-2-4-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!