当前位置:   article > 正文

损失函数-MS-SSIM(multiscale structure similarity)跨尺度结构相似性

ms-ssim

 参考资料:https://blog.csdn.net/weixin_41923961/article/details/84795832

MS-SSIM的考虑了不同尺度下结构相似程度

本文在SSIM的基础上继续研究,通过不同大小的滤波算子来扩大感受野,模拟尺度缩小的情况。

另外,先求取一次SSIM,再考虑其余四次的contrast 和 structure map

 

基于tensorflow的代码:

  1. #%%
  2. import tensorflow as tf
  3. import numpy as np
  4. import torch
  5. #%%
  6. #模仿matlab的fspecial函数,创建滤波算子(计算SSIM用)
  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. x_data = np.expand_dims(x_data, axis=-1)
  13. x_data = np.expand_dims(x_data, axis=-1)
  14. y_data = np.expand_dims(y_data, axis=-1)
  15. y_data = np.expand_dims(y_data, axis=-1)
  16. x = tf.constant(x_data, dtype=tf.float32)
  17. y = tf.constant(y_data, dtype=tf.float32)
  18. g = tf.exp(-((x**2 + y**2)/(2.0*sigma**2)))
  19. window = g / tf.reduce_sum(g)
  20. return tf.tile(window, (1,1,channels,channels))
  21. #计算ssim
  22. def tf_ssim(img1, img2, cs_map=False, mean_metric=True, filter_size=11, filter_sigma=1.5):
  23. _, height, width, ch = img1.get_shape().as_list()
  24. size = min(filter_size, height, width)
  25. sigma = size * filter_sigma / filter_size if filter_size else 0
  26. window = _tf_fspecial_gauss(size, sigma, ch) # window shape [size, size]
  27. K1 = 0.01
  28. K2 = 0.03
  29. L = 1 # depth of image (255 in case the image has a differnt scale)
  30. C1 = (K1*L)**2
  31. C2 = (K2*L)**2
  32. #求取滑块内均值Ux Uy,均方值Ux_sq
  33. padded_img1 = tf.pad(img1, [[0, 0], [size//2, size//2], [size//2, size//2], [0, 0]], mode="CONSTANT") #img1 上下左右补零
  34. padded_img2 = tf.pad(img2, [[0, 0], [size//2, size//2], [size//2, size//2], [0, 0]], mode="CONSTANT") #img2 上下左右补零
  35. mu1 = tf.nn.conv2d(padded_img1, window, strides=[1,1,1,1], padding='VALID') #利用滑动窗口,求取窗口内图像的的加权平均
  36. mu2 = tf.nn.conv2d(padded_img2, window, strides=[1,1,1,1], padding='VALID')
  37. mu1_sq = mu1*mu1 #img(x,y) Ux*Ux 均方
  38. mu2_sq = mu2*mu2 #img(x,y) Uy*Uy
  39. mu1_mu2 = mu1*mu2 #img(x,y) Ux*Uy
  40. #求取方差,方差等于平方的期望减去期望的平方,平方的均值减去均值的平方
  41. paddedimg11 = padded_img1*padded_img1
  42. paddedimg22 = padded_img2*padded_img2
  43. paddedimg12 = padded_img1*padded_img2
  44. sigma1_sq = tf.nn.conv2d(paddedimg11, window, strides=[1,1,1,1],padding='VALID') - mu1_sq #sigma1方差
  45. sigma2_sq = tf.nn.conv2d(paddedimg22, window, strides=[1,1,1,1],padding='VALID') - mu2_sq #sigma2方差
  46. sigma12 = tf.nn.conv2d(paddedimg12, window, strides=[1,1,1,1],padding='VALID') - mu1_mu2 #sigma12协方差,乘积的均值减去均值的乘积
  47. 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)
  48. if cs_map: #只考虑contrast对比度,structure结构,不考虑light亮度
  49. cs_map_value = tf.clip_by_value((2*sigma12 + C2)/(sigma1_sq + sigma2_sq + C2), 0, 1) #对比度结构map
  50. value = (ssim_value, cs_map_value)
  51. else:
  52. value = ssim_value
  53. if mean_metric: #求取矩阵的均值,否则返回ssim矩阵
  54. value = tf.reduce_mean(value)
  55. return value
  56. #计算跨尺度结构相似度指数(通过缩放原始图像方式)
  57. def tf_ms_ssim_resize(img1, img2, weights=None, return_ssim_map=None, filter_size=11, filter_sigma=1.5):
  58. if weights is None:
  59. weights = [0.0448, 0.2856, 0.3001, 0.2363, 0.1333] #论文中提到的几个参数
  60. level = len(weights)
  61. assert return_ssim_map is None or return_ssim_map < level
  62. weight = tf.constant(weights, dtype=tf.float32)
  63. mssim = []
  64. mcs = []
  65. _, h, w, _ = img1.get_shape().as_list()
  66. for l in range(level):
  67. ssim_map, cs_map = tf_ssim(img1, img2, cs_map=True, mean_metric=False, filter_size=filter_size, filter_sigma=filter_sigma)
  68. if return_ssim_map == l:
  69. return_ssim_map = tf.image.resize_images(ssim_map, size=(h, w), method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
  70. mssim.append(tf.reduce_mean(ssim_map))
  71. mcs.append(tf.reduce_mean(cs_map))
  72. img1 = tf.nn.avg_pool(img1, [1,2,2,1], [1,2,2,1], padding='SAME')
  73. img2 = tf.nn.avg_pool(img2, [1,2,2,1], [1,2,2,1], padding='SAME')
  74. # list to tensor of dim D+1
  75. mssim = tf.stack(mssim, axis=0)
  76. mcs = tf.stack(mcs, axis=0)
  77. #ms-ssim公式
  78. value = tf.reduce_prod(mcs[0:level-1]**weight[0:level-1])*(mssim[level-1]**weight[level-1])
  79. if return_ssim_map is not None:
  80. return value, return_ssim_map
  81. else:
  82. return value
  83. #计算跨尺度结构相似度指数(通过扩大感受野方式)
  84. def tf_ms_ssim(img1, img2, weights=None, mean_metric=False):
  85. if weights is None:
  86. weights = [1, 1, 1, 1, 1] # [0.0448, 0.2856, 0.3001, 0.2363, 0.1333] #[1, 1, 1, 1, 1] #
  87. level = len(weights)
  88. sigmas = [0.5]
  89. for i in range(level-1):
  90. sigmas.append(sigmas[-1]*2)
  91. weight = tf.constant(weights, dtype=tf.float32)
  92. mssim = []
  93. mcs = []
  94. for l, sigma in enumerate(sigmas):
  95. filter_size = int(max(sigma*4+1, 11))
  96. ssim_map, cs_map = tf_ssim(img1, img2, cs_map=True, mean_metric=False, filter_size=filter_size, filter_sigma=sigma)
  97. mssim.append(ssim_map)
  98. mcs.append(cs_map)
  99. # list to tensor of dim D+1
  100. value = mssim[level-1]**weight[level-1]
  101. for l in range(level):
  102. value = value * (mcs[l]**weight[l])
  103. if mean_metric:
  104. return tf.reduce_mean(value)
  105. else:
  106. return value
  107. img1 = np.arange(10000,dtype=np.float32).reshape([1,100,100,1])
  108. img2 = np.arange(10000,dtype=np.float32).reshape([1,100,100,1])
  109. with tf.Session() as sess:
  110. value = tf_ms_ssim(tf.constant(img1),tf.constant(img2),mean_metric=True)
  111. value1 = tf_ms_ssim_resize(tf.constant(img1),tf.constant(img2))
  112. print(sess.run(value))
  113. print(sess.run(value1))

输出结果:

1.0

1.0

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/192975
推荐阅读
相关标签
  

闽ICP备14008679号