【问题标题】:Compare Images in Python在 Python 中比较图像
【发布时间】:2012-08-02 17:04:03
【问题描述】:

我需要比较两个作为软件屏幕截图的图像。我想检查两个图像是否相同,包括图像中显示的数字和字母。这如何实现?

【问题讨论】:

  • 你说比较是什么意思?你想看看它们是否相同?您是否正在寻找有关如何在 Python 中执行此操作或如何比较一般图像的详细信息?
  • 是的,我想比较一下它们是否相同,包括软件中显示的数字/字母

标签: python image-processing image-comparison


【解决方案1】:

有以下方法可以进行正确的比较。

  • 首先是 均方根差 #

要衡量两个图像的相似程度,您可以计算图像之间差异的均方根 (RMS) 值。如果图像完全相同,则该值为零。下面的函数使用差分函数,然后根据生成图像的直方图计算 RMS 值。

# Example: File: imagediff.py

import ImageChops
import math, operator

def rmsdiff(im1, im2):
    "Calculate the root-mean-square difference between two images"

    h = ImageChops.difference(im1, im2).histogram()

    # calculate rms
    return math.sqrt(reduce(operator.add,
        map(lambda h, i: h*(i**2), h, range(256))
    ) / (float(im1.size[0]) * im1.size[1]))
  • 另一个是精确比较#

判断两张图片内容是否完全相同的最快方法是获取两张图片的差值,然后计算这张图片中非零区域的边界框。如果图像相同,则差异图像中的所有像素都为零,并且边界框函数返回 None。

import ImageChops

def equal(im1, im2):
    return ImageChops.difference(im1, im2).getbbox() is None

【讨论】:

  • 一个“幻数”给我带来了问题。我建议将 range(256) 替换为 range(len(h)) 以获得稳健性。
  • 我应该提到的小问题:大的单行(return statement)可能会更好。但如果不是,我个人至少会给 lambda 参数 h 另一个名称,只是为了清楚起见:例如:map(lambda x, i: x*(i**2), h, range(len(h)))。干杯! ;)
  • 好的。对于 RGB 调色板,我得到了 768 个值(R、G、B 连续 256 个)。因此,首先,需要 256 的模数来使直方图中的每个通道“点击”为零,否则,例如,第二个颜色通道的加权频率将是 256 次!每个连续的通道将进一步 +256!另外,我注意到需要转置 h 和 I。这很有效:return math.sqrt(reduce(operator.add, map(lambda h, i: i%256*(h**2), h, range(len(h))) ) / (float(im1.size[0]) * im1.size[1]))
  • 尝试您的确切比较示例,我得到了奇怪的结果。 diff.getbbox() is NoneTrue,尽管 im2 只是 im1 的副本,我在油漆中打开并绘制了所有内容。有什么想法吗?
【解决方案2】:

我正在维护一个名为 pyssim 的 Python 库,它使用 Structured Similarity (SSIM) 方法比较两个图像。

它没有 python 绑定,但perceptualdiff 程序在比较两个图像方面也很棒——而且速度非常快。

【讨论】:

  • pyssim 是一种模糊比较吗?如果图像中有一个文本框,框的位置与另一个图像相同,但文本略有不同怎么办?它会返回什么分数?它只考虑结构吗?
  • 如果文字不同,则得分较低。
  • 我是否正确地说比较的 2 个图像需要具有相同的尺寸?
  • 是的,您必须先调整一个大小才能匹配。
【解决方案3】:

我不能给出一个现成的答案,但我会指出(我认为)正确的方向。 比较两个图像的一种简单方法是对它们的二进制表示进行散列,然后查看这些散列是否相同。这样做的一个问题是您要使用的散列函数,您必须寻找一个冲突可能性低的函数,另一个是图像文件可能具有附加到原始二进制信息的元数据,因此您必须查看在如何切断该元数据以便仅使用它们的二进制信息比较图像。 另外,我不确定,但可能以 jpg 编码的图像的二进制表示与以 png 编码的图像不同,因此您应该注意这一点。

【讨论】:

    【解决方案4】:

    对于任何偶然发现这一点并且接受的答案对他们不起作用的人,我将其发布在这里。

    我有一个类似的场景,我需要将一张图片与其他数千张图片进行比较,然后找到最相似的一张。我最终开始使用 ImageChop 的差异函数并应用这样的平均值:

    import numpy as np
    
    def calcdiff(im1, im2):
        dif = ImageChops.difference(im1, im2)
        return np.mean(np.array(dif))
    

    通过将差异图像转换为数组,我可以计算平均差异。差异越小,图像与原始图像越接近。


    注意:另一种接近完全相似的方法是将ImageChops.difference(im1, im2) 转换为numpy 数组,然后将精确匹配像素[0, 0, 0] 减去该数组。然后通过计算数组的len(),我们得到一个分数,可以让我们区分图像。最接近的是分数最低的那个

    【讨论】:

    • 将 numpy 导入为 np
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 2014-09-11
    相关资源
    最近更新 更多