Ask Your Question

convexityDefects computes wrong result

Hi,

when running the following code snippet:

vector<Point> c = { { 356, 339 }, { 355, 340 }, { 353, 340 }, { 350, 343 }, { 349, 343 }, { 347, 345 }, { 344, 345 }, { 343, 346 }, { 334, 346 }, { 330, 350 }, { 331, 350 }, { 332, 351 }, { 334, 351 }, { 335, 352 }, { 336, 352 }, { 338, 354 }, { 339, 354 }, { 340, 355 }, { 340, 354 }, { 341, 353 }, { 342, 353 }, { 343, 352 }, { 344, 352 }, { 345, 351 }, { 349, 351 }, { 350, 350 }, { 352, 350 }, { 353, 349 }, { 354, 349 }, { 355, 350 }, { 356, 350 }, { 357, 351 }, { 357, 353 }, { 354, 356 }, { 354, 357 }, { 352, 359 }, { 353, 360 }, { 350, 363 }, { 350, 364 }, { 351, 365 }, { 351, 366 }, { 353, 368 }, { 353, 369 }, { 355, 371 }, { 355, 372 }, { 356, 371 }, { 356, 369 }, { 358, 367 }, { 358, 366 }, { 361, 363 }, { 361, 357 }, { 362, 356 }, { 362, 354 }, { 364, 352 }, { 364, 351 }, { 367, 348 }, { 368, 348 }, { 369, 347 }, { 367, 345 }, { 367, 343 }, { 366, 343 }, { 363, 340 }, { 359, 340 }, { 358, 339 } };

Mat img(480, 640, CV_8UC3, Scalar(0, 0, 0));
polylines( img, c, true, Scalar( 255, 0, 0 ), 1 );

vector<int> h;
convexHull( c, h );
vector<Point> hp;
for( const auto &e : h )
{
hp.push_back( c[ e ] );
}
cv::polylines( img, hp, true, Scalar( 0, 255, 0 ), 1 );

vector<Vec4i> d;
convexityDefects( c, h, d );

for( const auto &e : d )
{
circle( img, c[ e[ 2 ] ], 1, Scalar( 0, 0, 255 ), 1 );
}


I am getting the follwing output:

h: [57, 49, 45, 44, 9, 8, 0, 63, 61, 59]

d: [[57, 59, 9, 9273], [59, 61, 60, 154], [61, 63, 62, 201], [0, 8, 5, 765], [9, 44, 30, 4397], [45, 49, 46, 271], [49, 57, 52, 801]]

I am looking for the defect that is the farthest away from the hull which is: [9, 44, 30, 4397] which is located at the center of the image

The problem is, there is a wrong result: [57, 59, 9, 9273] which is even further away. In the image this wrong result is the the most left cross which is located on the hull and should have a depth of 0 and not 9273

Am I doing something wrong or is this a bug?

Thanks Chris

Edit: I created this bug report over there: click

edit retag close merge delete

Comments

but how are you trying to find the distance between the hull and the defects?

( 2015-03-14 16:03:18 -0500 )edit

convexityDefects() already computes the distance of the defect from the hull, its index 3 of the result Vec4i

( 2015-03-15 14:30:17 -0500 )edit

@Christoph Pacher you are right. Check my answer below.

( 2015-03-15 18:19:27 -0500 )edit

1 answer

Sort by » oldest newest most voted

According to the documentation:

convexityDefects – The output vector of convexity defects. In C++ and the new Python/Java interface each convexity defect is represented as 4-element integer vector (a.k.a. cv::Vec4i): (start_index, end_index, farthest_pt_index, fixpt_depth), where indices are 0-based indices in the original contour of the convexity defect beginning, end and the farthest point, and fixpt_depth is fixed-point approximation (with 8 fractional bits) of the distance between the farthest contour point and the hull. That is, to get the floating-point value of the depth will be fixpt_depth/256.0.

So your code and what you are doing is more or less correct. However, your extracted indices from the convexHull() function call are not in the correct order. You need to call it as follows:

convexHull( c, h, true );

then you will obtain the desired result ;-). If you check the documentation for the convexHull() function the third parameter is related to the convex hull orientation. If it is true, the output convex hull is oriented clockwise. Otherwise (default), it is oriented counter-clockwise.

more

Comments

i cant find a hint for the correct ordering of the hull for convexityDefects() in the documentation. when reversing the order I get the following result:

h: [9, 44, 45, 49, 57, 59, 61, 63, 0, 8]
d: [[8, 9, 1, 2715], [9, 44, 30, 4397], [45, 49, 46, 271], [49, 57, 52, 801], [57, 59, 58, 229], [59, 61, 60, 154], [61, 63, 62, 201], [0, 8, 5, 765]]


d[0] is again a result with wrong depth: 2715 even though the point is located on the hull. its just less obvious since the value is smaller then the defect I am looking for. I already tried reversing the hull order. As far as I remember my tests, the results change depending on form of the contour, it is possible to get a wrong result with a bigger depth than the one, I am looking for.

( 2015-03-16 13:00:24 -0500 )edit

Yes ok, but the output of the convexityDefects() is not ordered according to the farthest index but I guess something related to the found hulls (i.e. h in your case here). If you want to obtain the the farthest defect you will have to loop through your detected defects and compare them according to index 3 of the result Vec4i. As you can see then you will get easily which defect is farthest from its corresponding hull, which here is located at the d[1] position.

( 2015-03-16 15:27:38 -0500 )edit

please read my comments. I already tried inverting the hull ordering and got results from other contours where a wrong defect has a larger depth than the defect I am looking for. And even for the example i posted a defect depth of 2715 for a defect that is located directly ON the hull is a completely wrong result.

( 2015-03-16 18:32:49 -0500 )edit

ok I see your point now. It seems to be a bug, and for sure does not look like a normal behaviour. Try to make a bug report here. Just out of curiosity which version of opencv are you running. I am running the master branch of v3.0.0 from the github source.

( 2015-03-16 18:55:17 -0500 )edit
1

A am using a checkout from the master branch from 4 months ago. Thanks I will file a report.

( 2015-03-17 11:32:16 -0500 )edit

Stats

Asked: 2015-03-13 13:37:52 -0500

Seen: 592 times

Last updated: Mar 21 '15