![](/img/trans.png)
[英]how do i see the difference between two images in python using pil?
[英]Root mean square difference between two images using Python and PIL
我需要有一个像这里找到的函数: http : //effbot.org/zone/pil-comparing-images.htm ,它计算两个图像之间的均方根差。 代码如下所示:
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]))
尝试运行此代码会导致以下错误:TypeError:**或pow()的不支持的操作数类型:'NoneType'和'int'。 这是问题吗?
问题是它创建的直方图没有值(或实际上是无值),其中没有对应的像素值。
即,当您找到两个图像的差异时,生成的图像没有任何像素,例如,相隔43个单位,因此h [43] =无。
稍后,您尝试访问范围内每个亮度的像素数(256),并将其平方,这会导致它对None ** 2应该是什么感到困惑。
考虑将range(256)
更改为h.keys()
。
此外,您使用h表示两个不同的东西,考虑更改一个的名称,或者更好的是,它们都更改为有意义的名称。
在这里疯狂猜测,但在你的最后一行尝试这个,看看它是否有效:
return math.sqrt(sum(h*(i**2) for i, h in enumerate(h))) / (float(im1.size[0]) * im1.size[1]))
我不确定你为什么会得到你正在描述的TypeError
,但是如果你使用上面的代码并继续得到它,那就会发生一些非常奇怪的事情。
看来map
和reduce
在这里并不是真的需要。
rmsdiff
的改进版本可以是:
def rmsdiff(im1, im2):
"Calculate the root-mean-square difference between two images"
diff = ImageChops.difference(im1, im2)
h = diff.histogram()
sq = (value*((idx%256)**2) for idx, value in enumerate(h))
sum_of_squares = sum(sq)
rms = math.sqrt(sum_of_squares/float(im1.size[0] * im1.size[1]))
return rms
这是来源 。 根据我的测试,Mark Krautheim建议的改进至少有一个重要原因:与原始版本相反,当将图像与自身进行比较时,它会导致返回值为0.0。
请参见https://gist.github.com/bo858585/5377492 。 这个脚本将所有jpg图像从用户目录(指定它)除以它们的相似性,使用均方根(不分为sqrt(3) - 像素是3位RGB矢量),每对相应之间的差异(通过两个比较图像的矩阵20 * 20的像素的位置。 脚本总结了像素对之间的这些距离,并将此总和除以最大可能距离 - 这样脚本就可以获得两个图像的相似性。 在比较所有调整大小为20 * 20的图像之前。 您可以更改MAX_DISTANCE(从0到400),脚本会将更多或更少相似的图像分组到一个组。
考虑使用现有解决方案(如scikit-image)解决此问题:
from PIL import Image # No need for ImageChops
import math
from skimage import img_as_float
from skimage.measure import compare_mse as mse
def rmsdiff(im1, im2):
"""Calculates the root mean square error (RSME) between two images"""
return math.sqrt(mse(img_as_float(im1), img_as_float(im2)))
或者使用NumPy自己写一些东西:
from PIL import Image, ImageChops
import math
import numpy as np
def rmsdiff(im1, im2):
"""Calculates the root mean square error (RSME) between two images"""
errors = np.asarray(ImageChops.difference(im1, im2)) / 255
return math.sqrt(np.mean(np.square(errors)))
请注意,这两种方法都将像素强度视为[0.0,1.0]而不是[0,255]。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.