前言
最近用ssim測試圖片畫質損傷時,發現matlab自帶ssim與之前一直使用的ssim計算得分有差異,故和同事開始確定差異所在。
不同的SSIM版本
這里提到不同的ssim版本主要基於matlab。如前言所述,主要分為2個實現。
- 版本1:Zhou Wang實現的版本(也是我之前一直用的版本),具體見:
滑鐵盧大學:https://ece.uwaterloo.ca/~z70wang/research/ssim/
紐約大學:http://www.cns.nyu.edu/~lcv/ssim/ - 版本2:matlab2015-ssim(matlab從2014開始加入了ssim)
2個版本的差異
雖然2個版本的代碼實現完全不一樣,但總的說,差異可以歸結為以下幾點:
1. downsample
- Zhou Wang實現版本有downsample,他也推薦這么做,原因如下:
The precisely right scale depends on both the image resolution and the viewing distance and is usually difficult to be obtained. In practice, we suggest to use the following empirical formula to determine the scale for images viewed from a typical distance (say 3~5 times of the image height or width): 1) Let F = max(1, round(N/256)), where N is the number of pixels in image height (or width); 2) Average local F by F pixels and then downsample the image by a factor of F; and 3) apply the ssim_index.m program. For example, for an 512 by 512 image, F = max(1, round(512/256)) = 2, so the image should be averaged within a 2 by 2 window and downsampled by a factor of 2 before applying ssim_index.m.
上面這段意思:人看圖片時,與圖片有一定距離(相當於圖片縮小),一些細節可被忽略,如果進行downsample,除了減低運算復雜度,還能更貼合人的主觀觀看感受。
-
涉及downsample的代碼部分:
% automatic downsampling f = max(1,round(min(M,N)/256)); %downsampling by f %use a simple low-pass filter if(f>1) lpf = ones(f,f); lpf = lpf/sum(lpf(:)); img1 = imfilter(img1,lpf,'symmetric','same'); img2 = imfilter(img2,lpf,'symmetric','same'); img1 = img1(1:f:end,1:f:end); img2 = img2(1:f:end,1:f:end); end
-
由於Zhou Wang版ssim對比時,原圖與失真圖都做了downsample(縮小),其產生的影響是:
- downsample后的相似度 比 不做downsample的相似度 要高;
- 損失程度不同2張失真圖,在downsample后進行ssim,2者相似度差距減少;
downsample是導致 Zhou Wang版本 與 matlab官方版本 計算結果相差較大的主要原因。 而大學官網上其實也提供了Zhou Wang實現的非downsample版本,只不過名字是: ssim_index.m。
2. 濾波部分
- Zhou Wang版本去掉downsample后,和matlab官方的結果還有約±0.002差距,其原因主要是濾波部分存在差異。
- 濾波參數:
- 輸入矩陣(圖像)
- 這個是我們傳入的,不存差異;
- 濾波掩模
-
Zhou Wang版本
代碼:
-
- 輸入矩陣(圖像)
- 濾波參數:
window = fspecial('gaussian', 11, 1.5);
% 算子類型:gaussian(高斯)
% 模版尺寸:11*11
% 標准差:1.5
% 以上參數皆hardcode
```
- matlab版本
代碼:
```js
filtRadius = ceil(radius3);
filtSize = 2filtRadius + 1;
if (N < 3)
gaussFilt = fspecial('gaussian',[filtSize filtSize],radius); % 2D mask
else
...% 3D mask
end
% 算子類型:gaussian(高斯)
% 模版尺寸:[filtSize filtSize],使用默認值計算后,為:11*11矩陣;
% 標准差:radius,默認值為:1.5;
% 以上參數皆可通過傳參改變
```
- <font color=#FF4500>**濾波模式**</font>
- Zhou Wang版本:
使用互相關(correlation)
- matlab版本:
使用卷積(convolution)
- <font color=#FF4500>**邊界填充方式**</font>
- Zhou Wang版本:
邊界通過填充0來擴展,例如:

- matlab版本:
通過復制外邊界的值來擴展,例如:

- <font color=#FF4500>**結果矩陣**</font>
- Zhou Wang版本
只返回濾波時未使用邊緣補 0 部分進行計算的結果部分(返回矩陣小於輸入矩陣),例如:

- matlab版本
與輸入矩陣大小一致,例如:

由於以上差異,<font color=#FF4500>導致了 Zhou Wang版ssim 與 matlab官方ssim 在計算結果上存在輕微差距</font>。
3. 2D與3D圖片支持
- matlab官方的ssim,除了支持2D圖片,外還支持3D圖片;而Zhou Wang版本只支持2D圖片。
- 2D圖片
ssim只支持對2D灰度圖進行結構相似度計算,rgb圖(彩圖)需轉換為灰度圖才能計算(可調用rgb2gray進行轉換)。 - 3D圖片
3D圖片現在在醫療領域用得較多:
在matlab2015中,如果直接讀入rgb圖(不轉換為灰度)會被認為是3D圖,這個比較坑爹,ssim運行不報錯,但結果卻是完全錯的。