idamnjanovic@38
|
1 function [mssim, ssim_map] = ssim_index(img1, img2, K, window, L)
|
idamnjanovic@38
|
2
|
idamnjanovic@38
|
3 %========================================================================
|
idamnjanovic@38
|
4 %SSIM Index, Version 1.0
|
idamnjanovic@38
|
5 %Copyright(c) 2003 Zhou Wang
|
idamnjanovic@38
|
6 %All Rights Reserved.
|
idamnjanovic@38
|
7 %
|
idamnjanovic@38
|
8 %The author is with Howard Hughes Medical Institute, and Laboratory
|
idamnjanovic@38
|
9 %for Computational Vision at Center for Neural Science and Courant
|
idamnjanovic@38
|
10 %Institute of Mathematical Sciences, New York University.
|
idamnjanovic@38
|
11 %
|
idamnjanovic@38
|
12 %----------------------------------------------------------------------
|
idamnjanovic@38
|
13 %Permission to use, copy, or modify this software and its documentation
|
idamnjanovic@38
|
14 %for educational and research purposes only and without fee is hereby
|
idamnjanovic@38
|
15 %granted, provided that this copyright notice and the original authors'
|
idamnjanovic@38
|
16 %names appear on all copies and supporting documentation. This program
|
idamnjanovic@38
|
17 %shall not be used, rewritten, or adapted as the basis of a commercial
|
idamnjanovic@38
|
18 %software or hardware product without first obtaining permission of the
|
idamnjanovic@38
|
19 %authors. The authors make no representations about the suitability of
|
idamnjanovic@38
|
20 %this software for any purpose. It is provided "as is" without express
|
idamnjanovic@38
|
21 %or implied warranty.
|
idamnjanovic@38
|
22 %----------------------------------------------------------------------
|
idamnjanovic@38
|
23 %
|
idamnjanovic@38
|
24 %This is an implementation of the algorithm for calculating the
|
idamnjanovic@38
|
25 %Structural SIMilarity (SSIM) index between two images. Please refer
|
idamnjanovic@38
|
26 %to the following paper:
|
idamnjanovic@38
|
27 %
|
idamnjanovic@38
|
28 %Z. Wang, A. C. Bovik, H. R. Sheikh, and E. P. Simoncelli, "Image
|
idamnjanovic@38
|
29 %quality assessment: From error measurement to structural similarity"
|
idamnjanovic@38
|
30 %IEEE Transactios on Image Processing, vol. 13, no. 1, Jan. 2004.
|
idamnjanovic@38
|
31 %
|
idamnjanovic@38
|
32 %Kindly report any suggestions or corrections to zhouwang@ieee.org
|
idamnjanovic@38
|
33 %
|
idamnjanovic@38
|
34 %----------------------------------------------------------------------
|
idamnjanovic@38
|
35 %
|
idamnjanovic@38
|
36 %Input : (1) img1: the first image being compared
|
idamnjanovic@38
|
37 % (2) img2: the second image being compared
|
idamnjanovic@38
|
38 % (3) K: constants in the SSIM index formula (see the above
|
idamnjanovic@38
|
39 % reference). defualt value: K = [0.01 0.03]
|
idamnjanovic@38
|
40 % (4) window: local window for statistics (see the above
|
idamnjanovic@38
|
41 % reference). default widnow is Gaussian given by
|
idamnjanovic@38
|
42 % window = fspecial('gaussian', 11, 1.5);
|
idamnjanovic@38
|
43 % (5) L: dynamic range of the images. default: L = 255
|
idamnjanovic@38
|
44 %
|
idamnjanovic@38
|
45 %Output: (1) mssim: the mean SSIM index value between 2 images.
|
idamnjanovic@38
|
46 % If one of the images being compared is regarded as
|
idamnjanovic@38
|
47 % perfect quality, then mssim can be considered as the
|
idamnjanovic@38
|
48 % quality measure of the other image.
|
idamnjanovic@38
|
49 % If img1 = img2, then mssim = 1.
|
idamnjanovic@38
|
50 % (2) ssim_map: the SSIM index map of the test image. The map
|
idamnjanovic@38
|
51 % has a smaller size than the input images. The actual size:
|
idamnjanovic@38
|
52 % size(img1) - size(window) + 1.
|
idamnjanovic@38
|
53 %
|
idamnjanovic@38
|
54 %Default Usage:
|
idamnjanovic@38
|
55 % Given 2 test images img1 and img2, whose dynamic range is 0-255
|
idamnjanovic@38
|
56 %
|
idamnjanovic@38
|
57 % [mssim ssim_map] = ssim_index(img1, img2);
|
idamnjanovic@38
|
58 %
|
idamnjanovic@38
|
59 %Advanced Usage:
|
idamnjanovic@38
|
60 % User defined parameters. For example
|
idamnjanovic@38
|
61 %
|
idamnjanovic@38
|
62 % K = [0.05 0.05];
|
idamnjanovic@38
|
63 % window = ones(8);
|
idamnjanovic@38
|
64 % L = 100;
|
idamnjanovic@38
|
65 % [mssim ssim_map] = ssim_index(img1, img2, K, window, L);
|
idamnjanovic@38
|
66 %
|
idamnjanovic@38
|
67 %See the results:
|
idamnjanovic@38
|
68 %
|
idamnjanovic@38
|
69 % mssim %Gives the mssim value
|
idamnjanovic@38
|
70 % imshow(max(0, ssim_map).^4) %Shows the SSIM index map
|
idamnjanovic@38
|
71 %
|
idamnjanovic@38
|
72 %========================================================================
|
idamnjanovic@38
|
73
|
idamnjanovic@38
|
74
|
idamnjanovic@38
|
75 if (nargin < 2 || nargin > 5)
|
idamnjanovic@38
|
76 ssim_index = -Inf;
|
idamnjanovic@38
|
77 ssim_map = -Inf;
|
idamnjanovic@38
|
78 return;
|
idamnjanovic@38
|
79 end
|
idamnjanovic@38
|
80
|
idamnjanovic@38
|
81 if (size(img1) ~= size(img2))
|
idamnjanovic@38
|
82 ssim_index = -Inf;
|
idamnjanovic@38
|
83 ssim_map = -Inf;
|
idamnjanovic@38
|
84 return;
|
idamnjanovic@38
|
85 end
|
idamnjanovic@38
|
86
|
idamnjanovic@38
|
87 [M N] = size(img1);
|
idamnjanovic@38
|
88
|
idamnjanovic@38
|
89 if (nargin == 2)
|
idamnjanovic@38
|
90 if ((M < 11) || (N < 11))
|
idamnjanovic@38
|
91 ssim_index = -Inf;
|
idamnjanovic@38
|
92 ssim_map = -Inf;
|
idamnjanovic@38
|
93 return
|
idamnjanovic@38
|
94 end
|
idamnjanovic@38
|
95 window = fspecial('gaussian', 11, 1.5); %
|
idamnjanovic@38
|
96 K(1) = 0.01; % default settings
|
idamnjanovic@38
|
97 K(2) = 0.03; %
|
idamnjanovic@38
|
98 L = 255; %
|
idamnjanovic@38
|
99 end
|
idamnjanovic@38
|
100
|
idamnjanovic@38
|
101 if (nargin == 3)
|
idamnjanovic@38
|
102 if ((M < 11) || (N < 11))
|
idamnjanovic@38
|
103 ssim_index = -Inf;
|
idamnjanovic@38
|
104 ssim_map = -Inf;
|
idamnjanovic@38
|
105 return
|
idamnjanovic@38
|
106 end
|
idamnjanovic@38
|
107 window = fspecial('gaussian', 11, 1.5);
|
idamnjanovic@38
|
108 L = 255;
|
idamnjanovic@38
|
109 if (length(K) == 2)
|
idamnjanovic@38
|
110 if (K(1) < 0 || K(2) < 0)
|
idamnjanovic@38
|
111 ssim_index = -Inf;
|
idamnjanovic@38
|
112 ssim_map = -Inf;
|
idamnjanovic@38
|
113 return;
|
idamnjanovic@38
|
114 end
|
idamnjanovic@38
|
115 else
|
idamnjanovic@38
|
116 ssim_index = -Inf;
|
idamnjanovic@38
|
117 ssim_map = -Inf;
|
idamnjanovic@38
|
118 return;
|
idamnjanovic@38
|
119 end
|
idamnjanovic@38
|
120 end
|
idamnjanovic@38
|
121
|
idamnjanovic@38
|
122 if (nargin == 4)
|
idamnjanovic@38
|
123 [H W] = size(window);
|
idamnjanovic@38
|
124 if ((H*W) < 4 || (H > M) || (W > N))
|
idamnjanovic@38
|
125 ssim_index = -Inf;
|
idamnjanovic@38
|
126 ssim_map = -Inf;
|
idamnjanovic@38
|
127 return
|
idamnjanovic@38
|
128 end
|
idamnjanovic@38
|
129 L = 255;
|
idamnjanovic@38
|
130 if (length(K) == 2)
|
idamnjanovic@38
|
131 if (K(1) < 0 || K(2) < 0)
|
idamnjanovic@38
|
132 ssim_index = -Inf;
|
idamnjanovic@38
|
133 ssim_map = -Inf;
|
idamnjanovic@38
|
134 return;
|
idamnjanovic@38
|
135 end
|
idamnjanovic@38
|
136 else
|
idamnjanovic@38
|
137 ssim_index = -Inf;
|
idamnjanovic@38
|
138 ssim_map = -Inf;
|
idamnjanovic@38
|
139 return;
|
idamnjanovic@38
|
140 end
|
idamnjanovic@38
|
141 end
|
idamnjanovic@38
|
142
|
idamnjanovic@38
|
143 if (nargin == 5)
|
idamnjanovic@38
|
144 [H W] = size(window);
|
idamnjanovic@38
|
145 if ((H*W) < 4 || (H > M) || (W > N))
|
idamnjanovic@38
|
146 ssim_index = -Inf;
|
idamnjanovic@38
|
147 ssim_map = -Inf;
|
idamnjanovic@38
|
148 return
|
idamnjanovic@38
|
149 end
|
idamnjanovic@38
|
150 if (length(K) == 2)
|
idamnjanovic@38
|
151 if (K(1) < 0 || K(2) < 0)
|
idamnjanovic@38
|
152 ssim_index = -Inf;
|
idamnjanovic@38
|
153 ssim_map = -Inf;
|
idamnjanovic@38
|
154 return;
|
idamnjanovic@38
|
155 end
|
idamnjanovic@38
|
156 else
|
idamnjanovic@38
|
157 ssim_index = -Inf;
|
idamnjanovic@38
|
158 ssim_map = -Inf;
|
idamnjanovic@38
|
159 return;
|
idamnjanovic@38
|
160 end
|
idamnjanovic@38
|
161 end
|
idamnjanovic@38
|
162
|
idamnjanovic@38
|
163 C1 = (K(1)*L)^2;
|
idamnjanovic@38
|
164 C2 = (K(2)*L)^2;
|
idamnjanovic@38
|
165 window = window/sum(sum(window));
|
idamnjanovic@38
|
166 img1 = double(img1);
|
idamnjanovic@38
|
167 img2 = double(img2);
|
idamnjanovic@38
|
168
|
idamnjanovic@38
|
169 mu1 = filter2(window, img1, 'valid');
|
idamnjanovic@38
|
170 mu2 = filter2(window, img2, 'valid');
|
idamnjanovic@38
|
171 mu1_sq = mu1.*mu1;
|
idamnjanovic@38
|
172 mu2_sq = mu2.*mu2;
|
idamnjanovic@38
|
173 mu1_mu2 = mu1.*mu2;
|
idamnjanovic@38
|
174 sigma1_sq = filter2(window, img1.*img1, 'valid') - mu1_sq;
|
idamnjanovic@38
|
175 sigma2_sq = filter2(window, img2.*img2, 'valid') - mu2_sq;
|
idamnjanovic@38
|
176 sigma12 = filter2(window, img1.*img2, 'valid') - mu1_mu2;
|
idamnjanovic@38
|
177
|
idamnjanovic@38
|
178 if (C1 > 0 & C2 > 0)
|
idamnjanovic@38
|
179 ssim_map = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))./((mu1_sq + mu2_sq + C1).*(sigma1_sq + sigma2_sq + C2));
|
idamnjanovic@38
|
180 else
|
idamnjanovic@38
|
181 numerator1 = 2*mu1_mu2 + C1;
|
idamnjanovic@38
|
182 numerator2 = 2*sigma12 + C2;
|
idamnjanovic@38
|
183 denominator1 = mu1_sq + mu2_sq + C1;
|
idamnjanovic@38
|
184 denominator2 = sigma1_sq + sigma2_sq + C2;
|
idamnjanovic@38
|
185 ssim_map = ones(size(mu1));
|
idamnjanovic@38
|
186 index = (denominator1.*denominator2 > 0);
|
idamnjanovic@38
|
187 ssim_map(index) = (numerator1(index).*numerator2(index))./(denominator1(index).*denominator2(index));
|
idamnjanovic@38
|
188 index = (denominator1 ~= 0) & (denominator2 == 0);
|
idamnjanovic@38
|
189 ssim_map(index) = numerator1(index)./denominator1(index);
|
idamnjanovic@38
|
190 end
|
idamnjanovic@38
|
191
|
idamnjanovic@38
|
192 mssim = mean2(ssim_map);
|
idamnjanovic@38
|
193
|
idamnjanovic@38
|
194 return |