最近想实现相机自动对焦,也就是需要图像清晰度评价,在网上查找。
http://nkwavelet.blog.163.com/blog/static/227756038201461532247117
这个对理论或者公式介绍很详细,共有16个计算方法,值得一学。
(1)Brenner 梯度函数
(2)Tenengrad 梯度函数
(3)Laplacian 梯度函数
(4)SMD(灰度方差)函数
...
后面是模糊检测,噪点检测,噪点和模糊的组合
文章注重理论,没有具体的样例程序。有结果对比图。
https://blog.csdn.net/dcrmg/article/details/53543341
这个集中上面前三个方法的实现,这3个在opencv 都有函数实现。实现3种清晰度评价方法,分别是Tenengrad梯度方法、Laplacian梯度方法和方差方法。
Tenengrad梯度方法,衡量的指标是经过Sobel算子处理后的图像的平均灰度值,值越大,代表图像越清晰。Sobel 函数。
Laplacian梯度方法:同上,但用的是 Laplacian 函数
方差方法:方差是概率论中用来考察一组离散数据和其期望(即数据的均值)之间的离散(偏离)程度的度量方法。方差较大,表示这一组数据之间的偏差就较大,组内的数据有的较大,有的较小,分布不均衡;方差较小,表示这一组数据之间的偏差较小,组内的数据之间分布平均,大小相近。方差越大,表示清晰度越好。
这个有样例程序可参考。
下面给出第一个算法的代码如下(第二个只是注销部分差异):
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat imageSource = imread("2.jpg");
Mat imageGrey;
cvtColor(imageSource, imageGrey, CV_RGB2GRAY);
Mat imageSobel;
Sobel(imageGrey, imageSobel, CV_16U, 1, 1);
//Laplacian(imageGrey, imageSobel, CV_16U); 算法2
//图像的平均灰度
double meanValue = 0.0;
meanValue = mean(imageSobel)[0];
//double to string
stringstream meanValueStream;
string meanValueString;
meanValueStream << meanValue;
meanValueStream >> meanValueString;
meanValueString = "Articulation(Sobel Method): " + meanValueString;
putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2);
imshow("Articulation", imageSource);
waitKey();
}
这里的评估值就是 meanValue ,值越大越清晰。// double to string 部分只是加在图上显示。
方差计算的差异是:
//求灰度图像的标准差
meanStdDev(imageGrey, meanValueImage, meanStdValueImage);
double meanValue = 0.0;
meanValue = meanStdValueImage.at(0, 0);
文中也提到:
在工业应用中,最清晰的对焦拍摄出来的图像不一定是最好的,有可能出现摩尔纹(水波纹)现象,一般需要在最清晰对焦位置附件做一个微调。