损失函数-ms-ssim和L1的混合
ms-ssim占比alpha
L1占比1-alpha
#%%import tensorflow as tf
import numpy as np
import torch#模仿matlab的fspecial函数,创建滤波算子(计算SSIM用)
def _tf_fspecial_gauss(size, sigma, channels=1):"""Function to mimic the 'fspecial' gaussian MATLAB function"""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)))window = g / tf.reduce_sum(g)return tf.tile(window, (1,1,channels,channels))#高斯卷积
def tf_gauss_conv(img, filter_size=11, filter_sigma=1.5):_, height, width, ch = img.get_shape().as_list()size = min(filter_size, height, width)sigma = size * filter_sigma / filter_size if filter_size else 0window = _tf_fspecial_gauss(size, sigma, ch) # window shape [size, size]padded_img = tf.pad(img, [[0, 0], [size//2, size//2], [size//2, size//2], [0, 0]], mode="CONSTANT")return tf.nn.conv2d(padded_img, window, strides=[1,1,1,1], padding='VALID')#高斯加权的L1正则化
def tf_gauss_weighted_l1(img1, img2, mean_metric=True, filter_size=11, filter_sigma=1.5):diff = tf.abs(img1 - img2)L1 = tf_gauss_conv(diff, filter_size=filter_size, filter_sigma=filter_sigma)if mean_metric:return tf.reduce_mean(L1)else:return L1#计算ssim
def tf_ssim(img1, img2, cs_map=False, mean_metric=True, filter_size=11, filter_sigma=1.5):_, height, width, ch = img1.get_shape().as_list()size = min(filter_size, height, width)sigma = size * filter_sigma / filter_size if filter_size else 0window = _tf_fspecial_gauss(size, sigma, ch) # window shape [size, size]K1 = 0.01K2 = 0.03L = 1 # depth of image (255 in case the image has a differnt scale)C1 = (K1*L)**2C2 = (K2*L)**2#求取滑块内均值Ux Uy,均方值Ux_sqpadded_img1 = tf.pad(img1, [[0, 0], [size//2, size//2], [size//2, size//2], [0, 0]], mode="CONSTANT") #img1 上下左右补零padded_img2 = tf.pad(img2, [[0, 0], [size//2, size//2], [size//2, size//2], [0, 0]], mode="CONSTANT") #img2 上下左右补零mu1 = tf.nn.conv2d(padded_img1, window, strides=[1,1,1,1], padding='VALID') #利用滑动窗口,求取窗口内图像的的加权平均mu2 = tf.nn.conv2d(padded_img2, window, strides=[1,1,1,1], padding='VALID')mu1_sq = mu1*mu1 #img(x,y) Ux*Ux 均方mu2_sq = mu2*mu2 #img(x,y) Uy*Uymu1_mu2 = mu1*mu2 #img(x,y) Ux*Uy#求取方差,方差等于平方的期望减去期望的平方,平方的均值减去均值的平方paddedimg11 = padded_img1*padded_img1paddedimg22 = padded_img2*padded_img2paddedimg12 = padded_img1*padded_img2sigma1_sq = tf.nn.conv2d(paddedimg11, window, strides=[1,1,1,1],padding='VALID') - mu1_sq #sigma1方差sigma2_sq = tf.nn.conv2d(paddedimg22, window, strides=[1,1,1,1],padding='VALID') - mu2_sq #sigma2方差sigma12 = tf.nn.conv2d(paddedimg12, window, strides=[1,1,1,1],padding='VALID') - mu1_mu2 #sigma12协方差,乘积的均值减去均值的乘积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)if cs_map: #只考虑contrast对比度,structure结构,不考虑light亮度cs_map_value = tf.clip_by_value((2*sigma12 + C2)/(sigma1_sq + sigma2_sq + C2), 0, 1) #对比度结构mapvalue = (ssim_value, cs_map_value)else:value = ssim_valueif mean_metric: #求取矩阵的均值,否则返回ssim矩阵value = tf.reduce_mean(value)return value#计算跨尺度结构相似度指数(通过扩大感受野方式)
def tf_ms_ssim(img1, img2, weights=None, mean_metric=False):if weights is None:weights = [1, 1, 1, 1, 1] # [0.0448, 0.2856, 0.3001, 0.2363, 0.1333] #[1, 1, 1, 1, 1] #level = len(weights)sigmas = [0.5]for i in range(level-1):sigmas.append(sigmas[-1]*2)weight = tf.constant(weights, dtype=tf.float32)mssim = []mcs = []for l, sigma in enumerate(sigmas):filter_size = int(max(sigma*4+1, 11))ssim_map, cs_map = tf_ssim(img1, img2, cs_map=True, mean_metric=False, filter_size=filter_size, filter_sigma=sigma)mssim.append(ssim_map)mcs.append(cs_map)# list to tensor of dim D+1value = mssim[level-1]**weight[level-1]for l in range(level):value = value * (mcs[l]**weight[l])if mean_metric:return tf.reduce_mean(value)else:return value#ms-ssim和L1损失函数(SSIM占alpha,loss_L1占1-alpha)
def tf_ms_ssim_l1_loss(img1, img2, mean_metric=True, alpha=0.84):ms_ssim_map = tf_ms_ssim(img1, img2, mean_metric=False)l1_map = tf_gauss_weighted_l1(img1, img2, mean_metric=False, filter_size=33, filter_sigma=8.0)loss_map = (1-ms_ssim_map) * alpha + l1_map * (1-alpha)if mean_metric:return tf.reduce_mean(loss_map)else:return loss_map#%%
img1 = np.arange(10000,dtype=np.float32).reshape([1,100,100,1])
img2 = np.arange(10000,dtype=np.float32).reshape([1,100,100,1])-1ms_ssim_l1_loss = tf_ms_ssim_l1_loss(tf.constant(img1),tf.constant(img2))with tf.Session() as sess:print(sess.run(ms_ssim_l1_loss))
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!