一、原理
psnr是“Peak Signal to Noise Ratio”的缩写,即峰值信噪比,是一种评价图像的客观标准
用来表示信号最大可能功率和影响它的表示精度的破坏性噪声功率的比值,可以显示图像画质损失的程度。峰值信噪比越大,表示画质损失越小。PSNR的单位是dB,数值越大表示失真越小。
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()
'''