损失函数-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))

 

posted @ 2021-12-28 21:39  咖啡陪你  阅读(661)  评论(0)    收藏  举报