如何将轮廓层次结构从 python openCV 转换为 emgu cv 以查找封闭轮廓

Posted

技术标签:

【中文标题】如何将轮廓层次结构从 python openCV 转换为 emgu cv 以查找封闭轮廓【英文标题】:How to convert contour hierarchy from python openCV to emgu cv to find enclosing contours 【发布时间】:2021-09-23 11:36:21 【问题描述】:

我有一个用 python 编写的圆形检测,现在我需要将其转换为 emgu cv 以启用捆绑到 Xamarin ios 应用程序中。

为此,我在各个部分保存了检测过程的图像,以将其与新的 .net 实现进行比较。虽然有些部分是直截了当的,但其他部分似乎更棘手。我目前停留在检测到形状的层次结构中,并且已经检查了示例以及 this answer,然后我将其选为第一个解决方案。

这是我尝试转换的 python 行:

# finding all contours in the image which are enclosed within other contours (child contours)
( cnts, cnts_hs ) = cv2.findContours(img.copy(), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) 
cnts = [cnt for i,cnt in enumerate(cnts) if cnts_hs[0,i,3] != -1]

目前我使用上述答案进行了尝试,结果如下:

// finding all contours in the image which are enclosed within other contours (child contours)
// NOTE: 
// 'hier' is of type 'Mat'
// 'cnts' 'cntsContourOut' are both of type 'VectorOfVectorOfPoint'
CvInvoke.FindContours(img.Clone(), cnts, hier, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
int count = cnts.Size;
for (int i = 0; i < count; i++)

    using (VectorOfPoint cntr = cnts[i]) 
        // check if the contour is enclosed in another contour
        if (hier.GetDataPointer(i).ToInt32() != -1)
        
            cntsContourOut.Push(cntr);
        
    

但结果完全不同......虽然在过滤给定的样本图像后,python 线会产生 49 个轮廓,但 .net 线会产生原始的 91 个轮廓(没有一个被过滤掉)。 我想我对 python 行的作用有一些误解,当涉及到cnts_hs[0,i,3] 中的03 时,我仍然有这种误解。这就是我在 .net 实现中将它们排除在外的原因。

编辑1:

我想我应该提到我为hier.GetDataPointer() 尝试了以下参数变体:

hier.GetDataPointer(0,i,3)
// result in an array size exceeded exception

hier.GetDataPointer(i,3) // or even 4 instead of 3
// result in the same 91 contours

【问题讨论】:

在 Python 中,cnts_hs 是一个形状为 [1, #contours, 4] 的数组。第一个维度是单例维度,仅在其他 OpenCV 函数中使用时方便使用。最后一个维度中的四个值在documentation 中进行了解释。当使用链接问答中的确切实现时,即Get(HierarchyIndex component, int index),您很可能需要if (Get(i, 3) == -1)(或Get(i, 4),如果使用基于1的索引)。 @HansHirse 感谢您的评论。我必须承认,链接的答案只是使我采用了当前的方法,而对详细情况一无所知。 GetDataPointer(int[]) 接受我已经尝试过的整数数组(我应该从一开始就提到这一点。我现在将它作为编辑 1 添加到问题中)。所描述的Get(HierarchyIndex component, int index) 不可用或者直到现在我还没有找到它... 【参考方案1】:

经过一番深入研究,我找到了解决方案:

var data = hier.GetData();
for (int i = 0; i < count; i++)

    using (VectorOfPoint cntr = cnts[i]) 
        var d = (int)data.GetValue(new int[3]  0, i, 3 );
        if(d != -1)
            cntsContourOut.Push(cntr);
    

【讨论】:

以上是关于如何将轮廓层次结构从 python openCV 转换为 emgu cv 以查找封闭轮廓的主要内容,如果未能解决你的问题,请参考以下文章

opencv 9 -- 轮廓 层次结构

opencv 9 -- 轮廓 层次结构

opencv中的重复轮廓

在opencv中使用霍夫变换检测垂直线

OpenCV-Python教程:22.轮廓层级

OpenCV竟然可以这样学!成神之路终将不远(二十一)