在网址到图像中的文件系统中的蟒蛇形象比较(Comparing image in url to ima

2019-07-05 07:08发布

是否有一个快速简便的方法做这样的比较?

我发现一些图像相比较,从计算器的问题,但这些都不实际上证明了这个问题的答案。

我在我的文件系统映像文件和从URL中获取图像的脚本。 我要检查,如果在URL中的形象已经是磁盘上的相同。 通常我会在磁盘和URL的图像加载到PIL对象,并使用下面的函数,我发现:

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

但如果你有,因为它得到,即使你把质量100压缩的图像保存到磁盘与PIL这不起作用im1.save(outfile,quality=100)

我的代码当前如下: http://pastebin.com/295kDMsp但图像最终总是重新保存。

Answer 1:

问题的标题表明你有两个精确的图像进行比较,那就是平凡完成。 现在,如果你有类似的图像进行比较,然后解释为什么你没有找到一个完全满意的答案:没有度量标准适用于给出的预期结果每一个问题(注意,预期结果应用程序之间变化)。 其中一个问题是,这是很难 - 在这个意义上,有没有共同的协议 - 与多个频带比较图像,像彩色图像。 为了处理这一点,我会考虑在每个频段特定指标的应用,以及该指标的结果将是最低的结果值。 这假定该度量具有良好建立的范围,如[0,1],并且在该范围内的最大值是指图像是相同的(由给定度量)。 相反地​​,最小值意味着图像是完全不同的。

因此,所有我将在这里做的就是给你两个指标。 其中之一是SSIM和另外一个我会打电话的NRMSE(平均根正常化方误差)。 我选择呈现第二个,因为它是一个非常简单的方法,它可以为你的问题是不够的。

让我们开始使用的例子。 的图像是顺序如下:F =在50%的质量在PNG,G1 = JPEG原始图像f (与由convert f -quality 50 g ,G2 =的JPEG 1%质量) f ,H = “减轻” G2。

结果(四舍五入):

  • NRMSE(F,G1)= 0.96
  • NRMSE(F,G2)= 0.88
  • NRMSE(F,H)= 0.63
  • SSIM(F,G1)= 0.98
  • SSIM(F,G2)= 0.81
  • SSIM(F,H)= 0.55

在某种程度上,这两个度量处理好的修改,但是SSIM显示是通过报告更低的相似性时的图像实际上是视觉上不同的,并通过报告较高的值时,图像在视觉上是非常相似的更明智的。 在下一个示例中(以5%的质量F =原始图像,并且g = JPEG)考虑了彩色图像。

  • NRMSE(F,G)= 0.92
  • SSIM(F,G)= 0.61

因此,它是由你来决定什么是你喜欢的指标,并为它的阈值。

现在,度量。 我被命名为NRMSE简单地为1 - [RMSE /( maxval - minval )]。 其中maxval是从两个图像的最大强度进行比较,和分别同一对minval 。 RMSE由MSE的平方根给出:SQRT [(总和(A - B)** 2)/ | A |],其中| A | 指A.元件通过这样的数量,由RMSE给出的最大值为maxval 。 如果您想进一步了解MSE的图像中的含义,见,例如, https://ece.uwaterloo.ca/~z70wang/publications/SPM09.pdf 。 该指标SSIM(结构相似性)是更多地参与,你可以找到在前面包含的链接的详细信息。 为了方便地应用的指标,考虑下面的代码:

import numpy
from scipy.signal import fftconvolve

def ssim(im1, im2, window, k=(0.01, 0.03), l=255):
    """See https://ece.uwaterloo.ca/~z70wang/research/ssim/"""
    # Check if the window is smaller than the images.
    for a, b in zip(window.shape, im1.shape):
        if a > b:
            return None, None
    # Values in k must be positive according to the base implementation.
    for ki in k:
        if ki < 0:
            return None, None

    c1 = (k[0] * l) ** 2
    c2 = (k[1] * l) ** 2
    window = window/numpy.sum(window)

    mu1 = fftconvolve(im1, window, mode='valid')
    mu2 = fftconvolve(im2, window, mode='valid')
    mu1_sq = mu1 * mu1
    mu2_sq = mu2 * mu2
    mu1_mu2 = mu1 * mu2
    sigma1_sq = fftconvolve(im1 * im1, window, mode='valid') - mu1_sq
    sigma2_sq = fftconvolve(im2 * im2, window, mode='valid') - mu2_sq
    sigma12 = fftconvolve(im1 * im2, window, mode='valid') - mu1_mu2

    if c1 > 0 and c2 > 0:
        num = (2 * mu1_mu2 + c1) * (2 * sigma12 + c2)
        den = (mu1_sq + mu2_sq + c1) * (sigma1_sq + sigma2_sq + c2)
        ssim_map = num / den
    else:
        num1 = 2 * mu1_mu2 + c1
        num2 = 2 * sigma12 + c2
        den1 = mu1_sq + mu2_sq + c1
        den2 = sigma1_sq + sigma2_sq + c2
        ssim_map = numpy.ones(numpy.shape(mu1))
        index = (den1 * den2) > 0
        ssim_map[index] = (num1[index] * num2[index]) / (den1[index] * den2[index])
        index = (den1 != 0) & (den2 == 0)
        ssim_map[index] = num1[index] / den1[index]

    mssim = ssim_map.mean()
    return mssim, ssim_map


def nrmse(im1, im2):
    a, b = im1.shape
    rmse = numpy.sqrt(numpy.sum((im2 - im1) ** 2) / float(a * b))
    max_val = max(numpy.max(im1), numpy.max(im2))
    min_val = min(numpy.min(im1), numpy.min(im2))
    return 1 - (rmse / (max_val - min_val))


if __name__ == "__main__":
    import sys
    from scipy.signal import gaussian
    from PIL import Image

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

    if img1.size != img2.size:
        print "Error: images size differ"
        raise SystemExit

    # Create a 2d gaussian for the window parameter
    win = numpy.array([gaussian(11, 1.5)])
    win2d = win * (win.T)

    num_metrics = 2
    sim_index = [2 for _ in xrange(num_metrics)]
    for band1, band2 in zip(img1.split(), img2.split()):
        b1 = numpy.asarray(band1, dtype=numpy.double)
        b2 = numpy.asarray(band2, dtype=numpy.double)
        # SSIM
        res, smap = ssim(b1, b2, win2d)

        m = [res, nrmse(b1, b2)]
        for i in xrange(num_metrics):
            sim_index[i] = min(m[i], sim_index[i])

    print "Result:", sim_index

需要注意的是ssim拒绝当给定的比较图像window大于它们。 该window通常是非常小的,默认为11×11,因此,如果您的图片小于,没有什么太大的“结构”(从指标的名称)来比较,你应该用别的东西(像其他功能nrmse ) 。 有可能是实现一个更好的方式ssim ,因为在Matlab这个运行得更快。



Answer 2:

你可以让你自己的比较 - 使用平方差。 然后,您将设置一个阈值,如95%,如果它们是相似的,那么你就不必下载。 它消除了压缩的问题



Answer 3:

沿线的巴特洛梅耶莱万多夫斯基的建议下,我会建议比较直方图的熵,这是很容易和相对快速的计算:

def histogram_entropy(im):
    """ Calculate the entropy of an images' histogram.
    Used for "smart cropping" in easy-thumbnails;
    see also https://raw.github.com/SmileyChris/easy-thumbnails/master/easy_thumbnails/utils.py
    """
    if not isinstance(im, Image.Image):
        return 0  # Fall back to a constant entropy.

    histogram = im.histogram()
    hist_ceil = float(sum(histogram))
    histonorm = [histocol / hist_ceil for histocol in histogram]

...此功能是一个我在使用自动方作物滤波器我建-但你可以用熵值进行比较(甚至是不同的大小)的任何两个图像。

我有这种想法的应用程序的其他例子,让我知道了评论,如果你想我自己的方式来发送一个具体的例子。



文章来源: Comparing image in url to image in filesystem in python