这个问题的标题表明你有两个确切的图像要比较,而且
做得很琐碎。现在,如果你有相似的图像要比较
解释了为什么您没有找到完全满意的答案:没有度量
适用于给出预期结果的每个问题(注意
预期结果因应用而异)。问题之一是
很难——在没有共识的意义上——比较图像
有多个波段,比如彩色图像。为了解决这个问题,我会考虑
在每个频带中应用给定的度量,该度量的结果将
是最小的结果值。这是假设度量具有良好的
范围,如[0,1],此范围内的最大值表示图像
相同(按给定的度量)。相反,最小值意味着
图像完全不同。
所以,我要做的就是给你两个指标。其中之一就是
西米另一个我
将调用为NRMSE(均方误差根的标准化)。我
选择第二种方法是因为它是一种非常简单的方法
可能就够解决你的问题了。
让我们从例子开始。图像的顺序是:f=原始
PNG格式的图像,g1=JPEG,质量为“f”的50%(使用“convert f-quality”制作
50 g
),g2=JPEG 1%的“f”,h=“Lighted”g2质量。
Results (rounded):
- 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”显示出了它的优势
一个更明智的方法是,当图像实际上是真实的时,报告较低的相似性
视觉上清晰,当图像
视觉上非常相似。下一个示例考虑彩色图像(f=原始)
图像,g=JPEG,质量为5%)。
- 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 |表示数字
这样,RMSE给出的最大值就是“maxval”。如果要进一步了解图像中MSE的含义,请参阅例
如<https://ece.uwaterloo.ca/~z70wang/publications/SPM09.pdf>. 这个度量SSIM(Structural SIMilarity)更为复杂,您可以找到细节在前面包含的链接中。要方便地应用度量,请考虑
以下代码:
import numpyfrom scipy.signal import fftconvolvedef 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_mapdef 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
请注意,当给定的“window”较大时,“ssim”拒绝比较图像
比他们好。“window”通常非常小,默认值为11x11,因此如果
图像比那个小,没有太多的“结构”(从名字上来说)
度量)进行比较,您应该使用其他度量(如
函数“nrmse”)。可能有更好的方法来实现“ssim”,因为
在Matlab中,这个运行得更快。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)