原文链接:https://blog.csdn.net/u010886794/article/details/84784453
一.公式计算
峰值信噪比(Peak Signal to Noise Ratio,PSNR)经常用来评价图像质量。对于一张RGB三通道图像,其计算公式如下:
先计算图像与Ground Truth的均方误差MSE:
再计算PSNR:
计算PSNR的Python代码,网上有下面两种:
-
import cv2
-
import numpy
as np
-
import math
-
-
def psnr1(img1, img2):
-
mse = np.mean((img1 - img2) **
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))
理论上,这两种计算方式都对应上面的计算公式,在输入图像一样的情况下,这两段代码的结果应该是一样的。但是,在调用这段代码的时候,我发现这两者的结果却相差很远,同样的图片,psnr1的结果大概是29,而psnr2的结果是12。
-
gt = cv2.imread(
'1.jpg')
-
img= cv2.imread(
'2.jpg')
-
-
print(psnr1(gt,img))
-
print(psnr2(gt,img))
这是输出的结果:
单看代码的话完全看不出来任何问题,后来我输出了这两张图像作差的结果,发现所有的值都是在0-255之间的,比如img1的一个像素值是30,img2的一个像素值是60,二者作差,本来应该是-30,但是结果却是226,即对于负值,输出要加上256。所以,问题就出在这行代码上:
mse = np.mean((img1 - img2) ** 2 )
如果img1某个点的像素比img2小,而两者差别又比较大,这个绝对值比较大的负值就会变成一个比较小的正值,MSE的结果也会偏小,那么PSNR的值就会偏大。
只要把上面那行代码改成mse = np.mean((img1/1.0 - img2/1.0) ** 2 )就可以了。
最后,我们发现这两个结果是一样的了。
二.内置函数
import skimage.color as sc
import skimage
from skimage import measure
class PSNRMetric(BaseMetric):
def __init__(self):
self.name = 'psnr'
def evaluate(self, gt, pr):
gt = self.image_preprocess(gt)
pr = self.image_preprocess(pr)
return skimage.measure.compare_psnr(gt, pr, data_range=255)
''' 上面的函数为计算PSNR的内置方法'''