在图像处理中如何找到两张图片之间的轮廓差异?

4

我试图找到两个图像之间一个或多个差异的轮廓。

假设您有两个相同的图像。然后在其中一个图像的随机位置添加一个不透明的正方形和三角形。这些形状不能重叠。

我想要获取这些形状最外层像素的坐标,并且这些坐标必须被“分组” -> 我想要获取两组坐标,每组一个形状。

我尝试比较每个像素并获取最小和最大x和y值,这给了我形状的边界框。这有两个问题:它给我边界框而不是形状的轮廓。而且它仅适用于图像中没有超过一个形状的情况。

我无法想出一种方法来完成这项任务。

我几乎完全依赖php,但可以使用gd或imagick。我稍微倾向于gd,但imagick更快,更强大,所以也可以。

额外加分:最终结果应该是每个形状的简单(尽可能简单)多边形。某些精度损失是可以接受的,事实上是可以鼓励的。多边形的线条不必完美地遵循轮廓,允许一些偏差以换取更少的点。

编辑:
我所说的“轮廓”是这样的:假设我有一个画了一个矩形的图像。我想要找到的轮廓是组成矩形的四个点。涂上这个正方形的图像可以是任何图像。它可能是白色画布,也可能是风景或肖像,你说了算。
我现在意识到顺序很重要。我必须能够重新绘制正方形,而不会得到沙漏形状。

编辑2:
我正在使用imagick接近一步。

convert img/modified.png img/original.png -compose ChangeMask -composite out.png

这个命令使用原始图像作为蒙版(mask),将其应用到修改后的版本中,得到只有形状的图像。也许我可以使用标准的边缘检测算法来处理这张图像。
但是存在一个问题:只有当图像中只有一种形状时才能正常工作。但如果这是必然的结果,那么应该就没问题了。 编辑 3:
现在我可以获取不太复杂的形状轮廓。但它的结果有数百个点,这太多了。需要将其压缩到大约20个点左右。
具体过程如下:
  • 我使用上述 ImageMagick 命令得到只包含形状的图像,其余部分透明。
  • 在此图像中,我从顶部 (0,0) 开始向下查找非透明像素。然后查看 (1,0) 等等。当到达末尾时,我从 (width,0) 开始向左查找非透明像素,这样就遍历了整个图像的轮廓。

为什么不尝试使用标准轮廓算法之一呢?例如,Canny、梯度、拉普拉斯…… - Eddy_Em
这些算法是用于边缘检测的,而这不是我想要做的。你可以将其视为查找两个图像之间的差异。 - Dennis Haarbrink
那么,“轮廓”是什么意思?如果这是等值线,您可以使用Marching Squares算法。 - Eddy_Em
@Eddy_Em 请看修改后的问题。希望这样更清楚了。 - Dennis Haarbrink
也许您可以添加一个图像来展示您想要实现的内容?比矩形示例更复杂的内容。包括两个源图像和您期望的结果。这将有助于推荐解决方案。 - user2454182
1个回答

0

这里有几种不错的轮廓跟踪算法。个人而言,我使用了Moore-neighborhood追踪算法(另一个链接),获得了良好的结果。我发现它很精确,可以保留顺序,避免出现沙漏问题。

但是,在我进行这一步之前,我经常需要进行一些预处理(形态滤波器或图像减法(正如你发现的那样))。

完成这两个步骤后,您应该会有一系列点。您有两个选项:

1) 复杂情况:将它们收集到向量中。如果向量的斜率(或方向)发生了显著变化,那么你就知道有一个点。像potrace这样的命令行工具可以做到这一点。Potrace的算法在这里,非常好用。在你的简单矩形示例中,这将起作用,但在更复杂的场景中,如圆形(你只需要有很多圆形向量),它也会起作用。

2) 简单情况:使用Moore-Neigborhood遍历你找到的像素,并确定方向的变化。(即如果三个像素组成一条线,而接下来的三个像素不是通过某个阈值x“在线”,那么你就有了一个拐角)。这个算法对于正方形是有效的,但对于更复杂的图像,如八边形和圆形,在线之间的角度差异更为明显时,它开始失效。

如果你所有的形状都足够简单(正方形、圆形等),你还可以考虑模板匹配(简单形状检测)。Aforge文档中有一个好的链接,位于这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接