SSIM可以抵消MSE无法衡量图像结构相似性的缺陷。
SSIM定义:
其中:α、β、γ均大于0
上式中,μ_x,μ_y为图像块所有像素;δ_x,δ_y为图像像素值的标准差;δ_xy为x与y的协方差;C_1,C_2,C_3为常数,为避免分母为0时带来的系统错误。
在实际应用中,α=β=γ=1,C_3= 0.5C_2,则SSIM表达式为:
SSIM性质
- SSIM具有对称性。即SSIM(x,y)=SSIM(y,x)
- SSIM是一个0到1之间的数,SSIM越大,两图像间差异越小。
tensorflow实现:
tf.image.ssim(img1,img2,max_val)
img1:第一批图片。
img2:第二批图片。
max_val:图像的动态范围(即最大允许值和最小允许值之间的差值)。
注意:真正的SSIM仅在灰度上定义。 此函数不执行任何颜色空间转换。 (如果输入已经是YUV,那么它将计算YUV SSIM平均值。)
使用python实现
import tensorflow as tf
import numpy as np
import scipy.misc
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"]='2'
def _tf_fspecial_gauss(size, sigma=1.5):
x_data, y_data = np.mgrid[-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1]
x_data = np.expand_dims(x_data, axis=-1)#扩展数组的形状
x_data = np.expand_dims(x_data, axis=-1)
y_data = np.expand_dims(y_data, axis=-1)
y_data = np.expand_dims(y_data, axis=-1)
x = tf.constant(x_data, dtype=tf.float32)
y = tf.constant(y_data, dtype=tf.float32)
g = tf.exp(-((x**2 + y**2)/(2.0*sigma**2)))
return g / tf.reduce_sum(g)
def SSIM(img1, img2, k1=0.01, k2=0.02, L=1, window_size=11):
img1 = tf.expand_dims(img1, 0)
img1 = tf.expand_dims(img1, -1)
img2 = tf.expand_dims(img2, 0)
img2 = tf.expand_dims(img2, -1)
window = _tf_fspecial_gauss(window_size)
mu1 = tf.nn.conv2d(img1, window, strides = [1, 1, 1, 1], padding = 'VALID')
mu2 = tf.nn.conv2d(img2, window, strides = [1, 1, 1, 1], padding = 'VALID')
mu1_sq = mu1 * mu1
mu2_sq = mu2 * mu2
mu1_mu2 = mu1 * mu2
sigma1_sq = tf.nn.conv2d(img1*img1, window, strides = [1 ,1, 1, 1], padding = 'VALID') - mu1_sq
sigma2_sq = tf.nn.conv2d(img2*img2, window, strides = [1, 1, 1, 1], padding = 'VALID') - mu2_sq
sigma1_2 = tf.nn.conv2d(img1*img2, window, strides = [1, 1, 1, 1], padding = 'VALID') - mu1_mu2
c1 = (k1*L)**2
c2 = (k2*L)**2
ssim_map = ((2*mu1_mu2 + c1)*(2*sigma1_2 + c2)) / ((mu1_sq + mu2_sq + c1)*(sigma1_sq + sigma2_sq + c2))
return tf.reduce_mean(ssim_map)
img1 = np.array(scipy.misc.imread('tree.png', mode='RGB').astype('float32'))
img2 = np.array(scipy.misc.imread('tree2.png', mode='RGB').astype('float32'))
img1 = tf.constant(img1)
img2 = tf.constant(img2)
_SSIM_ = tf.image.ssim(img1, img2, 1.0)
rgb1 = tf.unstack(img1, axis=2)
r1 = rgb1[0]
g1 = rgb1[1]
b1 = rgb1[2]
rgb2 = tf.unstack(img2, axis=2)
r2 = rgb2[0]
g2 = rgb2[1]
b2 = rgb2[2]
ssim_r=SSIM(r1,r2)
ssim_g=SSIM(g1,g2)
ssim_b=SSIM(b1,b2)
ssim = tf.reduce_mean(ssim_r+ssim_g+ssim_b)/3
with tf.Session() as sess:
with tf.Session() as sess:
print('tf.image.ssim: ',sess.run(_SSIM_))
print('SSIM: ',sess.run(ssim))