一、原理
psnr是“Peak Signal to Noise Ratio”的缩写,即峰值信噪比,是一种评价图像的客观标准
用来表示信号最大可能功率和影响它的表示精度的破坏性噪声功率的比值,可以显示图像画质损失的程度。峰值信噪比越大,表示画质损失越小。PSNR的单位是dB,数值越大表示失真越小。
1、PSNR 是基于对应像素点间的误差, 即基于误差敏感的图像质量评价, 但是由于 PSNR 并未考虑到人眼的视觉特性, 可能出现评价结果与人的主观感觉不一致的情况;
SSIM 则是从亮度 、 对比度和结构 3 方面度量图像相似性, 比 PSNR 更符合人类视觉感官。
结构相似性指标(英文: structural similarity index measure,简称SSIM) 是-种用以衡量两张数位影像相似程度的指标。当两张影像其中一张为无失真影像,另一张为失真后的影像,二者的结构相似性可以看成是失真影像的影像品质衡量指标。相较于传统所使用的影像品质衡量指标,像是峰值信噪比(英语: PSNR),结构相似性在 影像品质的衡量上更能符合人眼对影像品质的判断。
3、MSSIM(Mean Structural Similarity )平均结构相似性
用滑动窗将图像分为N块,加权计算每一窗口的均值、方差以及协方差,权值wij满足∑i∑jwij=1,通常采用高斯核,然后算对应块的结构相似度SSIM,最后将平均值作为两图像的结构相似性度量。
1.首先计算mse(均方误差)。是反映估计量与被估计量之间差异程度的一种度量。
对于三通道的RGB图像 计算mse的数学表达式是:
转化成代码:
2.得到mse后计算PSNR。
其中,MAXI是表示图像点颜色的最大数值,如果每个采样点用 8 位表示,那么就是 255。所以MSE越小,则PSNR越大;所以PSNR越大,代表着图像质量越好。
一般来说,
1、PSNR高于40dB说明图像质量极好(即非常接近原始图像),
2、在30—40dB通常表示图像质量是好的(即失真可以察觉但可以接受),
3、在20—30dB说明图像质量差;
4、最后,PSNR低于20dB图像不可接受
转化成代码:
或者将像素归一化:
理论上(数学意义上讲两个式子是相等的),但实际结果是:
原因是如果img1-img2的结果为负,那么得到的结果将是ASCII的补码,也就是,如果img1-img2是-2,那么输出将是256-2=254所以导致mse增大,如果img1某个点的像素比img2小,而两者差别又比较大,这个绝对值比较大的负值就会变成一个比较小的正值,mse的结果也会偏小,那么PSNR的值就会偏大。把上面的式子用下面的式子代替即可解决问题。
二、代码(两种方法)
import cv2 as cv
import math
import numpy as np
def psnr1(img1, img2):
# compute mse
# mse = np.mean((img1-img2)**2)
mse = np.mean((img1 / 1.0 - img2 / 1.0) ** 2)
# compute psnr
if mse < 1e-10:
return 100
psnr1 = 20 * math.log10(255 / math.sqrt(mse))
return psnr1
def psnr2(img1, img2):#第二种法:归一化
mse = np.mean((img1 / 255.0 - img2 / 255.0) ** 2)
if mse < 1e-10:
return 100
PIXEL_MAX = 1
psnr2 = 20 * math.log10(PIXEL_MAX / math.sqrt(mse))
return psnr2
imag1 = cv.imread("./img/222.jpg")
print(imag1.shape)
imag2 = cv.imread("./img/22.jpg")
print(imag2.shape)
#如果大小不同可以强制改变
# imag2 = imag2.reshape(352,352,3)
#print(imag2.shape)
res1 = psnr1(imag1, imag2)
print("res1:", res1)
res2 = psnr2(imag1, imag2)
print("res2:", res2)
#tensorflow框架里有直接关于psnr计算的函数,直接调用就行了:(更推荐)以下代码
'''
#注意:计算PSNR的时候必须满足两张图像的size要完全一样!
#compute PSNR with tensorflow
import tensorflow as tf
def read_img(path):
return tf.image.decode_image(tf.read_file(path))
def psnr(tf_img1, tf_img2):
return tf.image.psnr(tf_img1, tf_img2, max_val=255)
def _main():
t1 = read_img('t1.jpg')
t2 = read_img('t2.jpg')
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
y = sess.run(psnr(t1, t2))
print(y)
if __name__ == '__main__':
_main()
'''