Python(PyTorch)和MATLAB及Rust和C++结构相似度指数测量导图
🎯要点
- 量化检查图像压缩质量
- 低分辨率多光谱和高分辨率图像实现超分辨率分析图像
- 质量图像索引/多尺度结构相似度指数和光谱角映射器及视觉信息保真度多种指标
- 峰值信噪比和结构相似度指数测量
- 结构相似性图像分类
- PNG和JPEG图像相似性近似算法
- 图像压缩,视频压缩、端到端优化图像压缩、神经图像压缩、GPU变速图像压缩
- 手术机器人深度估计算法重建三维可视化
- 推理图像超分辨率算法模型
- 三维实景实时可微分渲染算法
MATLAB结构相似度指数优劣
在本文中假设所有图像均以 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("====================");