图像质量评估指标
一般进行图像噪声的评估手段有四种,分别是:
- 信噪比(Signal to Noise Ratio,SNR)
- 峰值信噪比(Peak Signal to Noise Ratio, PSNR)
- 均方误差(Mean Square Error, MSE)
- 结构相似性(Structural SIMilarity, SSIM)。
下面分别介绍这四种评估指标。
均方误差(MSE)
均方差值是用于比较两幅图像
K
K
K,
I
I
I 的均方差值
M
S
E
=
1
m
n
∑
i
=
0
n
−
1
∑
j
=
0
m
−
1
∥
K
(
i
,
j
)
−
I
(
i
,
j
)
∥
2
M S E=\frac{1}{m n} \sum_{i=0}^{n-1} \sum_{j=0}^{m-1}\|K(i, j)-I(i, j)\|^{2}
MSE=mn1i=0∑n−1j=0∑m−1∥K(i,j)−I(i,j)∥2
信噪比(SNR)
SNR用于描述信号与噪声的比值
S
N
R
(
d
B
)
=
10
log
10
[
∑
x
=
0
m
−
1
∑
y
=
0
n
−
1
(
f
(
x
,
y
)
)
2
∑
x
=
0
m
−
1
∑
y
=
0
n
−
1
(
f
(
x
,
y
)
−
f
^
(
x
,
y
)
)
2
]
S N R(d B)=10 \log _{10}\left[\frac{\sum_{x=0}^{m-1} \sum_{y=0}^{n-1}(f(x, y))^{2}}{\sum_{x=0}^{m-1} \sum_{y=0}^{n-1}(f(x, y)-\hat{f}(x, y))^{2}}\right]
SNR(dB)=10log10[∑x=0m−1∑y=0n−1(f(x,y)−f^(x,y))2∑x=0m−1∑y=0n−1(f(x,y))2]
SNR代码实现
下面的代码是加入信噪比未为level
dB的噪声的代码:
def add_noise(y, level):
with torch.no_grad():
sigma = 10 ** (- (1 / 20) * level)
y = y + sigma * torch.randn(y.size()).to(self.device)
return y
峰值信噪比(PSNR)
灰度图PSNR计算
给定一个大小为
m
×
n
m\times n
m×n的干净图像
I
I
I和噪声图像
K
K
K,均方误差(
M
S
E
MSE
MSE)定义为:
M
S
E
=
1
m
n
∑
i
=
0
m
−
1
∑
j
=
0
n
−
1
[
I
(
i
,
j
)
−
K
(
i
,
j
)
]
2
M S E=\frac{1}{m n} \sum_{i=0}^{m-1} \sum_{j=0}^{n-1}[I(i, j)-K(i, j)]^{2}
MSE=mn1i=0∑m−1j=0∑n−1[I(i,j)−K(i,j)]2
在此基础上,PSNR(dB)被定义为:
P
S
N
R
=
10
⋅
log
10
(
M
A
X
I
2
M
S
E
)
P S N R=10 \cdot \log _{10}\left(\frac{M A X_{I}^{2}}{M S E}\right)
PSNR=10⋅log10(MSEMAXI2)
其中
M
A
X
I
2
MAX_I^2
MAXI2为图片可能的最大像素值。如果每个像素都由 8 位二进制来表示,那么就为 255。通常,如果像素值由
B
B
B位二进制来表示,那么
M
A
X
I
=
2
B
−
1
MAX_I=2^B-1
MAXI=2B−1。
一般地,针对 uint8 数据,最大像素值为 255;针对浮点型数据,最大像素值为 1。
RGB图像PSNR计算
如果是彩色图像,通常有三种方法来计算。
- 分别计算 RGB 三个通道的 PSNR,然后取平均值。
- 计算 RGB 三通道的 MSE ,然后再除以 3 。
- 将图片转化为 YCbCr 格式,然后只计算 Y 分量也就是亮度分量的 PSNR。
其中,第二和第三种方法比较常见。
峰值信噪比PSNR衡量图像失真或是噪声水平的客观标准。2个图像之间PSNR值越大,则越相似。普遍基准为30dB,30dB以下的图像劣化较为明显。
PSNR代码实现
方法一:利用skimage模块的compare_psnr
函数计算。
# method 1
diff = im1 - im2
mse = np.mean(np.square(diff))
psnr = 10 * np.log10(255 * 255 / mse)
# method 2
psnr = skimage.measure.compare_psnr(im1, im2, 255)
方法二:来自大佬LeCun的PSNR函数:
# 计算PSNR
def PSNR(target, pred, R=1, dummy=1e-4, reduction='mean'):
with torch.no_grad():
dims = (1, 2, 3) if len(target.shape) == 4 else 1
mean_sq_err = ((target - pred) ** 2).mean(dims)
mean_sq_err = mean_sq_err + (mean_sq_err == 0).float() * dummy # if 0, fill with dummy -> PSNR of 40 by default
output = 10 * torch.log10(R ** 2 / mean_sq_err)
if reduction == 'mean':
return output.mean()
elif reduction == 'none':
return output
结构相似性(SSIM)
SSIM 描述两个图像的相似性,公式基于样本
x
x
x和
y
y
y之间的三个比较衡量:亮度 (luminance)、对比度 (contrast) 和结构 (structure)。
l
(
x
,
y
)
=
2
μ
x
μ
y
+
c
1
μ
x
2
+
μ
y
2
+
c
1
c
(
x
,
y
)
=
2
σ
x
σ
y
+
c
2
σ
x
2
+
σ
y
2
+
c
2
s
(
x
,
y
)
=
σ
x
y
+
c
3
σ
x
σ
y
+
c
3
l(x, y)=\frac{2 \mu_{x} \mu_{y}+c_{1}}{\mu_{x}^{2}+\mu_{y}^{2}+c_{1}} c(x, y)=\frac{2 \sigma_{x} \sigma_{y}+c_{2}}{\sigma_{x}^{2}+\sigma_{y}^{2}+c_{2}} s(x, y)=\frac{\sigma_{x y}+c_{3}}{\sigma_{x} \sigma_{y}+c_{3}}
l(x,y)=μx2+μy2+c12μxμy+c1c(x,y)=σx2+σy2+c22σxσy+c2s(x,y)=σxσy+c3σxy+c3
一般取
c
3
=
c
2
/
2
c_3=c_2/2
c3=c2/2。
- μ x \mu_x μx为 x x x的均值, μ y \mu_y μy为 x x x的均值; σ x 2 \sigma_x^2 σx2为 x x x的方差, σ y 2 \sigma_y^2 σy2为 y y y的方差; σ x y 2 \sigma_{xy}^2 σxy2为 x y xy xy的方差;
- 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为两个常数,避免除零, L L L为像素值的范围;
- k 1 = 0.01 , k 2 = 0.03 k_{1}=0.01, k_{2}=0.03 k1=0.01,k2=0.03为默认值。
那么:
SSIM
(
x
,
y
)
=
[
l
(
x
,
y
)
α
⋅
c
(
x
,
y
)
β
⋅
s
(
x
,
y
)
γ
]
\operatorname{SSIM}(x, y)=\left[l(x, y)^{\alpha} \cdot c(x, y)^{\beta} \cdot s(x, y)^{\gamma}\right]
SSIM(x,y)=[l(x,y)α⋅c(x,y)β⋅s(x,y)γ]
将
α
,
β
,
γ
\alpha,\beta,\gamma
α,β,γ设为 1,可以得到
SSIM
(
x
,
y
)
=
(
2
μ
x
μ
y
+
c
1
)
(
2
σ
x
y
+
c
2
)
(
μ
x
2
+
μ
y
2
+
c
1
)
(
σ
x
2
+
σ
y
2
+
c
2
)
\operatorname{SSIM}(x, y)=\frac{\left(2 \mu_{x} \mu_{y}+c_{1}\right)\left(2 \sigma_{x y}+c_{2}\right)}{\left(\mu_{x}^{2}+\mu_{y}^{2}+c_{1}\right)\left(\sigma_{x}^{2}+\sigma_{y}^{2}+c_{2}\right)}
SSIM(x,y)=(μx2+μy2+c1)(σx2+σy2+c2)(2μxμy+c1)(2σxy+c2)
每次计算的时候都从图片上取一个 N × M N\times M N×M的窗口,然后不断滑动窗口进行计算,最后取平均值作为全局的 SSIM。
SSIM返回图像的MSSIM。这也是一个介于零和一之间的浮点数(越高越好)
SSIM代码实现
# im1 和 im2 都为灰度图像,uint8 类型
ssim = skimage.measure.compare_ssim(im1, im2, data_range=255)