cv::convexityDefects捕捉到cv::Exception
OpenCV(4.8.0) C:\GHA-OCV-1\_work\ci-gha-workflow\ci-gha-workflow\opencv\modules\imgproc\src\convhull.cpp:360: error: (-5:Bad argument) The convex hull indices are not monotonous, which can be in the case when the input contour contains self-intersections in function 'cv::convexityDefects'
这是输入轮廓点集
通过cv::convexHull找到的凸包点索引
凸包点集
如图,蓝色为轮廓点连线,橙色数字为凸包点的序号
原因是self-intersection(自相交)的轮廓,opencv无法处理
针对这种情况,opencv会抛出异常,如果不做异常处理,会导致程序崩溃
见git上的Issue:Indices from convexHull not monotonic #4539
作者vpisarev提到了没有好的办法处理这种情况
the issue is mostly fixed. Without that 1 pixel-wide “hair” on the
contour, which can be made more thick or completely eliminated using
morphological operations, everything now works well. With this “hair”
an exception is now thrown by convexityDefects. For now I do not have
a good solution to produce a good convex hull for such a contour. It’s
not a problem of Sklansky algorithm, I believe, it’s that this
particular case can be considered as a contour with self-intersection.
A contour with self-intersection is basically not a contour, it’s
rather a generic point set, and for such a set it’s impossible to
generate a completely ordered convex hull. But at least such case is
now caught by convexityDetects instead of silently producing incorrect
results.
BTW, it’s said in several places that Sklansky algorithm is incorrect.
This is true, but only when we are talking about O(N) Sklansky
algorithm that computes convex hulls for polygons. OpenCV does not
have a function to compute convex hull for polygons. It computes
convex hull for unordered 2D point sets. The complexity is
O(N*log(N)), not O(N). And the Sklansky algorithm in OpenCV iterates
though the points in a certain sorted order, not in the original
order. So, the counter-examples, developed by Toussaint et al, are not
applicable to our implementation. I cannot claim, of course, that our
implementation is completely bug-free. I’m just saying that OpenCV
implementation does not have the same problem as the original
Skansky’82 O(N) algorithm
有的人说先对cv::convexHull输出的索引数组降序排列后再输入convexityDefects,貌似不会异常了,但这样做不符合原理
一些库里(如CGAL库、PostGIS库)里有自相交多边形(或平面)的判断和消除算法,一般思路是将自相交多边形分解为多个子形状,或者把孔洞填补了
PostGIS教程十五:几何图形的有效性
对于三角网格的自相交(self intersect)问题该如何解决?