图像PSNR及其计算(OpenCV和matlab实现)
引言:在图像处理中,要对图像进行客观的评价,常常需要计算PSNR,本文将简单介绍PSNR的定义,并给出相关的源代码。
PSNR的概念
PSNR (Peak Signal to Noise Ratio)
峰值信噪比PSNR衡量图像失真或是噪声水平的客观标准。2个图像之间PSNR值越大,则越相似。普遍基准为30dB,30dB以下的图像劣化较为明显。定义为,
这里MAX表示图像颜色的最大数值,8bit图像取值为255。我们还要介绍MSE(均方差),即m×n单色图像 I 和 K(原图像与处理图像)之间均方误差,定义为:
PSNR编程实现
matlab实现
第一种实现方法:
- 在matlab 2016版本中是带有psnr的计算的,只需调用相关函数就好。官方详细说明链接
peaksnr = psnr(A,ref)
%peaksnr = psnr(A,ref) calculates the peak signal-to-noise ratio for the image A, with the image ref as the reference. A and ref must be of the same size and class.
- 1
- 2
第二种直观方法
- 在matlab中新建m文件,下面这个实现简单明了
function [PSNR, MSE]=psnr(I,K)
[M,N,D] = size(I);
Diff = double(I)-double(K);
MSE = sum(Diff(:).^2)/numel(I);
PSNR=10*log10(255^2/MSE);
end
- 1
- 2
- 3
- 4
- 5
- 6
第三种实现方法:
- 在matlab中新建m文件,复制进去保存就可以调用了。
function PSNR(A,B)
% PURPOSE: To find the PSNR (peak signal-to-noise ratio) between two
% intensity images A and B, each having values in the interval
% [0,1]. The answer is in decibels (dB).
%
% There is also a provision, in EXAMPLE 3 below, for images
% stored in the interval [0,255], i.e. 256 gray levels.
%
% SYNOPSIS: PSNR(A,B)
%
% DESCRIPTION: The following is quoted from "Fractal Image Compression",
% by Yuval Fisher et al.,(Springer Verlag, 1995),
% section 2.4, "Pixelized Data".
%
% "...PSNR is used to measure the difference between two
% images. It is defined as
%
% PSNR = 20 * log10(b/rms)
%
% where b is the largest possible value of the signal
% (typically 255 or 1), and rms is the root mean square
% difference between two images. The PSNR is given in
% decibel units (dB), which measure the ratio of the peak
% signal and the difference between two images. An increase
% of 20 dB corresponds to a ten-fold decrease in the rms
% difference between two images.
%
% There are many versions of signal-to-noise ratios, but
% the PSNR is very common in image processing, probably
% because it gives better-sounding numbers than other
% measures."
%
% EXAMPLE 1: load clown
% A = ind2gray(X,map); % Convert to an intensity image in [0,1].
% B = 0.95 * A; % Make B close to, but different from, A.
% PSNR(A,B) % ---> "PSNR = +33.49 dB"
%
% EXAMPLE 2: A = rand(256); % A is a random 256 X 256 matrix in [0,1].
% B = 0.9 * A; % Make B close to, but different from, A.
% PSNR(A,B) % ---> "PSNR = +24.76 dB (approx)"
%
% EXAMPLE 3: For images with 256 gray levels: this function PSNR was
% originally written for matrix-values between 0 and 1,
% because of MATLAB's preference for that interval.
%
% However, suppose the matrix has values in [0,255]. Taking
% Example 1 above, we could change the image to 256 gray levels.
%
% load clown
% A = ind2gray(X,map); % Convert to intensity image in [0,1]
% AA = uint8(255*A); % Change to integers in [0,255]
% BB = 0.95*AA; % Make BB close to AA.
%
% Now we must alter the code for this new case. Comment out the
% existing program (using %) and uncomment the alternative
% underneath it.
%
% PSNR(AA,BB) % ---> "PSNR = +33.56 dB"
%
% Note the slightly different result from Example 1, because
% decimal values were rounded into integers.
if A == B
error('Images are identical: PSNR has infinite value')
end
max2_A = max(max(A));
max2_B = max(max(B));
min2_A = min(min(A));
min2_B = min(min(B));
if max2_A > 1 || max2_B > 1 || min2_A < 0 || min2_B < 0
error('input matrices must have values in the interval [0,1]')
end
error_diff = A - B;
decibels = 20*log10(1/(sqrt(mean(mean(error_diff.^2)))));
disp(sprintf('PSNR = +%5.2f dB',decibels))
% if A == B
% error('Images are identical: PSNR has infinite value')
% end
% max2_A = max(max(A));
% max2_B = max(max(B));
% min2_A = min(min(A));
% min2_B = min(min(B));
%
% if max2_A > 255 || max2_B > 255 || min2_A < 0 || min2_B < 0
% error('input matrices must have values in the interval [0,255]')
% end
% error_diff = A - B;
% decibels = 20*log10(255/(sqrt(mean(mean(error_diff.^2)))));
% disp(sprintf('PSNR = +%5.2f dB',decibels))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
OpenCV实现
- 使用的是opencv 2.0版本,核心程序如下,很简单的程序,详细的注释可以帮助你理解getPSNR函数:
//输入格式是Mat类型,I1,I2代表是输入的两幅图像
double getPSNR(const Mat& I1, const Mat& I2)
{
Mat s1;
absdiff(I1, I2, s1); // |I1 - I2|AbsDiff函数是 OpenCV 中计算两个数组差的绝对值的函数
s1.convertTo(s1, CV_32F); // 这里我们使用的CV_32F来计算,因为8位无符号char是不能进行平方计算
s1 = s1.mul(s1); // |I1 - I2|^2
Scalar s = sum(s1); //对每一个通道进行加和
double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels
if( sse <= 1e-10) // 对于非常小的值我们将约等于0
return 0;
else
{
double mse =sse /(double)(I1.channels() * I1.total());//计算MSE
double psnr = 10.0*log10((255*255)/mse);
return psnr;//返回PSNR
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
可能需要添加的头文件是:
#include // Basic OpenCV structures (cv::Mat, Scalar)
#include // OpenCV window I/O
- 1
- 2
使用说明:
//先定义PSNR
double psnr;
//然后读取输入的两幅图像
Mat img1=imread('1.jpg');
Mat img2=imread('2.jpg');
//调用函数
psnr = getPSNR(img1,img2);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
参考资料
[1]http://iyenn.com/index/link?url=http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/highgui/video-input-psnr-ssim/video-input-psnr-ssim.html
[2]http://iyenn.com/index/link?url=http://www.mathworks.com/matlabcentral/fileexchange/135-psnr
评论记录:
回复评论: