图像质量评估指标MSE/SSIM/PSNR的分析和python实现

MSE、SSIM、PSNR图像质量评估指标SSIM/PSNR/MSE分析常用于超分辨算法的评估

MSE(MeanSquareError)

计算图像处理后的质量,最直接的思路即比较处理后的图像与真实图像(distortion-free)之间的差剖面,即可视误差,通过可视(visibility of errors )误差评价图像质量。 MSE 就是基于这种简单直接的思路确定的指标。

均方误差(mean-square error, MSE)是反映估计量与被估计量之间差异程度的一种度量。MSE的计算公式如下所示:

\[ MSE = \frac{1}{H \times M} \sum_{i=1}^{H} \sum_{j=1}^{W} (X(i, j)-Y(i, j))^2 \] MSE表示当前图像 \(X\) 和参考图像 \(Y\) 的均方误差(MeanSquare Error),\(H\)\(W\) 分别为图像的高度和宽度。

python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# TensorFlow Version
mse = tf.reduced_mean(tf.squared_difference(target,output))

# General Version
import numpy as np

def mae_value(y_true, y_pred):
"""compute mae of predict value and ground truth
:param y_true: numpy Calculable variable
:param y_pred: numpy Calculable variable
:return mae: float
"""

n = len(y_true)
mae = sum(np.abs(y_true - y_pred))/n
return mae

SSIM(structural similarity)

SSIM(structural similarity index),结构相似性,是一种衡量两幅图像相似度的指标。给定两个图像x和y, 两张图像的结构相似性可按照以下方式求出 :

\[ SSIM(x,y)=[l(x,y)]^{\alpha}[c(x,y)]^{\beta}[s(x,y)]^{\gamma} \]

\[ 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_{xy}+c_2}{\sigma_x^2+\sigma_y^2+c_2}, \]

\[ s(x,y)=\frac{\sigma_{xy}+c_3}{\sigma_x\sigma_y+c_3} \]

其中 \(\alpha>0,\ \beta>0, \gamma>0\)\(l(x, y)\)是亮度比较,\(c(x,y)\) 是对比度比较,\(s(x,y)\)是结构比较。\(\mu_x\)\(\mu_y\)分别代表 \(x\), \(y\) 的平均值,\(\sigma_x\)\(\sigma_y\) 分别代表 \(x\), \(y\) 的标准差。\(\sigma_{xy}\) 代表 \(x\)\(y\) 的协方差。而 \(c_1\)\(c_2\)\(c_3\)分别为常数,避免分母为 \(0\) 带来的系统错误。

在实际工程计算中,我们一般设定 \(\alpha=\beta=\gamma=1\),以及 \(c_3=c_2/2\) 可以将SSIM简化为下: \[ SSIM(x,y)= \frac{(2\mu_x\mu_y + c_1)(\sigma_{xy}+c_2)}{(\mu_x^2 + \mu_y^2 + c_1)(\sigma_x^2 + \sigma_y^2+c_2)} \] 结构相似性的范围为0到1,当两张图像一模一样时,SSIM的值等于1。作为结构相似性理论的实现,结构相似度指数从图像组成的角度将结构信息定义为独立于亮度、对比度的,反映场景中物体结构的属性,并将失真建模为亮度、对比度和结构三个不同因素的组合。用均值作为亮度的估计,标准差作为对比度的估计,协方差作为结构相似程度的度量。

python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# TensorFlow Version
tf.image.ssim(x, y, 255)

# General Version
def ssim(imageA, imageB):
# 为确保图像能被转为灰度图
imageA = np.array(imageA, dtype=np.uint8)
imageB = np.array(imageB, dtype=np.uint8)
# 通道分离,注意顺序BGR不是RGB
(B1, G1, R1) = cv2.split(imageA)
(B2, G2, R2) = cv2.split(imageB)
# convert the images to grayscale BGR2GRAY
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)

# 方法一
(grayScore, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
print("gray SSIM: {}".format(grayScore))

# 方法二
(score0, diffB) = compare_ssim(B1, B2, full=True)
(score1, diffG) = compare_ssim(G1, G2, full=True)
(score2, diffR) = compare_ssim(R1, R2, full=True)
aveScore = (score0+score1+score2)/3
print("BGR average SSIM: {}".format(aveScore ))

return grayScore, aveScore

参考链接

https://blog.csdn.net/leviopku/article/details/84635897 https://www.cnblogs.com/djw12333/p/11982426.html

PSNR(PeakSignal to Noise Ratio)

峰值信噪比,是一种评价图像的客观标准,它具有局限性,一般是用于最大值信号和背景噪音之间的一个工程项目。PSRN越大,图像失真越小,编码质量越高,PSNR的普遍基准为30dB,低于30dB失真明显,一般在30dB到40dB之间。

peak的中文意思是顶点。而ratio的意思是比率或比列的。整个意思就是到达噪音比率的顶点信号,psnr一般是用于最大值信号和背景噪音之间的一个工程项目。通常在经过影像压缩之后,输出的影像都会在某种程度与原始影像不同。

为了衡量经过处理后的影像品质,我们通常会参考PSNR值来衡量某个处理程序能否令人满意。它是原图像与被处理图像之间的均方误差相对于\((2^n-1)^2\)的对数值(信号最大值的平方,\(n\) 是每个采样值的比特数),计算公式如下:

\[ PSNR = 10 \times log_{10}(\frac{(2^n-1)^2}{MSE}) = 20 \times log_{10}(\frac{(2^n-1)}{\sqrt{MSE}}) \]

其中,MSE是原图像与处理图像之间均方误差。\(n\) 为每像素的比特数,一般取 8,即像素灰阶数为256。PSNR的单位为dB,所以PSNR值越大,就代表失真越少。

PSNR是最普遍,最广泛使用的评鉴画质的客观量测法,不过许多实验结果都显示,PSNR的分数无法和人眼看到的视觉品质完全一致,有可能PSNR较高者看起来反而比PSNR较低者差。这是因为人眼的视觉对于误差的敏感度并不是绝对的,其感知结果会受到许多因素的影响而产生变化(例如:人眼对空间频率较低的对比差异敏感度较高,人眼对亮度对比差异的敏感度较色度高,人眼对一个区域的感知结果会受到其周围邻近区域的影响)。

python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# TensorFlow Version
mse = tf.reduced_mean(tf.squared_difference(target,output))
psnr = tf.constant(255**2,dtype = tf.float32)/mse

# General Version
import cv2
import numpy as np
import math

def psnr1(img1, img2):
mse = np.mean((img1/1.0 - img2/1.0) ** 2 )
if mse < 1.0e-10:
return 100
return 10 * math.log10(255.0**2/mse)

def psnr2(img1, img2):
mse = np.mean( (img1/255. - img2/255.) ** 2 )
if mse < 1.0e-10:
return 100
PIXEL_MAX = 1
return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))

参考链接

https://blog.csdn.net/u010886794/article/details/84784453


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!