当它们的边缘相互接触时,如何检测不同的对象?

信息处理 图像处理 边缘检测
2022-01-14 00:14:53

我需要找到从相机检索到的图像中的所有轮廓。所以我先用canny边缘检测器找边缘,然后找轮廓。很简单。

但是,我的轮廓被“合并”了。例如,在下图中,我显然有 4 个不同的对象。不过,边缘在某些点略有接触,所以我得到一个大轮廓而不是四个独立的轮廓。我尝试改变阈值、侵蚀、形态操作和类似的东西,但边缘保持轻微接触。有没有人对如何在类似于下图的图像中获得单独的轮廓有任何建议?(下图显然只是一个例子,我的实际图像要复杂得多,但基本问题相同)。

在此处输入图像描述

4个回答

检测不同的组件:

如果您尝试检测不同的组件,除了检测轮廓之外,可能还有其他方法可以做到这一点。这是 Mathematica 中的一个示例。腐蚀后膨胀用于在检测之前关闭第二个组件中的间隙(如果您不这样做,它将不会检测到它)。

img = Binarize@Import["http://i.stack.imgur.com/yqDyu.png"];
Colorize[MorphologicalComponents[Dilation[Erosion[img,1],1]]]

下图左图显示了不完美的对象检测(没有缩小差距),右图显示了正确的检测(运行上述代码)。

在此处输入图像描述 在此处输入图像描述

检测不同的轮廓:

但是,如果您确实只想分离轮廓,这里有一个例子。像以前一样执行腐蚀和膨胀以缩小间隙,并且生成的图像通过 Canny 边缘检测器运行。我已经明确了默认选项,以便您可以看到正在使用的内容。

img2 = EdgeDetect[Dilation[Erosion[img, 1], 1], Method -> "Canny"]

这将为您提供内部和外部边缘(见左下图),因为像素宽度在周围都大于 1。由于性能下降(可能与您的其他图像不同),我没有太多运气试图让它更薄。内轮廓是您想要的轮廓,外轮廓只是所有 4 个组件的组合轮廓。现在我们需要做的就是删除最外面的一个:

SelectComponents[img2, "EnclosingComponentCount", # > 0 &]

它只给你内部轮廓(见右下角)。换句话说,它只选择那些被至少一个其他轮廓包围的轮廓,这会自动取消最外面的轮廓。我不知道这些命令/操作在 openCV 中的等价物。

在此处输入图像描述 在此处输入图像描述

请注意,图中明显的中断是由于保存为较小尺寸的 jpeg。在我的屏幕上看起来不是这样。

尝试使用像腐蚀这样的形态过滤器对图像进行预处理这将允许分离触摸轮廓。检测轮廓后,您可以应用膨胀操作来完成格子。

这不是您问题的答案,但轮廓分析容易出错。您对此无能为力,它仅适用于非常简单的场景。

如果您在使用它时遇到问题,您应该寻找一种完全不同的算法。有更复杂和更健壮的方法来解决问题,但这取决于您想要实现的目标(对象检测、跟踪等......)

考虑到您使用 canny 检测它们,轮廓不一定是开放的。Canny 的问题已经在这里讨论过了。关于 canny的讨论为您提供了一个基本概念,即在 Canny 之上仍然需要诸如闭合和膨胀之类的操作来评估闭合轮廓。

这也取决于我们是在寻找轮廓还是分割(Canny 与Graphcuts等方法)。所以我想寻找强大的解决方案取决于您的最终应用程序。