【问题标题】:OpenCV: arcLength assert fails with cv::MatOpenCV:arcLength 断言失败并出现 cv::Mat
【发布时间】:2015-08-20 20:17:28
【问题描述】:

我尝试使用arcLength 计算轮廓周长。轮廓从文件中读入Mat,它只是轮廓的黑白图片。 但是,当我将此 Mat 传递给函数时,它会引发错误:

Assertion failed (curve.checkVector(2) >= 0 && (curve.depth() == CV_32F || curve.depth() == CV_32S)) in arcLength

我发现真正的原因是curve.checkVector(2) 返回-1。尽管我已阅读有关此方法的文档,但我仍然不明白如何修复此错误。
这是带有角点的测试图像 (1,1), (1,21), (21,21), (21,1)

【问题讨论】:

    标签: c++ opencv mat


    【解决方案1】:

    轮廓应该是(来自OpenCV doc):

    二维点的输入向量,存储在 std::vector 或 Mat 中。

    不是黑白图像。

    您可以通过不同的方式计算周长。最强大的是使用findContours 仅查找外部轮廓(RETR_EXTERNAL),并在该轮廓上调用arcLength

    几个例子:

    #include <opencv2\opencv.hpp>
    #include <vector>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
        Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
    
        // Method 1: length of unsorted points
        // NOTE: doesn't work!
    
        vector<Point> points;
        findNonZero(img, points);
        double len1 = arcLength(points, true);
        // 848.78
    
        // Method 2: length of the external contour
    
        vector<vector<Point>> contours;
        findContours(img.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); // Retrieve only external contour
        double len2 = arcLength(contours[0], true);
        // 80
    
    
    
        // Method 3: length of convex hull of contour
        // NOTE: convex hull based methods work reliably only for convex shapes.
    
        vector<Point> hull1;
        convexHull(contours[0], hull1);
        double len3 = arcLength(hull1, true);
        // 80
    
        // Method 4: length of convex hull of unsorted points
        // NOTE: convex hull based methods work reliably only for convex shapes.
    
        vector<Point> hull2;
        convexHull(points, hull2);
        double len4 = arcLength(hull2, true);
        // 80
    
    
        // Method 5: number of points in the contour
        // NOTE: this will simply count the number of points in the contour.
        // It works only if: 
        //     1) findContours was used with option CHAIN_APPROX_NONE.
        //     2) the contours is thin (has thickness of 1 pixel).
    
        double len5 = contours[0].size(); 
        // 80
    
        return 0;
    }
    

    【讨论】:

    • 这样去掉了断言错误,但是结果不正确。我创建了一个正方形轮廓,每边等于 20,我得到的答案是 848.784,不过应该是 80。我也不明白其他点如何存储在 Mat 中。
    • 我刚刚查看了积分顺序,似乎需要对它们进行排序。我稍后会返回结果
    • 太棒了!我必须说我考虑过寻找轮廓但没有选择正确的配置常数。 还有一点更重要。凸面将并不总是正常工作,因为可能有更复杂的轮廓(我也有这样的图像)。我也不太确定最后一种方法 5 是否适用于其他示例,例如三角形。因此,我建议您在答案中添加评论,我会将您的答案标记为已接受。
    • @Anjenson 我以为您只有您发布的图片。正如您所说,一般而言,并非每种方法都能奏效。因此添加了一些 cmets 来澄清这一点。让我知道现在是否更清楚了。
    猜你喜欢
    • 1970-01-01
    • 2017-12-24
    • 2023-03-23
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 2019-05-04
    • 2023-03-27
    相关资源
    最近更新 更多