繁体   English   中英

使用Python和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 ,但是如果你使用上面的代码并继续得到它,那就会发生一些非常奇怪的事情。

看来mapreduce在这里并不是真的需要。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM