/Lib/EvaluateImage/qssim.m

https://github.com/tingfengainiaini/SRviaMoE · MATLAB · 312 lines · 175 code · 27 blank · 110 comment · 19 complexity · 0a92d0136dfd70062ebc8290578b3be9 MD5 · raw file

  1. function [mqssim, qssim_map] = qssim(img1, img2,ch,sqrt_3, K, window, L)
  2. %========================================================================
  3. %QSSIM Index, Version 1.2
  4. %Copyright(c) 2011 Amir Kolaman
  5. %All Rights Reserved.
  6. %
  7. %----------------------------------------------------------------------
  8. %Permission to use, copy, or modify this software and its documentation
  9. %for educational and research purposes only and without fee is hereby
  10. %granted, provided that this copyright notice and the original authors'
  11. %names appear on all copies and supporting documentation. This program
  12. %shall not be used, rewritten, or adapted as the basis of a commercial
  13. %software or hardware product without first obtaining permission of the
  14. %authors. The authors make no representations about the suitability of
  15. %this software for any purpose. It is provided "as is" without express
  16. %or implied warranty.
  17. %----------------------------------------------------------------------
  18. %This code was modified from the original ssim_index.m downloaded from
  19. %http://www.ece.uwaterloo.ca/~z70wang/research/ssim/
  20. %which is the implementation of
  21. %Z. Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli, "Image quality
  22. %assessment: From error visibility to structural similarity," IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004.
  23. %__________________________________________________________________________
  24. %
  25. %This is an implementation of the algorithm for calculating the
  26. %Quaternion Structural SIMilarity (QSSIM) index between two images. Please refer
  27. %to the following paper:
  28. %
  29. %A. Kolaman, Orly Yadid-Pecht "Quaternion Structural Similarity a New Quality Index for Color Images"
  30. %IEEE Transactios on Image Processing, vol. ??, no. ??, ??. 2011.
  31. %
  32. %Kindly report any suggestions or corrections to kolaman@bgu.ac.il
  33. %
  34. %To use this index you need to first download Quaternion Toolbox for Matlab at
  35. %http://qtfm.sourceforge.net/
  36. %and add it to Matlab's path
  37. %----------------------------------------------------------------------
  38. %% IMG1(N,N) while N an odd number SHOULD BE CHANGED
  39. %Input : (1) img1: the first image being compared
  40. % (2) img2: the second image being compared
  41. %%
  42. % (3) ch: the precent of upsizing chrominance sautration as to detect saturation changes better
  43. % (4) sqrt_3: whether to use normilize by square root of 3
  44. % (5) K: constants in the SSIM index formula (see the above
  45. % reference). defualt value: K = [0.01 0.03]
  46. % (6) window: local window for statistics (see the above
  47. % reference). default widnow is Gaussian given by
  48. % window = fspecial('gaussian', 11, 1.5);
  49. % (7) L: dynamic range of the images. default: L = 255
  50. %
  51. %Output: (1) mqssim: the mean QSSIM index value between 2 images.
  52. % If one of the images being compared is regarded as
  53. % perfect quality, then mqssim can be considered as the
  54. % quality measure of the other image.
  55. % If img1 = img2, then mqssim = 1.
  56. % (2) qqssim_map: the QSSIM index map of the test image. The map
  57. % has a smaller size than the input images. The actual size:
  58. % size(img1) - size(window) + 1.
  59. %
  60. %Default Color image Usage:
  61. % Given 2 test images img1 and img2, whose dynamic range is 0-255
  62. %
  63. % [mqssim qqssim_map] = qssim_index(img1, img2);
  64. %
  65. %Default gray scale image Usage:
  66. % Given 2 test images img1 and img2, whose dynamic range is 0-255, and
  67. % are gray scale (m,n,1) images
  68. %if sqrt_3=1 than use:
  69. % img1_RGB(:,:,3)=img1./sqrt(3);
  70. % img2_RGB(:,:,3)=img2./sqrt(3);
  71. %else
  72. % img1_RGB(:,:,3)=img1;
  73. % img2_RGB(:,:,3)=img2;
  74. % img1_RGB(:,:,2)=img1_RGB(:,:,3);
  75. % img1_RGB(:,:,1)=img1_RGB(:,:,3);
  76. % img2_RGB(:,:,2)=img2_RGB(:,:,3);
  77. % img2_RGB(:,:,1)=img2_RGB(:,:,3);
  78. %
  79. % [mqssim qqssim_map] = qssim_index(img1_RGB, img2_RGB);
  80. %
  81. %Advanced Usage:
  82. % User defined parameters. For example
  83. %
  84. % K = [0.05 0.05];
  85. % window = ones(8);
  86. % L = 100;
  87. % [mqssim qqssim_map] = qssim_index(img1, img2, K, window, L);
  88. %
  89. %See the results:
  90. %
  91. % mqssim %Gives the mqssim value
  92. % imshow(max(0, qqssim_map).^4) %Shows the QSSIM index map
  93. %
  94. %========================================================================
  95. %% making sure the input is in double
  96. img1=double(img1)./256;
  97. img2=double(img2)./256;
  98. %% *******************checking function input settings****************
  99. if (nargin < 2 || nargin > 7)
  100. mqssim = -Inf;
  101. qssim_map = -Inf;
  102. display('parameters are not adaquate');
  103. return;
  104. end
  105. if (nargin == 2)
  106. ch=1;
  107. sqrt_3=1;
  108. window = fspecial('gaussian', 11, 1.5); % creating 11x11 gaussian window
  109. K(1) = 0.01; % default settings
  110. K(2) = 0.03; %
  111. L = 1; %
  112. end
  113. if (size(img1) ~= size(img2))
  114. mqssim = -Inf;
  115. qssim_map = -Inf;
  116. display('images are different in size');
  117. return;
  118. end
  119. [M N] = size(img1(:,:,1));
  120. if (nargin == 4)
  121. if ((M < 11) || (N < 11))
  122. mqssim = -Inf;
  123. qssim_map = -Inf;
  124. return
  125. end
  126. window = fspecial('gaussian', 11, 1.5); % creating 11x11 gaussian window
  127. K(1) = 0.01; % default settings
  128. K(2) = 0.03; %
  129. L = 1; %
  130. end
  131. if (nargin == 5)
  132. if ((M < 11) || (N < 11))
  133. mqssim = -Inf;
  134. qssim_map = -Inf;
  135. return
  136. end
  137. window = fspecial('gaussian', 11, 1.5);
  138. L =1;
  139. if (length(K) == 2)
  140. if (K(1) < 0 || K(2) < 0)
  141. mqssim = -Inf;
  142. qssim_map = -Inf;
  143. return;
  144. end
  145. else
  146. mqssim = -Inf;
  147. qssim_map = -Inf;
  148. return;
  149. end
  150. end
  151. if (nargin == 6)
  152. [H W] = size(window);
  153. if ((H*W) < 4 || (H > M) || (W > N))
  154. mqssim = -Inf;
  155. qssim_map = -Inf;
  156. return
  157. end
  158. L = 1;
  159. if (length(K) == 2)
  160. if (K(1) < 0 || K(2) < 0)
  161. mqssim = -Inf;
  162. qssim_map = -Inf;
  163. return;
  164. end
  165. else
  166. mqssim = -Inf;
  167. qssim_map = -Inf;
  168. return;
  169. end
  170. end
  171. if (nargin == 7)
  172. [H W] = size(window);
  173. if ((H*W) < 4 || (H > M) || (W > N))
  174. mqssim = -Inf;
  175. qssim_map = -Inf;
  176. return
  177. end
  178. if (length(K) == 2)
  179. if (K(1) < 0 || K(2) < 0)
  180. mqssim = -Inf;
  181. qssim_map = -Inf;
  182. return;
  183. end
  184. else
  185. mqssim = -Inf;
  186. qssim_map = -Inf;
  187. return;
  188. end
  189. end
  190. %% ***********************beginning of the code***********************
  191. %$$$$$$$$$$$$$$$$$$$$ Dilating and chrominance channel of both $$$$$$$
  192. %%$$$$$$$$$$$$$$$$$$$$$$$$$$$ images by ch $$$$$$$$$$$$$$$$$$$$$$$$$$$$
  193. img1_L(:,:,3)=img1(:,:,1)/3+img1(:,:,2)/3+img1(:,:,3)/3;
  194. img1_L(:,:,2)=img1_L(:,:,3);
  195. img1_L(:,:,1)=img1_L(:,:,3);
  196. img1_ch=img1-img1_L;
  197. img1=img1_ch.*ch+img1_L;
  198. % img1=img1_ch+img1_L./ch;
  199. img2_L(:,:,3)=img2(:,:,1)/3+img2(:,:,2)/3+img2(:,:,3)/3;
  200. img2_L(:,:,2)=img2_L(:,:,3);
  201. img2_L(:,:,1)=img2_L(:,:,3);
  202. img2_ch=img2-img2_L;
  203. img2=img2_ch.*ch+img2_L;
  204. % img2=img2_ch+img2_L./ch;
  205. %$$$$$$$$$$$$$$$$$$$$ Dilating and chrominance channel of both $$$$$$$
  206. %%$$$$$$$$$$$$$$$$$$$$$$$$$$$ images by ch $$$$$$$$$$$$$$$$$$$$$$$$$$$$
  207. % automatic downsampling
  208. f = max(1,round(min(M,N)/256));
  209. %downsampling by f
  210. %use a simple low-pass filter
  211. if(f>1)
  212. lpf = ones(f,f);
  213. lpf = (1./(f*f))*lpf;
  214. img1 = imfilter(img1,lpf,'symmetric','same');
  215. img2 = imfilter(img2,lpf,'symmetric','same');
  216. img1 = img1(1:f:end,1:f:end,:);
  217. img2 = img2(1:f:end,1:f:end,:);
  218. end
  219. C1 = (K(1)*L)^2;
  220. C2 = (K(2)*L)^2;
  221. C1=quaternion(C1,0,0,0);
  222. C2=quaternion(C2,0,0,0);
  223. window = window/sum(sum(window)); %normalize to sum 1
  224. img1_Q=img_to_Q(img1,sqrt_3);
  225. img2_Q=img_to_Q(img2,sqrt_3);
  226. mu1 = filter2_RGB(img1,window);%gaussian average of all the colors in image 1
  227. mu2 = filter2_RGB(img2,window);%gaussian average of all the colors in image 2
  228. mu1_Q = img_to_Q(mu1,sqrt_3);%convert F image to quaternion
  229. mu2_Q = img_to_Q(mu2,sqrt_3);%convert G image to quaternion
  230. mu1_sq_Q=mu1_Q.*conj(mu1_Q);%compute mu1_squared in quaternions
  231. mu2_sq_Q=mu2_Q.*conj(mu2_Q);%compute mu2_squared in quaternions
  232. mu1_mu2_Q=mu1_Q.*conj(mu2_Q);%compute the correlation between mu1 and mu2 in quaternions
  233. img1_hue_sq_Q=img1_Q.*conj(img1_Q);%compute img1_hue_squared in quaternions
  234. img2_hue_sq_Q=img2_Q.*conj(img2_Q);%compute img2_hue_squared in quaternions
  235. img1_img2_hue_Q=img1_Q.*conj(img2_Q);%compute the correlation between img1_hue and img2_hue.
  236. sigma1_sq_Q = filter2_Q(img1_hue_sq_Q,window)-mu1_sq_Q;%average the hue squared with a gaussian
  237. sigma2_sq_Q = filter2_Q(img2_hue_sq_Q,window)-mu2_sq_Q ;%average the hue squared with a gaussian
  238. sigma12_Q = filter2_Q(img1_img2_hue_Q,window)-mu1_mu2_Q ;%average the hue squared with a gaussian
  239. if (abs(C1) > 0 && abs(C2) > 0)
  240. qssim_map_Q = ((2*mu1_mu2_Q + C1).*(2*conj(sigma12_Q) + C2))./((mu1_sq_Q + mu2_sq_Q + C1).*(conj(sigma1_sq_Q + sigma2_sq_Q) + C2));
  241. qssim_map = abs(qssim_map_Q);
  242. else
  243. numerator1 = 2*mu1_mu2 + C1;
  244. numerator2 = 2*sigma12 + C2;
  245. denominator1 = mu1_sq + mu2_sq + C1;
  246. denominator2 = sigma1_sq + sigma2_sq + C2;
  247. qssim_map = ones(size(mu1));
  248. index = (denominator1.*denominator2 > 0);
  249. qssim_map(index) = (numerator1(index).*numerator2(index))./(denominator1(index).*denominator2(index));
  250. index = (denominator1 ~= 0) & (denominator2 == 0);
  251. qssim_map(index) = numerator1(index)./denominator1(index);
  252. end
  253. mqssim = mean2(qssim_map);
  254. end
  255. function f_img=filter2_RGB(img,window)
  256. %this function performs a gaussian average on an RGB image
  257. f_img(:,:,1) = filter2(window, img(:,:,1), 'valid');%gaussian average of red color in image 1
  258. f_img(:,:,2) = filter2(window, img(:,:,2), 'valid');%gaussian average of green color in image 1
  259. f_img(:,:,3) = filter2(window, img(:,:,3), 'valid');%gaussian average of blue color in image 1
  260. end
  261. function result=filter2_Q(f_Q,window)
  262. % this function does a regular filter2 on every part of the quaternion
  263. % matrix seperatly
  264. temp(:,:,1) = filter2(window, s(f_Q), 'valid');%gaussian average of red color in image 1
  265. temp(:,:,2) = filter2(window, x(f_Q), 'valid');%gaussian average of green color in image 1
  266. temp(:,:,3) = filter2(window, y(f_Q), 'valid');%gaussian average of blue color in image 1
  267. temp(:,:,4) = filter2(window, z(f_Q), 'valid');%gaussian average of blue color in image 1
  268. result = convert(quaternion(temp(:,:,1), ...
  269. temp(:,:,2), ...
  270. temp(:,:,3),...
  271. temp(:,:,4)), 'double');
  272. end
  273. function img_Q=img_to_Q(img,sqrt_3)
  274. % this function convert RGB image to quaternion space
  275. %it converts the image to quaternion and normalizes it to 1
  276. if sqrt_3==1
  277. img_Q = convert(quaternion(img(:,:,1), ...
  278. img(:,:,2), ...
  279. img(:,:,3)), 'double') ./sqrt(3);
  280. else
  281. img_Q = convert(quaternion(img(:,:,1), ...
  282. img(:,:,2), ...
  283. img(:,:,3)), 'double') ;
  284. end
  285. end