【问题标题】:Image Comparison for vector images (based on edge detection)?矢量图像的图像比较(基于边缘检测)?
【发布时间】:2012-11-18 18:16:13
【问题描述】:

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

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

我希望过程如下:

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

现在为了比较,我尝试了很多不同的建议方法,但到目前为止结果很糟糕。实际上,我可以使用随机图像获得比测试图像更好的比较结果。我已经根据实际图像、它们的边缘(使用 ImageFilter.CONTOUR 或 ImageFilter.FIND_EDGES 的“过滤器”功能创建)、Pixel-Based Comparison 尝试了RMS difference comparison,但到目前为止我在网上没有找到任何东西(尽管我不断地谷歌搜索)或StackOverflow 给了我不错的结果。

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

【问题讨论】:

  • 基于矢量的方法存在问题,您如何处理错误的杂散标记或具有不同纵横比的绘制图像?除了我的回答之外,如果您可以获得标准化图像,则使用特征脸(参见 wiki)的光栅化方法在这里可能很有用(尽管计算量很大并且需要一些线性代数)。

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


【解决方案1】:

要获得更好的响应,您需要更好地限制应用程序的范围。这里有一些可以帮助你的东西。我想您的“蹩脚绘图”输入总是与您提供的输入相似,因为它具有很强的边缘,并且其上存在的颜色无关紧要。要以简单的方式解决(或者更好地接近解决方案)您的问题,您需要根据尺度不变描述符来描述这两个图像。

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

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

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

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

【讨论】:

  • 哇,你让我大吃一惊 :) 有人告诉我这不是你第一次 :P 能否请你包含测试代码,以便我可以试验它(你不必在这里粘贴它,附加文件会很棒)?非常感谢!
  • 很好,希望你能用。下面是拆分成两个文件的代码:pastebin.com/SGhw0fMZpastebin.com/mRZ0mzVa,非常简单,可以多方面改进。
【解决方案2】:

我不确定如何具体使用 PIL 来执行此操作,但我可以为您指出一些很好的工作示例来帮助您自学(这对于图像处理来说是一项不平凡的任务!)。

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

另一个例子是ShapeCatcher

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

关于形状上下文的免费研究论文可以在他们的Berkeley site 上找到。

【讨论】:

  • 感谢您的建议 Hooked,不幸的是,我希望这段代码在 Pythonista 上运行,这是 iOS python 环境,不幸的是它不允许安装 3rd 方库,甚至没有 numpy 或 scipy,所以我'd 需要找到一种方法使上述内容与标准 Python 库一起工作。我有点希望这对 PIL 来说是一件容易的事,但我很可能在自欺欺人:)
  • @somada141 明白了(虽然很高兴知道问题中的约束!)。我仍然认为这些参考是有效的,因为您可以看到生产级实现中涉及的算法。
【解决方案3】:

我认为,如果您将线可视化为图形上的边,而将交叉点可视化为节点,即使一个很丑,计算机也应该能够看到它们是同一个符号。只需使用关卡来获取您的白人和黑人,然后尝试分析连续的黑点。

【讨论】:

  • 感谢您的回复 Voronoi,您是否有机会知道如何执行您的建议?我用 PIL 找不到任何有关矢量图像的信息
  • codeboje.de/pysvg 是一个不错的 SVG 库,你可以试试。你正在做的事情是非常困难的,所以祝你好运。
  • 对于边缘检测,我会在对比度增强后寻找靠近白色像素/灰色像素的黑色像素。可以这么说定义外循环,找到内部边缘,尝试通过取一行像素并分析(白,黑,白,黑)进行关联
  • 您可能需要使用许多不同的策略,但提高对比度和调整色阶以获得准确的黑白照片是第一步。
  • 另外,为什么不能将 SVG 导出为 png 并为此使用 PIL?
【解决方案4】:

有一个方法叫做SIFT。 OpenCV 使用它,并且在 Python OpenCV 中也有一个实现。实现是OpenCV中的SURF,各种问题和例子都能找到,效果很好。 this问题中有一个例子。

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

【讨论】:

    【解决方案5】:

    我知道这已经被回答了,但也许有人会找到这个。

    与公认的答案不同,我不会处理梯度来执行二值化,而是查看Otsu's Thresholding。如果您的所有图像仅包含非常暗和非常亮的区域,这应该会很好,因为它会查找图像直方图中的两个峰值(一个用于所有亮像素,一个用于所有暗像素),然后在值上设置阈值在两个峰之间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-01
      • 2020-12-16
      • 1970-01-01
      • 2011-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多