PSNR 值在 matlab 实现和 python 中不同
PSNR values differ in matlab implementation and python
我已经实现了一个 python 代码来计算 YCrCb 通道中 Y 通道的 PSNR 值。
我得到的 PSNR 值约为 35.7dB(对于一对图像)
import cv2, main
import sys
i1 = cv2.imread(sys.argv[1])
i2 = cv2.imread(sys.argv[2])
i1= cv2.cvtColor(i1, cv2.COLOR_BGR2YCrCb)
i2= cv2.cvtColor(i2, cv2.COLOR_BGR2YCrCb)
print(main.psnr(i1[:,:,0], i2[:,:,0]))
在主psnr中定义为:
def psnr(target, ref):
import cv2
target_data = numpy.array(target, dtype=numpy.float64)
ref_data = numpy.array(ref,dtype=numpy.float64)
diff = ref_data - target_data
print(diff.shape)
diff = diff.flatten('C')
rmse = math.sqrt(numpy.mean(diff ** 2.))
return 20 * math.log10(255 / rmse)
我在 matlab 中得到了一个在线实现(来自我所指的论文)
我得到的 PSNR 值约为 37.06dB(对于同一对图像)
function psnr=compute_psnr(im1,im2)
if size(im1, 3) == 3,
im1 = rgb2ycbcr(im1);
im1 = im1(:, :, 1);
end
if size(im2, 3) == 3,
im2 = rgb2ycbcr(im2);
im2 = im2(:, :, 1);
end
imdff = double(im1) - double(im2);
imdff = imdff(:);
rmse = sqrt(mean(imdff.^2));
psnr = 20*log10(255/rmse)
这个错误可能是由于 numpy 引入的错误还是 numpy 似乎达到的精度?
您的两个转换函数似乎产生了截然不同的结果:
Python output:
Octave output:
这解释了差异。
Octave 确实提到有几个 YCbCr 标准:
The formula used for the conversion is dependent on two constants,
KB and KR which can be specified individually, or according to
existing standards:
"601" (default)
According to the ITU-R BT.601 (formerly CCIR 601) standard.
Its values of KB and KR are 0.114 and 0.299 respectively.
"709" (default)
According to the ITU-R BT.709 standard. Its values of KB and
KR are 0.0722 and 0.2116 respectively.
也许 python 版本使用了不同的标准? (或者可能是 BGR 与 RGB 问题?)。无论如何,这就是差异所在,这似乎不是 numpy 精度的问题(当使用相同的输入分别测试这些函数时,它们会产生相同的结果)。
编辑:
根据这些:
- Why is the Y, converted by rgb2ycbcr in the Matlab, in the range [16, 235]?
- http://docs.opencv.org/3.1.0/de/d25/imgproc_color_conversions.html#color_convert_rgb_ycrcb
- https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
python(或者更确切地说,opencv 库)似乎正在输出 'analog'(未缩放)版本,而 matlab/octave 正在输出 'digital'(缩放)版本。
已确认:
# Python
RGB = numpy.concatenate(
( numpy.array([[[0], [255], [255], [0], [0], [0], [255]]], dtype=numpy.uint8),
numpy.array([[[0], [0], [255], [255], [255], [0], [255]]], dtype=numpy.uint8),
numpy.array([[[0], [0], [0], [0], [255], [255], [255]]], dtype=numpy.uint8)),
axis=2)
RGB2Y = cv2.cvtColor(RGB, cv2.COLOR_BGR2YCrCb)
print(RGB2Y)
[[[ 0 128 128]
[ 29 107 255]
[179 0 171]
[150 21 43]
[226 149 1]
[ 76 255 85]
[255 128 128]]]
% Octave
pkg load image;
RGB = uint8 (cat (3, [0, 255, 255, 0, 0, 0, 255], ...
[0, 0, 255, 255, 255, 0, 255], ...
[0, 0, 0, 0, 255, 255, 255]));
RGB2Y = rgb2ycbcr(RGB)
RGB2Y =
ans(:,:,1) =
16 81 210 145 170 41 235
ans(:,:,2) =
128 90 16 54 166 240 128
ans(:,:,3) =
128 240 146 34 16 110 128
因此,如果这是实现一致性的问题,我会使用上面维基百科页面中提到的从模拟到数字的转换公式来缩放 python 结果,即:
如果这是 "which version is the most appropriate one for the calculation of PSNR" 的问题,我不知道,但根据我在上面的链接中阅读的内容,我的钱会花在 matlab / octave 实现上。
我已经实现了一个 python 代码来计算 YCrCb 通道中 Y 通道的 PSNR 值。 我得到的 PSNR 值约为 35.7dB(对于一对图像)
import cv2, main
import sys
i1 = cv2.imread(sys.argv[1])
i2 = cv2.imread(sys.argv[2])
i1= cv2.cvtColor(i1, cv2.COLOR_BGR2YCrCb)
i2= cv2.cvtColor(i2, cv2.COLOR_BGR2YCrCb)
print(main.psnr(i1[:,:,0], i2[:,:,0]))
在主psnr中定义为:
def psnr(target, ref):
import cv2
target_data = numpy.array(target, dtype=numpy.float64)
ref_data = numpy.array(ref,dtype=numpy.float64)
diff = ref_data - target_data
print(diff.shape)
diff = diff.flatten('C')
rmse = math.sqrt(numpy.mean(diff ** 2.))
return 20 * math.log10(255 / rmse)
我在 matlab 中得到了一个在线实现(来自我所指的论文) 我得到的 PSNR 值约为 37.06dB(对于同一对图像)
function psnr=compute_psnr(im1,im2)
if size(im1, 3) == 3,
im1 = rgb2ycbcr(im1);
im1 = im1(:, :, 1);
end
if size(im2, 3) == 3,
im2 = rgb2ycbcr(im2);
im2 = im2(:, :, 1);
end
imdff = double(im1) - double(im2);
imdff = imdff(:);
rmse = sqrt(mean(imdff.^2));
psnr = 20*log10(255/rmse)
这个错误可能是由于 numpy 引入的错误还是 numpy 似乎达到的精度?
您的两个转换函数似乎产生了截然不同的结果:
Python output:
Octave output:
这解释了差异。
Octave 确实提到有几个 YCbCr 标准:
The formula used for the conversion is dependent on two constants,
KB and KR which can be specified individually, or according to
existing standards:
"601" (default)
According to the ITU-R BT.601 (formerly CCIR 601) standard.
Its values of KB and KR are 0.114 and 0.299 respectively.
"709" (default)
According to the ITU-R BT.709 standard. Its values of KB and
KR are 0.0722 and 0.2116 respectively.
也许 python 版本使用了不同的标准? (或者可能是 BGR 与 RGB 问题?)。无论如何,这就是差异所在,这似乎不是 numpy 精度的问题(当使用相同的输入分别测试这些函数时,它们会产生相同的结果)。
编辑:
根据这些:
- Why is the Y, converted by rgb2ycbcr in the Matlab, in the range [16, 235]?
- http://docs.opencv.org/3.1.0/de/d25/imgproc_color_conversions.html#color_convert_rgb_ycrcb
- https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
python(或者更确切地说,opencv 库)似乎正在输出 'analog'(未缩放)版本,而 matlab/octave 正在输出 'digital'(缩放)版本。
已确认:
# Python
RGB = numpy.concatenate(
( numpy.array([[[0], [255], [255], [0], [0], [0], [255]]], dtype=numpy.uint8),
numpy.array([[[0], [0], [255], [255], [255], [0], [255]]], dtype=numpy.uint8),
numpy.array([[[0], [0], [0], [0], [255], [255], [255]]], dtype=numpy.uint8)),
axis=2)
RGB2Y = cv2.cvtColor(RGB, cv2.COLOR_BGR2YCrCb)
print(RGB2Y)
[[[ 0 128 128] [ 29 107 255] [179 0 171] [150 21 43] [226 149 1] [ 76 255 85] [255 128 128]]]
% Octave
pkg load image;
RGB = uint8 (cat (3, [0, 255, 255, 0, 0, 0, 255], ...
[0, 0, 255, 255, 255, 0, 255], ...
[0, 0, 0, 0, 255, 255, 255]));
RGB2Y = rgb2ycbcr(RGB)
RGB2Y = ans(:,:,1) = 16 81 210 145 170 41 235 ans(:,:,2) = 128 90 16 54 166 240 128 ans(:,:,3) = 128 240 146 34 16 110 128
因此,如果这是实现一致性的问题,我会使用上面维基百科页面中提到的从模拟到数字的转换公式来缩放 python 结果,即:
如果这是 "which version is the most appropriate one for the calculation of PSNR" 的问题,我不知道,但根据我在上面的链接中阅读的内容,我的钱会花在 matlab / octave 实现上。