【问题标题】:How to check if two images are the same?如何检查两个图像是否相同?
【发布时间】:2021-04-26 16:28:23
【问题描述】:

我正在使用ImageChops 来检查两个图像是否不同:

currentPic = Image.open('current.png').convert('RGB')
previousPic = Image.open('previous.png').convert('RGB')
diff = ImageChops.difference(currentPic, previousPic)
if diffUserHome.getbbox():
   print("Images are different herey !!")

我试图修改此代码以检查两个图像是否相同。 你知道一种方法,让我使用 ImageChops 库检查两张图片是否完全相同?

【问题讨论】:

  • 这可能对你有帮助:stackoverflow.com/a/12175980/12070811
  • 感谢@sfacky 的评论,但这会计算图像的哈希值,它仅在它们位于相同文件的情况下才有效,如果它们看起来相同或具有 0 像素差异则无效
  • 你需要更清楚你的意思是相同的。 64x80 纯黑色 GIF 与 64x80 纯黑色 PNG 相同吗?他们将有不同的校验和。 64x80 纯黑色 8 位 PNG 与 64x80 纯黑色 16 位 PNG 相同吗?出售的黑色托盘 PNG 怎么样? 64x80 纯黑色 PNG 是否与 64x80 纯黑色 PNG 相同,该 PNG 由完全相同的代码创建,但元数据中有 1 秒后的时间戳?
  • 嗨@Mark Setchell 我需要检查它是否是相同的像素。如果你想更具体。并且里面没有不同的像素
  • 我链接的答案是第二个,它散列像素数据,而不是文件

标签: python python-3.x python-imaging-library


【解决方案1】:

ImageChops.difference() 函数通过将两个图像逐个像素地相减来为您创建一个新图像。如果生成的图像完全是黑色的,则您提取的图像完全相同。这是因为黑色的 rgb 值为 {0,0,0}。 Image.getbbox() 函数计算图像中非零区域的边界框。如果找不到非零点,此函数返回 0。使用这些,可以制作一个简单的函数,如下所示。

from PIL import Image, ImageChops

def isDiffirent(current,previous):
    diff = ImageChops.difference(current,previous)
    if diff.getbbox():
        return 1
    else:
        return 0

【讨论】:

  • 但是....这正是原始代码的内容(除了明显的拼写错误diff/diffUserHome)...
  • @kozmoonot 这个函数也总是返回 1 无论我在里面放什么。它不起作用
【解决方案2】:

您可以使用Image.getdata() 获取差异图像的所有像素值。将这些转换为 NumPy 数组可以很容易地对所有像素值求和。当且仅当原始两个图像之间的所有像素值都相同时,该和为零,因为像素值不能为负。

from PIL import Image, ImageChops
import numpy as np

def are_same_image(image1, image2):
    if np.sum(np.array(ImageChops.difference(image1, image2).getdata())) == 0:
        return True
    return False

【讨论】:

    【解决方案3】:

    我不会在这里使用ImageChops.difference,因为它无法处理不同的图像modes,参见

    from PIL import Image, ImageChops
    
    # Read images
    img1 = Image.open('image.png').convert('L')
    img2 = Image.open('image.png').convert('L').convert('F')
    
    diff = ImageChops.difference(img1, img2)
    

    虽然两个图像是相同的(w.r.t. 像素的强度),但我们得到以下ValueError:

    Traceback (most recent call last):
      File "...", line 7, in <module>
        diff = ImageChops.difference(img1, img2)
      File "...\lib\site-packages\PIL\ImageChops.py", line 102, in difference
        return image1._new(image1.im.chop_difference(image2.im))
    ValueError: images do not match
    

    一般来说,我同意使用 NumPy 的矢量化能力来加速计算,但也可能有这种非常简单的 Pillow only 方法:

    1. 检查波段数。如果它们不匹配,则图像必须不同。
    2. 手动计算每个像素的绝对强度差异(即ImageChops.difference 实际执行的操作),但请确保支持任意两种图像模式。这对于单通道和多通道图像略有不同。
    3. 按照之前的建议对所有像素求和。如果该总和大于0,则图像必须不同。

    那是我的代码:

    from PIL import Image
    
    # Read images
    img1 = Image.open('path/to/your/image.png').convert('RGB')
    img2 = Image.open('path/to/your/image.png').convert('RGB')
    
    # Check for different number of channels
    if img1.im.bands != img2.im.bands:
        print('Images are different; number of channels do not match.')
        exit(-1)
    
    # Get image (pixel) data
    imdata1 = list(img1.getdata())
    imdata2 = list(img2.getdata())
    
    # Calculate pixel-wise absolute differences, and sum those differences
    diff = 0
    if img1.im.bands == 1:
        diff = sum([abs(float(i1) - float(i2)) for i1, i2 in zip(imdata1, imdata2)])
    else:
        diff = sum([abs(float(i1) - float(i2)) for i1, i2 in
                    zip([i for p in imdata1 for i in p],
                        [i for p in imdata2 for i in p])])
    if diff > 0:
        print('Images are different; pixel-wise difference > 0.')
        exit(-1)
    
    print('Images are the same.')
    

    对于某些图像,代码原样返回:

    Images are the same.
    

    另外,对于开头提到的情况,我们会得到这个输出。然而,对于一些输入,如

    img1 = Image.open('image.png').convert('L')
    img2 = Image.open('image.png').convert('F')
    

    最有可能的输出是:

    Images are different; pixel-wise difference > 0.
    

    直接转换为模式F 将导致单个强度值的一些小数部分,因此与普通转换为模式L 存在差异。

    如果您有代码失败的用例,请告诉我。我很好奇,如果我在这里错过了一些边缘情况!

    ----------------------------------------
    System information
    ----------------------------------------
    Platform:      Windows-10-10.0.16299-SP0
    Python:        3.9.1
    PyCharm:       2021.1.1
    Pillow:        8.2.0
    ----------------------------------------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-25
      • 2014-03-22
      • 2023-03-13
      • 2011-06-22
      • 2014-06-11
      • 1970-01-01
      相关资源
      最近更新 更多