@@ -10,74 +10,97 @@ At the same time, in this implementation, I have dealt with the problem that the
1010
1111> When comparing images, the mean squared error (MSE)–while simple to implement–is not highly indicative of perceived similarity. Structural similarity aims to address this shortcoming by taking texture into account. More details can be seen at https://scikit-image.org/docs/dev/auto_examples/transform/plot_ssim.html?highlight=structure+similarity
1212
13- ![ results] ( https://user-images.githubusercontent.com/26847524/174805728-81e8502b-2ecb-4b40-a2c4-b4f1e2361ea9 .png )
13+ ![ results] ( https://user-images.githubusercontent.com/26847524/175031400-92426661-4536-43c7-8f6e-5c470fb9ccb5 .png )
1414
1515``` python
1616import matplotlib.pyplot as plt
1717import numpy as np
1818import torch
1919import torch.nn.functional as F
20- from pytorch_ssim import SSIM , ssim
20+ from lartpang_ssim import SSIM
21+ from po_hsun_su_ssim import SSIM as PoHsunSuSSIM
22+ from vainf_ssim import MS_SSIM as VainFMSSSIM
23+ from vainf_ssim import SSIM as VainFSSIM
2124from skimage import data, img_as_float
2225
2326img = img_as_float(data.camera())
2427rows, cols = img.shape
2528
26- noise = np.ones_like(img) * 0.2 * (img.max() - img.min())
29+ noise = np.ones_like(img) * 0.3 * (img.max() - img.min())
2730rng = np.random.default_rng()
2831noise[rng.random(size = noise.shape) > 0.5 ] *= - 1
2932
3033img_noise = img + noise
31- img_const = img + abs (noise )
34+ img_const = np.zeros_like(img )
3235
3336img_tensor = torch.from_numpy(img).unsqueeze(0 ).unsqueeze(0 ).float()
3437img_noise_tensor = torch.from_numpy(img_noise).unsqueeze(0 ).unsqueeze(0 ).float()
3538img_const_tensor = torch.from_numpy(img_const).unsqueeze(0 ).unsqueeze(0 ).float()
3639
37- fig, axes = plt.subplots(nrows = 2 , ncols = 3 , figsize = (10 , 8 ), sharex = True , sharey = True )
40+ fig, axes = plt.subplots(nrows = 1 , ncols = 3 , figsize = (15 , 7 ) )
3841ax = axes.ravel()
3942
4043mse_none = F.mse_loss(img_tensor, img_tensor, reduction = " mean" )
41- ssim_none = ssim(img_tensor, img_tensor, L = img_tensor.max() - img_tensor.min())
42-
4344mse_noise = F.mse_loss(img_tensor, img_noise_tensor, reduction = " mean" )
44- ssim_noise = ssim(img_tensor, img_noise_tensor, L = img_noise_tensor.max() - img_noise_tensor.min())
45-
4645mse_const = F.mse_loss(img_tensor, img_const_tensor, reduction = " mean" )
47- ssim_const = ssim(img_tensor, img_const_tensor, L = img_const_tensor.max() - img_const_tensor.min())
46+
47+ # https://github.com/VainF/pytorch-msssim
48+ vainf_ssim_none = VainFSSIM(channel = 1 , data_range = 1 )(img_tensor, img_tensor)
49+ vainf_ssim_noise = VainFSSIM(channel = 1 , data_range = 1 )(img_tensor, img_noise_tensor)
50+ vainf_ssim_const = VainFSSIM(channel = 1 , data_range = 1 )(img_tensor, img_const_tensor)
51+ vainf_ms_ssim_none = VainFMSSSIM(channel = 1 , data_range = 1 )(img_tensor, img_tensor)
52+ vainf_ms_ssim_noise = VainFMSSSIM(channel = 1 , data_range = 1 )(img_tensor, img_noise_tensor)
53+ vainf_ms_ssim_const = VainFMSSSIM(channel = 1 , data_range = 1 )(img_tensor, img_const_tensor)
54+
55+ # use the settings of https://github.com/VainF/pytorch-msssim
56+ ssim_none_0 = SSIM(return_msssim = False , L = 1 , padding = 0 , ensemble_kernel = False )(img_tensor, img_tensor)
57+ ssim_noise_0 = SSIM(return_msssim = False , L = 1 , padding = 0 , ensemble_kernel = False )(img_tensor, img_noise_tensor)
58+ ssim_const_0 = SSIM(return_msssim = False , L = 1 , padding = 0 , ensemble_kernel = False )(img_tensor, img_const_tensor)
59+ ms_ssim_none_0 = SSIM(return_msssim = True , L = 1 , padding = 0 , ensemble_kernel = False )(img_tensor, img_tensor)
60+ ms_ssim_noise_0 = SSIM(return_msssim = True , L = 1 , padding = 0 , ensemble_kernel = False )(img_tensor, img_noise_tensor)
61+ ms_ssim_const_0 = SSIM(return_msssim = True , L = 1 , padding = 0 , ensemble_kernel = False )(img_tensor, img_const_tensor)
62+
63+ # https://github.com/Po-Hsun-Su/pytorch-ssim
64+ pohsunsu_ssim_none = PoHsunSuSSIM()(img_tensor, img_tensor)
65+ pohsunsu_ssim_noise = PoHsunSuSSIM()(img_tensor, img_noise_tensor)
66+ pohsunsu_ssim_const = PoHsunSuSSIM()(img_tensor, img_const_tensor)
67+
68+ # use the settings of https://github.com/Po-Hsun-Su/pytorch-ssim
69+ ssim_none_1 = SSIM(return_msssim = False , L = 1 , padding = None , ensemble_kernel = True )(img_tensor, img_tensor)
70+ ssim_noise_1 = SSIM(return_msssim = False , L = 1 , padding = None , ensemble_kernel = True )(img_tensor, img_noise_tensor)
71+ ssim_const_1 = SSIM(return_msssim = False , L = 1 , padding = None , ensemble_kernel = True )(img_tensor, img_const_tensor)
72+
4873
4974ax[0 ].imshow(img, cmap = plt.cm.gray, vmin = 0 , vmax = 1 )
50- ax[0 ].set_xlabel(f " MSE: { mse_none:.2f } , SSIM: { ssim_none:.2f } " )
75+ ax[0 ].set_xlabel(
76+ f " MSE: { mse_none:.6f } \n "
77+ f " SSIM { ssim_none_0:.6f } , MS-SSIM { ms_ssim_none_0:.6f } \n "
78+ f " (VainF) SSIM: { vainf_ssim_none:.6f } , MS-SSIM { vainf_ms_ssim_none:.6f } \n "
79+ f " SSIM { ssim_none_1:.6f } \n "
80+ f " (PoHsunSu) SSIM: { pohsunsu_ssim_none:.6f } \n "
81+ )
5182ax[0 ].set_title(" Original image" )
5283
5384ax[1 ].imshow(img_noise, cmap = plt.cm.gray, vmin = 0 , vmax = 1 )
54- ax[1 ].set_xlabel(f " MSE: { mse_noise:.2f } , SSIM: { ssim_noise:.2f } " )
85+ ax[1 ].set_xlabel(
86+ f " MSE: { mse_noise:.6f } \n "
87+ f " SSIM { ssim_noise_0:.6f } , MS-SSIM { ms_ssim_noise_0:.6f } \n "
88+ f " (VainF) SSIM: { vainf_ssim_noise:.6f } , MS-SSIM { vainf_ms_ssim_noise:.6f } \n "
89+ f " SSIM { ssim_noise_1:.6f } \n "
90+ f " (PoHsunSu) SSIM: { pohsunsu_ssim_noise:.6f } \n "
91+ )
5592ax[1 ].set_title(" Image with noise" )
5693
5794ax[2 ].imshow(img_const, cmap = plt.cm.gray, vmin = 0 , vmax = 1 )
58- ax[2 ].set_xlabel(f " MSE: { mse_const:.2f } , SSIM: { ssim_const:.2f } " )
95+ ax[2 ].set_xlabel(
96+ f " MSE: { mse_const:.6f } \n "
97+ f " SSIM { ssim_const_0:.6f } , MS-SSIM { ms_ssim_const_0:.6f } \n "
98+ f " (VainF) SSIM: { vainf_ssim_const:.6f } , MS-SSIM { vainf_ms_ssim_const:.6f } \n "
99+ f " SSIM { ssim_const_1:.6f } \n "
100+ f " (PoHsunSu) SSIM: { pohsunsu_ssim_const:.6f } \n "
101+ )
59102ax[2 ].set_title(" Image plus constant" )
60103
61- mse_none = F.mse_loss(img_tensor, img_tensor, reduction = " mean" )
62- ssim_none = SSIM(L = img_tensor.max() - img_tensor.min())(img_tensor, img_tensor)
63-
64- mse_noise = F.mse_loss(img_tensor, img_noise_tensor, reduction = " mean" )
65- ssim_noise = SSIM(L = img_noise_tensor.max() - img_noise_tensor.min())(img_tensor, img_noise_tensor)
66-
67- mse_const = F.mse_loss(img_tensor, img_const_tensor, reduction = " mean" )
68- ssim_const = SSIM(L = img_const_tensor.max() - img_const_tensor.min())(img_tensor, img_const_tensor)
69-
70- ax[3 ].imshow(img, cmap = plt.cm.gray, vmin = 0 , vmax = 1 )
71- ax[3 ].set_xlabel(f " MSE: { mse_none:.2f } , SSIM: { ssim_none:.2f } " )
72- ax[3 ].set_title(" Original image" )
73-
74- ax[4 ].imshow(img_noise, cmap = plt.cm.gray, vmin = 0 , vmax = 1 )
75- ax[4 ].set_xlabel(f " MSE: { mse_noise:.2f } , SSIM: { ssim_noise:.2f } " )
76- ax[4 ].set_title(" Image with noise" )
77-
78- ax[5 ].imshow(img_const, cmap = plt.cm.gray, vmin = 0 , vmax = 1 )
79- ax[5 ].set_xlabel(f " MSE: { mse_const:.2f } , SSIM: { ssim_const:.2f } " )
80- ax[5 ].set_title(" Image plus constant" )
81104
82105[ax[i].set(xticklabels = [], yticklabels = [], xticks = [], yticks = []) for i in range (len (axes))]
83106
@@ -247,5 +270,6 @@ plt.savefig("prediction.png")
247270## Reference
248271
249272- https://github.com/Po-Hsun-Su/pytorch-ssim
273+ - https://github.com/VainF/pytorch-msssim
250274- https://scikit-image.org/docs/dev/auto_examples/transform/plot_ssim.html?highlight=structure+similarity
251275- Z. Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli, “Image quality assessment: From error visibility to structural similarity,” IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004.
0 commit comments