在本文中假设所有图像均以 sRGB 颜色空间进行编码,即使用指数 ≈ 2.4 \approx 2.4 ≈2.4 进行近似伽马编码。请注意,这意味着假定由本文脚本加载的图像可以直接在屏幕上按原样查看。对于两个图像 A A A和 B B B,每像素结构相似性指数测量的原始公式由下式给出
SSIM ( x , y ) = ( l ( x , y ) ) α ( c ( x , y ) ) β ( s ( x , y ) ) 2 ( 1 ) \operatorname{SSIM}(x, y)=(l(x, y))^\alpha(c(x, y))^\beta(s(x, y))^2\qquad(1) SSIM(x,y)=(l(x,y))α(c(x,y))β(s(x,y))2(1)
其中 A A A 和 B B B 是所有函数的输入,但为了清楚起见省略了。为了计算像素周围补丁的均值、方差和协方差,他们使用这些公式的高斯加权版本,滤波器内核为 11 × 11 11 \times 11 11×11 像素和 σ = 1.5 \sigma=1.5 σ=1.5。亮度分量 l l l 则为
l ( x , y ) = 2 μ A μ B + C 1 μ A 2 + μ B 2 + C 1 ( 2 ) l(x, y)=\frac{2 \mu_{ A } \mu_{ B }+C_1}{\mu_{ A }^2+\mu_{ B }^2+C_1}\qquad(2) l(x,y)=μA2+μB2+C12μAμB+C1(2)
其中平均值 μ A \mu_{ A } μA 和 μ B \mu_{ B } μB 也是 x , y x, y x,y 的函数,例如 μ A ( x , y ) \mu_{ A }(x, y) μA(x,y),但我们跳过 $ (x, y)$ 支持更短的符号,对于方差 σ A 2 \sigma_{ A }^2 σA2 和 σ B 2 \sigma_{ B }^2 σB2 以及协方差 σ A B \sigma_{ A B } σAB 也是如此。对比分量 c c c 是
c ( x , y ) = 2 σ A σ B + C 2 σ A 2 + σ B 2 + C 2 ( 3 ) c(x, y)=\frac{2 \sigma_{ A } \sigma_{ B }+C_2}{\sigma_{ A }^2+\sigma_{ B }^2+C_2}\qquad(3) c(x,y)=σA2+σB2+C22σAσB+C2(3)
最后,结构分量 s s s 是
s ( x , y ) = σ A B + C 3 σ A σ B + C 3 ( 4 ) s(x, y)=\frac{\sigma_{ A B }+C_3}{\sigma_{ A } \sigma_{ B }+C_3}\qquad(4) s(x,y)=σAσB+C3σAB+C3(4)
学者们提出 C 1 = ( K 1 L ) 2 、 C 2 = ( K 2 L ) 2 C_1=\left(K_1 L\right)^2、C_2=\left(K_2 L\right)^2 C1=(K1L)2、C2=(K2L)2 和 C 3 = C 2 / 2 C_3=C_2 / 2 C3=C2/2,其中 L = 255 L=255 L=255 对于 8 位组件图像。此外,他们选择了 K 1 = 0.01 K_1=0.01 K1=0.01 和 K 2 = 0.03 K_2=0.03 K2=0.03。如果图像的范围是 [ 0 , 1 ] [0,1] [0,1],我们设置 L = 1 L=1 L=1以获得相同的结果,即 C 1 = K 1 2 C_1=K_1^2 C1=K12和 C 2 = K 2 2 C_2=K_2^2 C2=K22。最后,在整个图像上汇集的平均 SSIM (MSSIM) 值是
MSSIM ( A , B ) = 1 w h ∑ x ∑ y SSIM ( x , y ) ( 5 ) \operatorname{MSSIM}( A , B )=\frac{1}{w h} \sum_x \sum_y \operatorname{SSIM}(x, y)\qquad(5) MSSIM(A,B)=wh1x∑y∑SSIM(x,y)(5)
其中 w w w 和 h h h 是图像的宽度和高度。可以看出, σ A σ B \sigma_{ A } \sigma_{ B } σAσB 项位于方程 3 的分子中,以及方程 4 的分母中。为了创建简化的表达式,建议使用 α = β = γ = 1 \alpha=\beta=\gamma=1 α=β=γ=1 和 C 3 = C 2 / 2 C_3=C_2 / 2 C3=C2/2,结果是
SSIM ( x , y ) = ( 2 μ A μ B + C 1 ) ( 2 σ A B + C 2 ) ( μ A 2 + μ B 2 + C 1 ) ( σ A 2 + σ B 2 + C 2 ) ( 6 ) \operatorname{SSIM}(x, y)=\frac{\left(2 \mu_{ A } \mu_{ B }+C_1\right)\left(2 \sigma_{ A B }+C_2\right)}{\left(\mu_{ A }^2+\mu_{ B }^2+C_1\right)\left(\sigma_{ A }^2+\sigma_{ B }^2+C_2\right)}\qquad(6) SSIM(x,y)=(μA2+μB2+C1)(σA2+σB2+C2)(2μAμB+C1)(2σAB+C2)(6)
以上等从数学角度分析 SSIM 的组成部分。下面将详细讨论质量指数本身的行为。我们使用符号 x / y x / y x/y 来表示特定灰度值的像素。例如,128/255对应灰度值 50.2 % 50.2\% 50.2%。简写形式 x ∣ y x \mid y x∣y 指定像素大小的棋盘图案,颜色为 x / 255 x / 255 x/255 和 y / 255 y / 255 y/255。字母 b b b 和 w w w 分别是黑色 ( 0 / 255 ) (0 / 255) (0/255) 和白色 (255/255) 的简写。
图1执行代码:
isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0;
if(isOctave)
pkg load image;
end
disp("");
disp("====================");
disp("Results for Figure 1");
disp("--------------------");
srcdir = "teaser/";
dstdir = "result_images/";
images = ["earthmoon"; "plants"; "i01_l95_tid2013"; "monument_awgn5"; "einstein"; "snow_leaves_contrast3"];
for idx = 1:length(images)
name = images(idx,:);
srcfileprefix = strcat(srcdir, name);
A=rgb2gray(imread(convertStringsToChars(strcat(srcfileprefix, '_reference.png'))));
B=rgb2gray(imread(convertStringsToChars(strcat(srcfileprefix, '_test.png'))));
[mssim_simplified, mssim, ssim_map_simplified, ssim_map, l_map, c_map, s_map] = ssimlcs(A,B);
mssim_simplified
float2grayred(ssim_map, strcat(dstdir, name, '_ssim.png'), 1);
float2grayred(l_map, convertStringsToChars(strcat(dstdir, name, '_L.png')), 1);
float2grayred(c_map, convertStringsToChars(strcat(dstdir, name, '_C.png')), 1);
float2grayred(s_map, convertStringsToChars(strcat(dstdir, name, '_S.png')), 1);
disp("--------------------");
end
disp("====================");
图2 执行代码
isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0;
if(isOctave)
pkg load image;
end
disp("");
disp("====================");
disp("Results for Figure 2");
disp("--------------------");
A=imread('gray/gray000.png');
B=imread('gray/gray255.png');
if(isOctave)
B =B .* 255;
end
[mssim_simplified, mssim, ssim_map_simplified, ssim_map, l_map, c_map, s_map] = ssimlcs(A,B);
disp("MSSIM between black and white images");
mssim_simplified
float2grayred(ssim_map, 'result_images/luminance_minimum_ssim.png', 1);
float2grayred(l_map, 'result_images/luminance_minimum_L.png', 1);
float2grayred(c_map, 'result_images/luminance_minimum_C.png', 1);
float2grayred(s_map, 'result_images/luminance_minimum_S.png', 1);
disp("--------------------");
A=imread('gray/gray128.png');
B=imread('checker/checker-bw.png');
if(isOctave)
B =B .* 255;
end
[mssim_simplified, mssim, ssim_map_simplified, ssim_map, l_map, c_map, s_map] = ssimlcs(A,B);
disp("MSSIM between gray (128/255) and a checkered image (black and white)");
mssim_simplified
float2grayred(ssim_map, 'result_images/contrast_minimum_ssim.png', 1);
float2grayred(l_map, 'result_images/contrast_minimum_L.png', 1);
float2grayred(c_map, 'result_images/contrast_minimum_C.png', 1);
float2grayred(s_map, 'result_images/contrast_minimum_S.png', 1);
disp("--------------------");
A=imread('checker/checker-bw.png');
B=imread('checker/checker-wb.png');
if(isOctave)
A =A .* 255;
B =B .* 255;
end
[mssim_simplified, mssim, ssim_map_simplified, ssim_map, l_map, c_map, s_map] = ssimlcs(A,B);
disp("MSSIM between gray checker and inverted checkerboard");
mssim_simplified
float2grayred(ssim_map, 'result_images/structure_minimum_ssim.png', 1);
float2grayred(l_map, 'result_images/structure_minimum_L.png', 1);
float2grayred(c_map, 'result_images/structure_minimum_C.png', 1);
float2grayred(s_map, 'result_images/structure_minimum_S.png', 1);
disp("====================");
图4 执行代码
isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0;
if(isOctave)
pkg load image;
end
disp("");
disp("====================");
disp("Results for Figure 4");
disp("--------------------");
A=imread('gray/gray253.png');
B=imread('gray/gray255.png');
if(isOctave)
B =B .* 255;
end
[mssim, ssim_map] = ssim(A,B);
disp("MSSIM between 253/255 and 255/255: ");
mssim
disp("--------------------");
A=imread('gray/gray128.png');
B=imread('gray/gray130.png');
[mssim, ssim_map] = ssim(A,B);
disp("MSSIM between 128/255 and 130/255: ");
mssim
disp("--------------------");
A=imread('gray/gray000.png');
B=imread('gray/gray002.png');
[mssim, ssim_map] = ssim(A,B);
disp("MSSIM between 0/255 and 2/255: ");
mssim
disp("--------------------");
A=imread('gray/gray222.png');
B=imread('gray/gray255.png');
if(isOctave)
B =B .* 255;
end
[mssim, ssim_map] = ssim(A,B);
disp("MSSIM between 222/255 and 255/255: ");
mssim
disp("--------------------");
A=imread('gray/gray000.png');
B=imread('gray/gray026.png');
[mssim, ssim_map] = ssim(A,B);
disp("MSSIM between 0/255 and 26/255: ");
mssim
disp("====================");