如何将轮廓层次结构从 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]
中的0
或3
时,我仍然有这种误解。这就是我在 .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 以查找封闭轮廓的主要内容,如果未能解决你的问题,请参考以下文章