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

Pet*_*son 39 python linux image

试图解决防止上传重复图像的问题.

我有两个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)
Run Code Online (Sandbox Code Playgroud)

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

58.9830484122
Run Code Online (Sandbox Code Playgroud)

谁能告诉我一个合适的截止点应该是什么?

更新II

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

b=Image.open('a.jpg')
b.save(open('b.jpg','wb'))
Run Code Online (Sandbox Code Playgroud)

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

Aut*_*ter 25

有一个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))
Run Code Online (Sandbox Code Playgroud)

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

  • 此代码查找图像直方图之间的RMS误差,**NOT**图像本身之间.考虑两个图像可以具有相同的直方图但完全不同,例如,如果您"加扰"像素. (12认同)
  • 应该注意的是,如果你用相同的列表理解来替换map + reduce调用,你将获得非常好的速度提升(在我的Mac上大约快80%).请改用以下代码(为格式不佳道歉):`diff_squares = [(h1 [i] - h2 [i])**2 for x in xrange(len(h1))]; rms = math.sqrt(sum(diff_squares)/ len(h1));`.这是在Python 2.7.3上,我已经在OS X和Linux上复制了结果.YMMV,但差异足够大,值得调查. (6认同)

Xol*_*lve 20

这里开始

确定两个图像是否具有完全相同内容的最快方法是获得两个图像之间的差异,然后计算该图像中非零区域的边界框.如果图像相同,则差异图像中的所有像素均为零,并且边界框函数返回"无".

import ImageChops

def equal(im1, im2):
    return ImageChops.difference(im1, im2).getbbox() is None
Run Code Online (Sandbox Code Playgroud)


for*_*ran 11

我想你应该对图像进行解码并逐个像素地进行比较,看看它们是否相似.

有了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())
Run Code Online (Sandbox Code Playgroud)

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

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


sub*_*iet 10

使用ImageMagick,您只需在shell中使用[或通过程序内的OS库调用]

compare image1 image2 output
Run Code Online (Sandbox Code Playgroud)

这将创建一个带有差异标记的输出图像

compare -metric AE -fuzz 5% image1 image2 output
Run Code Online (Sandbox Code Playgroud)

会给你一个5%的模糊因子来忽略微小的像素差异.可以从这里获得更多信息

  • 有没有一种方法可以编程确定结果`output`是否为空? (3认同)