矢量图像的图像比较(基于边缘检测)?

时间:2012-11-30 13:59:05

标签: python image image-processing computer-vision python-imaging-library

过去两天我一直在浏览帖子和例子,我尝试过并经过广泛测试的所有片段都证明是无用的,至少对我来说是这样。

我想要做的是比较从墙上或纸上拍摄的黑色矢量符号(质量类似于人们可能会说的严重扫描图像),并将其与相同或类似符号的电子版本进行比较(这将是本地存储并与照片比较)。请看一下这两个附加的图像,第一个干净的图像(参考图像)是符号的数据库版本,第二个是我在一张纸上制作的蹩脚图画,然后我用我的iPad拍摄。

Reference Image

Test Image

我希望程序如下:

  • 加载这两个图像,然后使用我在此处找到的修剪算法的修改版本进行修剪:Trimming images with PIL。我发现'阈值'值为50,'显而易见'值为20(链接脚本中的参数)为这些图像提供了良好的结果
  • 然后将图像调整为相同尺寸并进行比较

现在进行比较,我尝试了大量不同的建议方法,但到目前为止,结果非常糟糕。实际上,我可以通过随机图像获得比测试结果更好的比较结果。我已根据实际图像,边缘(使用ImageFilter.CONTOUR或ImageFilter.FIND_EDGES的'过滤器'功能创建)RMS difference comparison尝试了Pixel-Based Comparison,但到目前为止我没有在网上找到任何内容(尽管我的不断的谷歌搜索)或StackOverflow这里给了我不错的结果。

我认为问题在于测试图像的嘈杂背景,但我无法证明这一点。有没有人知道是否有办法从这些图像的边缘中获取矢量轮廓,并将它们不仅仅作为图像而是作为图像矢量进行比较? 尽管绘图很糟糕,但我发现这两个图像非常相似,应该可以很好地比较它。

5 个答案:

答案 0 :(得分:4)

要获得更好的响应,您需要更好地限制应用程序的范围。这可能对你有所帮助。我认为你的“糟糕绘画”输入总是类似于你提供的那个,它具有强大的边缘,并且它上面的颜色是无关紧要的。要以简单的方式解决(或者,更好地,更接近解决方案)问题,您需要根据比例不变描述符来描述两个图像。

我接受它:对两个图像进行二值化,计算两者内部连接组件(CC)的数量,丢弃不相关大小的CC(距离中位数太远,平均值,与stddev相关等等,您决定)。您可能希望补充第二步,以更好地区分您的图像与其他输入,即,您希望您的方法更强大,您将需要更多的判别描述符。在某些时候,您可能还想考虑使用SVM或其他机器学习技术。

因此,二值化步骤:执行形态梯度并丢弃弱梯度。如果输入与发布的输入类似,则非常容易。这是我得到的强度为60的阈值(我也假设您的输入在[0,255]范围内):

enter image description here enter image description here

我很快就尝试了90到90之间的阈值,所有这些都适用于这些图像。裁剪这些很容易,你也可以填充背景和对象:

enter image description here enter image description here

现在,您可以以白色提取连接的组件并对其进行分析。在这种情况下,最简单的方法是计算它们。对于这些输入,我们在“完美”图像中得到12,在“坏”图像中得到14。但是,在“坏”的一个中,我们有2个大小为1的组件(每个组件中只有一个像素),这些组件被轻易消除。还有很多其他方法可以比较连接的组件,但我希望这可以帮助您入门。如果您需要这些任务的代码,我可以加入它。

答案 1 :(得分:1)

我不确定如何使用PIL专门做这个,但我可以指出一些好的工作示例来帮助你自学(这对图像处理来说是一项非常重要的任务!)。

一个很好的工作示例是DeTeXify,一个程序将鼠标绘制的符号与一个已知符号的大型库匹配(在这种情况下,可以在排版程序LaTeX中创建符号)。可以使用前端和后端的源代码。

另一个例子是ShapeCatcher,其中:

  

...使用所谓的“形状上下文”来找到两个形状之间的相似之处。形状上下文是描述形状之间相似性概念的一种强大的数学方法,是Serge Belongie和Jitendra Malik首先提出的特征描述符。

可以在Berkeley site上找到免费提供的形状背景研究论文。

答案 2 :(得分:0)

我认为如果你将线条可视化为图形上的边缘,将交叉点视为节点,即使一个很难看,计算机应该能够看到它们是相同的符号。只需玩水平以获得白人和黑人,然后尝试分析连续的黑点。

答案 3 :(得分:0)

有一种名为SIFT的方法。 OpenCV使用它,并且Python OpenCV中也有一个实现。实现是OpenCV中的SURF,可以找到各种问题和示例,并且它运行良好。 this问题中有一个例子。

(将此答案作为额外参考发布)

答案 4 :(得分:0)

我知道这已经得到了解答,但也许有人会发现这一点。

与接受的答案不同,我不会处理执行二值化的渐变,而是查看Otsu's Thresholding。如果所有图像仅包含非常暗且非常亮的区域,则它应该可以正常工作,因为它在图像直方图中查找两个峰值(一个用于所有亮像素,一个用于所有暗像素),然后是一个值的阈值在两个山峰之间。