我从Wikipedia的PSNR文章中下载了两张图片(原始的未压缩PNG和Q = 90
压缩的JPG,报告的PSNR为45.53 dB
)。然后,我跑了:
import cv2
img1 = cv2.imread('PSNR-example-base.png')
img2 = cv2.imread('PSNR-example-comp-90.jpg')
cv2.PSNR(img1, img2)
但是我获得的输出值是
29.436334461883582
,而不是45.53
。我还尝试了this topic的Ryan SH的建议:
import numpy as np
import math
img1 = img1.astype(np.float64) / 255.
img2 = img2.astype(np.float64) / 255.
mse = np.mean((img1 - img2) ** 2)
10 * math.log10(1. / mse)
再次获得
29.43633446188358
。我究竟做错了什么?
最佳答案
引起差异的原因很可能是在参考图像的标题中提示的(我强调):
不会像您那样为整个RGB图像计算PSNR,而仅为图像的luma(“亮度”)计算PSNR。
另外,我什至无法从您的问题中复制29.4363...
。所以,这是我的比较代码:
import cv2
import numpy as np
from skimage import io # Only needed for web grabbing images, use cv2.imread for local images
def psnr(image1, image2):
# OpenCV
print('OpenCV PSNR: ', cv2.PSNR(image1, image2))
# Own implementation
mse = np.mean((image1.astype(np.float64) / 255 - image2.astype(np.float64) / 255) ** 2)
print('Own implementation: ', 10 * np.log10(1. / mse))
def luma(image):
return (0.299 * image[:, :, 2] + 0.587 * image[:, :, 1] + 0.114 * image[:, :, 0]).astype(np.uint8)
# return (0.2126 * image[:, :, 2] + 0.7152 * image[:, :, 1] + 0.0722 * image[:, :, 0]).astype(np.uint8)
# return (0.212 * image[:, :, 2] + 0.701 * image[:, :, 1] + 0.087 * image[:, :, 0]).astype(np.uint8)
# Calculate PSNR on referenced images
img1 = cv2.cvtColor(io.imread('https://upload.wikimedia.org/wikipedia/commons/d/d3/PSNR-example-base.png'), cv2.COLOR_RGB2BGR)
img2 = cv2.cvtColor(io.imread('https://upload.wikimedia.org/wikipedia/commons/2/2a/PSNR-example-comp-90.jpg'), cv2.COLOR_RGB2BGR)
psnr(img1, img2)
# Calculate luma PSNR on referenced images
psnr(luma(img1), luma(img2))
输出:
OpenCV PSNR: 39.021537956442224
Own implementation: 39.02153795644222
OpenCV PSNR: 44.79892614734474
Own implementation: 44.79892614734474
对我来说,RGB图像的PSNR远远高于您报告的PSNR。但是,亮度的PSNR确实与给定值匹配,尽管并不完全相同。我测试了多个亮度计算,但没有一个给出准确的结果-但由于在参考示例中未提及该结果,因此如何计算亮度,尝试重现精确值始终毫无意义。
希望有帮助!
关于python - PSNR计算结果不正确,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59253688/