损失函数-ssim和L1混合
ssim占比alpha
L1占比1-alpha
1 #%% 2 3 import tensorflow as tf 4 import numpy as np 5 import torch 6 7 #模仿matlab的fspecial函数,创建滤波算子(计算SSIM用) 8 def _tf_fspecial_gauss(size, sigma, channels=1): 9 """Function to mimic the 'fspecial' gaussian MATLAB function 10 """ 11 x_data, y_data = np.mgrid[-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1] 12 13 x_data = np.expand_dims(x_data, axis=-1) 14 x_data = np.expand_dims(x_data, axis=-1) 15 16 y_data = np.expand_dims(y_data, axis=-1) 17 y_data = np.expand_dims(y_data, axis=-1) 18 19 x = tf.constant(x_data, dtype=tf.float32) 20 y = tf.constant(y_data, dtype=tf.float32) 21 22 g = tf.exp(-((x**2 + y**2)/(2.0*sigma**2))) 23 24 window = g / tf.reduce_sum(g) 25 return tf.tile(window, (1,1,channels,channels)) 26 27 #高斯卷积 28 def tf_gauss_conv(img, filter_size=11, filter_sigma=1.5): 29 _, height, width, ch = img.get_shape().as_list() 30 size = min(filter_size, height, width) 31 sigma = size * filter_sigma / filter_size if filter_size else 0 32 window = _tf_fspecial_gauss(size, sigma, ch) # window shape [size, size] 33 padded_img = tf.pad(img, [[0, 0], [size//2, size//2], [size//2, size//2], [0, 0]], mode="CONSTANT") 34 return tf.nn.conv2d(padded_img, window, strides=[1,1,1,1], padding='VALID') 35 36 #高斯加权的L1正则化 37 def tf_gauss_weighted_l1(img1, img2, mean_metric=True, filter_size=11, filter_sigma=1.5): 38 diff = tf.abs(img1 - img2) 39 L1 = tf_gauss_conv(diff, filter_size=filter_size, filter_sigma=filter_sigma) 40 if mean_metric: 41 return tf.reduce_mean(L1) 42 else: 43 return L1 44 45 #计算ssim 46 def tf_ssim(img1, img2, cs_map=False, mean_metric=True, filter_size=11, filter_sigma=1.5): 47 _, height, width, ch = img1.get_shape().as_list() 48 size = min(filter_size, height, width) 49 sigma = size * filter_sigma / filter_size if filter_size else 0 50 51 window = _tf_fspecial_gauss(size, sigma, ch) # window shape [size, size] 52 K1 = 0.01 53 K2 = 0.03 54 L = 1 # depth of image (255 in case the image has a differnt scale) 55 C1 = (K1*L)**2 56 C2 = (K2*L)**2 57 58 #求取滑块内均值Ux Uy,均方值Ux_sq 59 padded_img1 = tf.pad(img1, [[0, 0], [size//2, size//2], [size//2, size//2], [0, 0]], mode="CONSTANT") #img1 上下左右补零 60 padded_img2 = tf.pad(img2, [[0, 0], [size//2, size//2], [size//2, size//2], [0, 0]], mode="CONSTANT") #img2 上下左右补零 61 mu1 = tf.nn.conv2d(padded_img1, window, strides=[1,1,1,1], padding='VALID') #利用滑动窗口,求取窗口内图像的的加权平均 62 mu2 = tf.nn.conv2d(padded_img2, window, strides=[1,1,1,1], padding='VALID') 63 mu1_sq = mu1*mu1 #img(x,y) Ux*Ux 均方 64 mu2_sq = mu2*mu2 #img(x,y) Uy*Uy 65 mu1_mu2 = mu1*mu2 #img(x,y) Ux*Uy 66 67 #求取方差,方差等于平方的期望减去期望的平方,平方的均值减去均值的平方 68 paddedimg11 = padded_img1*padded_img1 69 paddedimg22 = padded_img2*padded_img2 70 paddedimg12 = padded_img1*padded_img2 71 72 sigma1_sq = tf.nn.conv2d(paddedimg11, window, strides=[1,1,1,1],padding='VALID') - mu1_sq #sigma1方差 73 sigma2_sq = tf.nn.conv2d(paddedimg22, window, strides=[1,1,1,1],padding='VALID') - mu2_sq #sigma2方差 74 sigma12 = tf.nn.conv2d(paddedimg12, window, strides=[1,1,1,1],padding='VALID') - mu1_mu2 #sigma12协方差,乘积的均值减去均值的乘积 75 76 ssim_value = tf.clip_by_value(((2*mu1_mu2 + C1)*(2*sigma12 + C2))/((mu1_sq + mu2_sq + C1)*(sigma1_sq + sigma2_sq + C2)), 0, 1) 77 if cs_map: #只考虑contrast对比度,structure结构,不考虑light亮度 78 cs_map_value = tf.clip_by_value((2*sigma12 + C2)/(sigma1_sq + sigma2_sq + C2), 0, 1) #对比度结构map 79 value = (ssim_value, cs_map_value) 80 else: 81 value = ssim_value 82 if mean_metric: #求取矩阵的均值,否则返回ssim矩阵 83 value = tf.reduce_mean(value) 84 return value 85 86 def tf_ssim_l1_loss(img1, img2, mean_metric=True, filter_size=11, filter_sigma=1.5, alpha=0.84): 87 L1 = tf_gauss_weighted_l1(img1, img2, mean_metric=False, filter_size=filter_size, filter_sigma=filter_sigma) 88 if mean_metric: 89 loss_ssim= 1 - tf_ssim(img1, img2, cs_map=False, mean_metric=True, filter_size=filter_size, filter_sigma=filter_sigma) 90 loss_L1 = tf.reduce_mean(L1) 91 value = loss_ssim * alpha + loss_L1 * (1-alpha) 92 else: 93 loss_ssim= 1 - tf_ssim(img1, img2, cs_map=False, mean_metric=False, filter_size=filter_size, filter_sigma=filter_sigma) 94 value = loss_ssim * alpha + L1 * (1-alpha) 95 96 return value, loss_ssim 97 98 #%% 99 img1 = np.arange(10000,dtype=np.float32).reshape([1,100,100,1]) 100 img2 = np.arange(10000,dtype=np.float32).reshape([1,100,100,1])-1 101 102 l1_loss = tf_ssim_l1_loss(tf.constant(img1),tf.constant(img2)) 103 104 with tf.Session() as sess: 105 print(sess.run(l1_loss))

浙公网安备 33010602011771号