前言
最近用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者相似度差距减少;
2. 滤波部分
- Zhou Wang版本去掉downsample后,和matlab官方的结果还有约±0.002差距,其原因主要是滤波部分存在差异。
- 滤波参数:
- 输入矩阵(图像)
- 这个是我们传入的,不存差异;
- 滤波掩模
Zhou Wang版本
代码:
window = fspecial('gaussian', 11, 1.5);
% 算子类型:gaussian(高斯)
% 模版尺寸:11*11
% 标准差:1.5
% 以上参数皆hardcode
matlab版本
代码:
filtRadius = ceil(radius*3);
filtSize = 2*filtRadius + 1;
if (N < 3)
gaussFilt = fspecial('gaussian',[filtSize filtSize],radius); % 2D mask
else
...% 3D mask
end
% 算子类型:gaussian(高斯)
% 模版尺寸:[filtSize filtSize],使用默认值计算后,为:11*11矩阵;
% 标准差:radius,默认值为:1.5;
% 以上参数皆可通过传参改变
- 滤波模式
- Zhou Wang版本:
使用互相关(correlation)
- matlab版本:
使用卷积(convolution)
- 边界填充方式
- Zhou Wang版本:
边界通过填充0来扩展,例如:
- matlab版本:
通过复制外边界的值来扩展,例如:
- 结果矩阵
- Zhou Wang版本
只返回滤波时未使用边缘补 0 部分进行计算的结果部分(返回矩阵小于输入矩阵),例如:
- matlab版本
与输入矩阵大小一致,例如:
由于以上差异,导致了 Zhou Wang版ssim 与 matlab官方ssim 在计算结果上存在轻微差距。
- 滤波参数:
- 输入矩阵(图像)
- 这个是我们传入的,不存差异;
- 滤波掩模
Zhou Wang版本
代码:window = fspecial('gaussian', 11, 1.5); % 算子类型:gaussian(高斯) % 模版尺寸:11*11 % 标准差:1.5 % 以上参数皆hardcode
matlab版本
代码:filtRadius = ceil(radius*3); filtSize = 2*filtRadius + 1; if (N < 3) gaussFilt = fspecial('gaussian',[filtSize filtSize],radius); % 2D mask else ...% 3D mask end % 算子类型:gaussian(高斯) % 模版尺寸:[filtSize filtSize],使用默认值计算后,为:11*11矩阵; % 标准差:radius,默认值为:1.5; % 以上参数皆可通过传参改变
- 滤波模式
- Zhou Wang版本:
使用互相关(correlation) - matlab版本:
使用卷积(convolution)
- Zhou Wang版本:
- 边界填充方式
- Zhou Wang版本:
边界通过填充0来扩展,例如:
- matlab版本:
通过复制外边界的值来扩展,例如:
- Zhou Wang版本:
- 结果矩阵
- Zhou Wang版本
只返回滤波时未使用边缘补 0 部分进行计算的结果部分(返回矩阵小于输入矩阵),例如:
- matlab版本
与输入矩阵大小一致,例如:
- Zhou Wang版本
- 输入矩阵(图像)
3. 2D与3D图片支持
- matlab官方的ssim,除了支持2D图片,外还支持3D图片;而Zhou Wang版本只支持2D图片。
- 2D图片
ssim只支持对2D灰度图进行结构相似度计算,rgb图(彩图)需转换为灰度图才能计算(可调用rgb2gray进行转换)。
- 3D图片
3D图片现在在医疗领域用得较多:
在matlab2015中,如果直接读入rgb图(不转换为灰度)会被认为是3D图,这个比较坑爹,ssim运行不报错,但结果却是完全错的。
ssim只支持对2D灰度图进行结构相似度计算,rgb图(彩图)需转换为灰度图才能计算(可调用rgb2gray进行转换)。
3D图片现在在医疗领域用得较多:
在matlab2015中,如果直接读入rgb图(不转换为灰度)会被认为是3D图,这个比较坑爹,ssim运行不报错,但结果却是完全错的。