图像算法评估 = 定性(主观,观察) + 定量(客观,特征值) + 算法时间
平均梯度(mean gradient):
指图像的边界或影线两侧附近灰度有明显差异,即灰度变化率大,这种变化率的大小可用来表示图像清晰度。
它反映了图像微小细节反差变化的速率,即图像多维方向上密度变化的速率,表征图像的相对清晰程度。
一般而言,评价梯度越大,图像层次越多,也就越清晰。
信息熵
图像信息熵也是图像质量评价的常用指标,它从信息论的角度反映图像信息丰富程度。通常情况下,图像信息熵越大
其信息量就越丰富,质量越好。
视觉信息保真度(Visual Information Fidelity, VIF)
VIF是Sheikh等结合自然图像统计模型、图像失真模型和人眼视觉系统模型提出的图像质量评价指标.
与峰值信噪比(Peak Signal-to-Noise Ratio, PSNR)、结构相似性(Structural Similarity, SSIM)等指标相比,VIF与主观视觉有更高的一致性。其值越大,表明图像质量越好。
PSNR,峰值信噪比
psnr是“Peak Signal to Noise Ratio”的缩写,即峰值信噪比,是一种评价图像的客观标准,它具有局限性,一般是用于最大值信号和背景噪音之间的一个工程项目。
PSNR是最普遍,最广泛使用的评鉴画质的客观量测法,不过许多实验结果都显示,PSNR的分数无法和人眼看到的视觉品质完全一致,
有可能PSNR较高者看起来反而比PSNR较低者差。这是因为人眼的视觉对于误差的敏感度并不是绝对的,其感知结果会受到许多因素的影响而产生变化
(例如:人眼对空间频率较低的对比差异敏感度较高,人眼对亮度对比差异的敏感度较色度高,人眼对一个区域的感知结果会受到其周围邻近区域的影响)
https://www.cnblogs.com/qrlozte/p/5340216.html
SSIM ,结构相似性
SSIM(structural similarity index),结构相似性,是一种衡量两幅图像相似度的指标。该指标首先由德州大学奥斯丁分校的图像和视频工程实验室(Laboratory for Image and Video Engineering)提出。
SSIM使用的两张图像中,一张为未经压缩的无失真图像,另一张为失真后的图像.
其中值的范围在0~1之间,1为完全一致,0为完全不一至。
http://blog.csdn.net/chaipp0607/article/details/70160307
MSE,均方误差
均方误差(mean-square error, MSE)是反映估计量与被估计量之间差异程度的一种度量。
https://stackoverflow.com/questions/20271479/what-does-it-mean-to-get-the-mse-mean-error-squared-for-2-images
图像质量主观评价
图像质量客观评价
全参考,Full-Reference,FR:
A)基于图像像素统计基础:计算待评图像和和参考图像对应像素点灰度值之间的差异,从统计角度衡量图像质量优劣。待评图像未F,参考图像为R,大小都为M*N。
缺点:从图像像素值的全局统计出发,未考虑人眼的局部视觉因素,因此对图像局部质量无法把握。
注:部分参考资料中,对上述两个公式采用多通道处理。
B)基于信息论基础:基于信息论中的信息熵基础,提出
通过计算待评图像和参考图像之间的互信息来衡量图像的质量优劣。扩展了图像与人眼之间的联系。
缺点:对图像的结构信息没有反应。
C)基于结构信息基础:提出者认为图像的结构失真的度量应是图像感知质量的最好近似。在此基础上提出了结构相似性度量。
其中正常数C1,C2,C3,用来调节分母接近0时的不稳定性,这三个成分因素综合起来就是SSIM指标。
SSIM值越大,图像质量越好,该指标算法实现简单,质量评估效果比较可靠。
半参考,也叫部分参考,Reduced-Reference,RR
无参考,也叫盲评价,blind quality,No-Reference,NR,由于理想图像很难获取,所以这种完全脱离了对理想参考图像依赖的质量评估方法应用较为广泛,无参考方法一般都是基于图像统计特征。
A)均值:图像像素的平均值,反应图像的平均亮度,平均亮度越大,图像质量越好,
B)标准差:图像像素灰度值相对于均值的离散程度,标准差越大,表明图像中灰度级分布越散,图像质量页就越好。
C)平均梯度:反应图像中细节反差和纹理变化,他在一定程度上反应图像的清晰度。
ΔxF(i,j) Δ x F ( i , j ) 表示像素点(i,j)在x上的一阶差分, ΔyF(i,j) Δ y F ( i , j ) 表示该点在y方向上的一阶差分。该公式有待商榷!
D)熵:指图像的平均信息量,从信息论的角度衡量图像中信息的多少,信息熵越大,说明图像包含的信息越多。假设图像中各个像素点的灰度值之间时相互独立的,图像的灰度分布为p={p1,p2,…..,pi,…….pn},其中Pi表示灰度值为i的像素的个数与总像素个数之比,而n为灰度级总数,则计算公式为
P(l) P ( l ) 为灰度值 l l 在图像中出现的概率,L为图像的灰度等级,如256灰度等级的图像,L=255.
图像评价参数
实验需要以下数据:MSE,PSNR,SSIM,mean、std、gradient、entropy。
/*
单幅图像信息熵计算
定义中,图像的信息熵通常采用灰度图计算
*/
double entropy(Mat & img)
{
double temp[256] = { 0.0f };
// 计算每个像素的累积值
int row = img.rows;
int col = img.cols;
for (int r = 0; rfor (int c = 0; c const uchar * i = img.ptr(r,c);
temp[*i] ++;
}
}
// 计算每个像素的概率
int size = row * col;
for (int i = 0; i<256; i++)
{
temp[i] = temp[i] / size;
}
double result = 0.0f;
// 计算图像信息熵
for (int i = 0; i<256; i++)
{
if (temp[i] != 0.0) {
result += temp[i] * log2(temp[i]);
}
}
return -result;
}
/*
计算平均梯度
梯度的计算应采用灰度图
公式?通用的都是 sqrt( (dx^2 + dy^2) /2 )
笔记中从书《数字图像处理及应用――谢凤英》摘录的公式有待商榷
*/
double meanGradient(Mat & grayImg) {
if (grayImg.channels() != 1) {
printf("avgGradient 参数错误,必须输入单通道图!");
return 0.0;
}
// 原灰度图转换成浮点型数据类型
Mat src;
grayImg.convertTo(src, CV_64FC1);
double temp = 0.0f;
// 由于求一阶差分的边界问题,这里行列都要-1
int rows = src.rows - 1;
int cols = src.cols - 1;
// 根据公式计算平均梯度
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
// 离散的delta就是相邻的离散点的差值
double dx = src.at<double>(r, c + 1) - src.at<double>(r, c);
double dy = src.at<double>(r + 1, c) - src.at<double>(r, c);
double ds = sqrt((dx*dx + dy * dy) / 2);
temp += ds;
}
}
double imageAVG = temp / (rows*cols);
return imageAVG;
}
/*计算灰度图的均值和方差*/
void mean_std(const Mat & grayImg, double & mean, double & std) {
if (grayImg.channels() != 1) {
printf("mean_std 参数错误,必须输入单通道图!");
return ;
}
Mat mat_mean, mat_stddev;
meanStdDev(grayImg, mat_mean, mat_stddev);
mean = mat_mean.at<double>(0, 0);
std = mat_stddev.at<double>(0, 0);
}
double getMSE(const Mat & src1, const Mat & src2)
{
Mat s1;
absdiff(src1, src2, s1); // |src1 - src2|
s1.convertTo(s1, CV_32F); // 不能在8位矩阵上做平方运算
s1 = s1.mul(s1); // |src1 - src2|^2
Scalar s = sum(s1); // 叠加每个通道的元素
double result = 0.0f;
int ch = s1.channels();
for (int i = 0; i < ch; i++) {
// 叠加所有通道
result += s.val[i];
}
if (result <= 1e-10) // 如果值太小就直接等于0
return 0;
else
return result / (ch*s1.total());
}
double getPSNR(const Mat& src1, const Mat& src2, double MSE) {
if (MSE <= 1e-10) {
return 0;
}
return 10.0*log10((255 * 255) / MSE);
}
double getMSSIM(const Mat& src1, const Mat& src2)
{
// 参数由经验公式取得
// C1=(K1*L)^2, C2=(K2*L)^2, C3=C2/2, 一般地K1=0.01, K2=0.03, L=255( 是像素值的动态范围,一般都取为255)
const double C1 = 6.5025, C2 = 58.5225;
const int TYPE = CV_32F;
// 不能在单字节类型上计算,范围溢出,需要转换
Mat I1, I2;
src1.convertTo(I1, TYPE);
src2.convertTo(I2, TYPE);
Mat I2_2 = I2.mul(I2); // I2^2
Mat I1_2 = I1.mul(I1); // I1^2
Mat I1_I2 = I1.mul(I2); // I1*I2
// 高斯函数计算图像的均值、方差以及协方差,而不是采用遍历像素点的方式,以换来更高的效率
Mat mu1, mu2;
GaussianBlur(I1, mu1, Size(11, 11), 1.5);
GaussianBlur(I2, mu2, Size(11, 11), 1.5);
Mat mu1_2 = mu1.mul(mu1);
Mat mu2_2 = mu2.mul(mu2);
Mat mu1_mu2 = mu1.mul(mu2);
Mat sigma1_2, sigma2_2, sigma12;
GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
sigma1_2 -= mu1_2;
GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
sigma2_2 -= mu2_2;
GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
sigma12 -= mu1_mu2;
Mat t1, t2, t3;
t1 = 2 * mu1_mu2 + C1;
t2 = 2 * sigma12 + C2;
t3 = t1.mul(t2);
t1 = mu1_2 + mu2_2 + C1;
t2 = sigma1_2 + sigma2_2 + C2;
t1 = t1.mul(t2);
Mat ssim_map;
divide(t3, t1, ssim_map);
Scalar SSIM = mean(ssim_map);
// 返回三个通道的SSIM的平均值,[0,1]之间
return (SSIM.val[2] + SSIM.val[1] + SSIM.val[0]) / 3 ;
}