之前介绍了通过Hash进行图片相似度识别的一系列算法,本次接着来介绍另一种非常常用的衡量两幅图片相似度的指标——SSIM。
SSIM算法
SSIM(structural similarity)是一种用来衡量图片相似度的指标,也可用来判断图片压缩后的质量。
基本原理:
SSIM由亮度对比、对比度对比、结构对比三部分组成。
其中有几个需要注意的点:
(更多SSIM介绍可自行搜索论文《Image Quality Assessment: From Error Visibility to Structural Similarity》)
Python实现
代码流程:
STEP 1:修改尺寸,灰度化。SSIM计算时需要保证图片大小相同,并且根据上述算法原理得知,要基于灰度进行计算,因此对图片进行灰度化处理。
STEP 2:加窗。局部求SSIM指数的效果要好于全局,用标准差为1.5的高斯加权函数作为加权窗口,每一步基于窗口内像素进行计算,得到由局部SSIM指数构成的SSIM指数映射矩阵。
STEP 3:计算。用平均SSIM指数作为最终结果。
完整代码:
借鉴网上代码并用以下两张图片为例:
(image1)
import numpy as np
from PIL import Image
from scipy.signal import convolve2d
def matlab_style_gauss2D(shape=(3,3),sigma=0.5):
#高斯加窗
m,n = [(ss-1.)/2. for ss in shape]
y,x = np.ogrid[-m:m+1,-n:n+1]
h = np.exp( -(x*x + y*y) / (2.*sigma*sigma) )
h[ h < np.finfo(h.dtype).eps*h.max() ] = 0
sumh = h.sum()
if sumh != 0:
h /= sumh
return h
def filter2(x, kernel, mode='same'):
#窗口内进行高斯卷积,类似加权平均
return convolve2d(x, np.rot90(kernel, 2), mode=mode)
def compute_ssim(im1, im2, k1=0.01, k2=0.03, win_size=11, L=255):
M, N = im1.shape
C1 = (k1*L)**2
C2 = (k2*L)**2
window = matlab_style_gauss2D(shape=(win_size,win_size), sigma=1.5)
window = window/np.sum(np.sum(window))
if im1.dtype == np.uint8:
im1 = np.double(im1)
if im2.dtype == np.uint8:
im2 = np.double(im2)
mu1 = filter2(im1, window, 'valid')
mu2 = filter2(im2, window, 'valid')
mu1_sq = mu1 * mu1
mu2_sq = mu2 * mu2
mu1_mu2 = mu1 * mu2
sigma1_sq = filter2(im1*im1, window, 'valid') - mu1_sq
sigma2_sq = filter2(im2*im2, window, 'valid') - mu2_sq
sigmal2 = filter2(im1*im2, window, 'valid') - mu1_mu2
ssim_map = ((2*mu1_mu2+C1) * (2*sigmal2+C2)) / ((mu1_sq+mu2_sq+C1) * (sigma1_sq+sigma2_sq+C2))
return np.mean(np.mean(ssim_map))
if __name__ == "__main__":
image1 = Image.open('image1.png')
image2 = Image.open('image2.png')
print(compute_ssim(np.array(image1.resize((8, 8), Image.ANTIALIAS).convert('L'), 'f'),np.array(image2.resize((8, 8), Image.ANTIALIAS).convert('L'), 'f')))
结果为: