【问题标题】:opencv find perimeter of a connected componentopencv查找连接组件的周长
【发布时间】:2016-06-10 09:56:05
【问题描述】:

我正在使用 opencv 2.4.13

我正在尝试查找连接组件的周长,我正在考虑使用ConnectedComponentWithStats,但它不返回周长,只返回面积、宽度等... 有一种方法可以找到具有轮廓但不是相反的区域(我的意思是一个组件,而不是整个图像)。

arcLength 方法效果不佳,因为我拥有组件的所有点,而不仅仅是轮廓。

我知道有一种 BF 方法可以通过遍历组件的每个像素并查看他是否有不在同一个组件中的邻居来找到它。但我想要一个成本更低的功能。 否则,如果您知道一种将组件与 findContours 方法找到的轮廓链接的方法,那么它也适合我。

谢谢

【问题讨论】:

  • 轮廓和连通分量没有区别,你能上传你的输入图像吗?
  • 连通分量也有轮廓内的像素没有?

标签: c++ opencv connected-components


【解决方案1】:

添加到@Miki 的答案,这是查找连接组件周长的更快方法

//getting the connected components with statistics
cv::Mat1i labels, stats;
cv::Mat centroids;

int lab = connectedComponentsWithStats(img, labels, stats, centroids);

for (int i = 1; i < lab; ++i)
{
    //Rectangle around the connected component
    cv::Rect rect(stats(i, 0), stats(i, 1), stats(i, 2), stats(i, 3));

    // Get the mask for the i-th contour
    Mat1b mask_i = labels(rect) == i;

    // Compute the contour
    vector<vector<Point>> contours;     
    findContours(mask_i, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

    if(contours.size() <= 0)
         continue;        

    //Finding the perimeter
    double perimeter = contours[0].size();
    //you can use this as well for measuring perimeter
    //double perimeter = arcLength(contours[0], true);

}

【讨论】:

    【解决方案2】:

    最简单的可能是使用findContours

    您可以计算由 connectedComponents(WithStats) 计算的第 i 个组件的轮廓,因此它们与您的标签对齐。使用CHAIN_APPROX_NONE,您将获得轮廓中的所有点,因此矢量的size() 已经是周长的度量。您最终可以使用arcLength(...) 来获得更准确的结果:

    Mat1i labels;
    int n_labels = connectedComponents(img, labels);
    
    for (int i = 1; i < n_labels; ++i)
    {
        // Get the mask for the i-th contour
        Mat1b mask_i = labels == i;
    
        // Compute the contour
        vector<vector<Point>> contours;     
        findContours(mask_i.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    
        if (!contours.empty())
        {
            // The first contour (and probably the only one)
            // is the one you're looking for
    
            // Compute the perimeter
            double perimeter_i = contours[0].size();
        }
    }
    

    【讨论】:

    • 好的,我不知道我可以在带有遮罩的特定组件上使用 findContours,谢谢!
    • 问题:你为什么使用 mask_i.clone() ? mask_i 还不够吗?
    • FindContours 会损坏输入图像。如果以后不需要掩码,可以避免clone()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 2015-05-20
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    相关资源
    最近更新 更多