以python/linux的方式比较两个图像

2024-04-23 20:35:32 发布

您现在位置:Python中文网/ 问答频道 /正文

试图解决阻止上载重复图像的问题。

我有两个JPG。看着它们,我可以看到它们实际上是一样的。但由于某些原因,它们有不同的文件大小(一个是从备份中提取的,另一个是另一个上载的),因此它们有不同的md5校验和。

我怎样才能高效而自信地比较两幅图像,就像一个人能够看到它们是完全相同的一样?

示例:http://static.peterbe.com/a.jpghttp://static.peterbe.com/b.jpg

更新

我写了这个剧本:

import math, operator
from PIL import Image
def compare(file1, file2):
    image1 = Image.open(file1)
    image2 = Image.open(file2)
    h1 = image1.histogram()
    h2 = image2.histogram()
    rms = math.sqrt(reduce(operator.add,
                           map(lambda a,b: (a-b)**2, h1, h2))/len(h1))
    return rms

if __name__=='__main__':
    import sys
    file1, file2 = sys.argv[1:]
    print compare(file1, file2)

然后我下载了两个视觉上完全相同的图像并运行脚本。输出:

58.9830484122

有人能告诉我什么是合适的截止线吗?

更新II

a.jpg和b.jpg之间的区别在于,第二个文件是用PIL保存的:

b=Image.open('a.jpg')
b.save(open('b.jpg','wb'))

这显然应用了一些非常轻质量的修改。我现在已经解决了我的问题,将相同的PIL save应用到正在上传的文件,而不做任何事情,现在它工作了!


Tags: 图像imageimportcomhttppilstaticmath
3条回答

有一个OSS项目使用WebDriver进行屏幕截图,然后比较图片,看看是否有问题(http://code.google.com/p/fighting-layout-bugs/))。它通过将文件打开到一个流中,然后比较每个位来实现。

您可以使用PIL执行类似的操作。

编辑:

经过更多的研究我发现

h1 = Image.open("image1").histogram()
h2 = Image.open("image2").histogram()

rms = math.sqrt(reduce(operator.add,
    map(lambda a,b: (a-b)**2, h1, h2))/len(h1))

http://snipplr.com/view/757/compare-two-pil-images-in-python/http://effbot.org/zone/pil-comparing-images.htm

我想你应该解码图像并逐像素比较,看看它们是否合理相似。

有了PIL和Numpy,你可以很容易地做到:

import Image
import numpy
import sys

def main():
    img1 = Image.open(sys.argv[1])
    img2 = Image.open(sys.argv[2])

    if img1.size != img2.size or img1.getbands() != img2.getbands():
        return -1

    s = 0
    for band_index, band in enumerate(img1.getbands()):
        m1 = numpy.array([p[band_index] for p in img1.getdata()]).reshape(*img1.size)
        m2 = numpy.array([p[band_index] for p in img2.getdata()]).reshape(*img2.size)
        s += numpy.sum(numpy.abs(m1-m2))
    print s

if __name__ == "__main__":
    sys.exit(main())

这将为您提供一个数值,如果图像完全相同,该数值应非常接近0。

请注意,移位/旋转的图像将被报告为非常不同的,因为像素不会逐个匹配。

here

判断两幅图像内容是否完全相同的最快方法是求出两幅图像之间的差值,然后计算出该图像中非零区域的边界框。

如果图像相同,则差异图像中的所有像素都为零,并且bounding box函数返回None。

from PIL import ImageChops


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

相关问题 更多 >