首页 > 解决方案 > PSNR 计算结果不正确

问题描述

我从维基百科的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

我还尝试了 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.

我究竟做错了什么?

标签: pythonopencvimage-processing

解决方案


差异的原因很可能在引用图像的标题中暗示(我强调):

不同质量级别的 cjpeg 压缩图像的示例亮度PSNR 值。

PSNR 不像您那样针对整个 RGB 图像计算,而仅针对图像的亮度(“亮度”)计算。

另外,我什至无法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 确实与给定值完全匹配,尽管并不完全相同。我测试了几个亮度计算,没有一个给出确切的结果——但是由于在引用的示例中没有提到亮度是如何计算的,所以无论如何尝试重现精确值是没有意义的。

希望有帮助!


推荐阅读