OpenCV 图像清晰度(相机自动对焦)

相机的自动对焦要求相机根据拍摄环境和场景的变化,通过相机内部的微型驱动马达,自动调节相机镜头和CCD之间的距离,保证像平面正好投影到CCD的成像表面上。这时候物体的成像比较清晰,图像细节信息丰富。

相机自动对焦的过程,其实就是对成像清晰度评价的过程,对焦不准确,拍摄出来的图像清晰度低,视觉效果模糊,如果是在工业检测测量领域,对焦不准导致的后果可能是致命的;对焦准确的图像清晰度较高,层次鲜明,对比度高。

图像清晰度评价算法有很多种,在空域中,主要思路是考察图像的领域对比度,即相邻像素间的灰度特征的梯度差;在频域中,主要思路是考察图像的频率分量,对焦清晰的图像高频分量较多,对焦模糊的图像低频分量较多。

这里实现3种清晰度评价方法,分别是Tenengrad梯度方法、Laplacian梯度方法和方差方法。

Tenengrad梯度方法

Tenengrad梯度方法利用Sobel算子分别计算水平和垂直方向的梯度,同一场景下梯度值越高,图像越清晰。以下是具体实现,这里衡量的指标是经过Sobel算子处理后的图像的平均灰度值,值越大,代表图像越清晰。

 1 #include <highgui/highgui.hpp>
 2 #include <imgproc/imgproc.hpp>
 3
 4 using namespace std;
 5 using namespace cv;
 6
 7 int main()
 8 {
 9     Mat imageSource = imread("2.jpg");
10     Mat imageGrey;
11
12     cvtColor(imageSource, imageGrey, CV_RGB2GRAY);
13     Mat imageSobel;
14     Sobel(imageGrey, imageSobel, CV_16U, 1, 1);
15
16     //图像的平均灰度
17     double meanValue = 0.0;
18     meanValue = mean(imageSobel)[0];
19
20     //double to string
21     stringstream meanValueStream;
22     string meanValueString;
23     meanValueStream << meanValue;
24     meanValueStream >> meanValueString;
25     meanValueString = "Articulation(Sobel Method): " + meanValueString;
26     putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2);
27     imshow("Articulation", imageSource);
28     waitKey();
29 }

使用三张测试图片模拟不同对焦。第一张最清晰,得分最高,第二三张越来越模糊,得分依次降低。

Laplacian梯度方法:

Laplacian梯度是另一种求图像梯度的方法,在上例的OpenCV代码中直接替换Sobel算子即可。

 1 #include <highgui/highgui.hpp>
 2 #include <imgproc/imgproc.hpp>
 3
 4 using namespace std;
 5 using namespace cv;
 6
 7 int main()
 8 {
 9     Mat imageSource = imread("1.jpg");
10     Mat imageGrey;
11
12     cvtColor(imageSource, imageGrey, CV_RGB2GRAY);
13     Mat imageSobel;
14
15     Laplacian(imageGrey, imageSobel, CV_16U);
16     //Sobel(imageGrey, imageSobel, CV_16U, 1, 1);
17
18     //图像的平均灰度
19     double meanValue = 0.0;
20     meanValue = mean(imageSobel)[0];
21
22     //double to string
23     stringstream meanValueStream;
24     string meanValueString;
25     meanValueStream << meanValue;
26     meanValueStream >> meanValueString;
27     meanValueString = "Articulation(Laplacian Method): " + meanValueString;
28     putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2);
29     imshow("Articulation", imageSource);
30     waitKey();
31 }

用同样的三张测试图片测试,结果一致,随着对焦模糊得分降低:

方差方法:

方差是概率论中用来考察一组离散数据和其期望(即数据的均值)之间的离散(偏离)成都的度量方法。方差较大,表示这一组数据之间的偏差就较大,组内的数据有的较大,有的较小,分布不均衡;方差较小,表示这一组数据之间的偏差较小,组内的数据之间分布平均,大小相近。

对焦清晰的图像相比对焦模糊的图像,它的数据之间的灰度差异应该更大,即它的方差应该较大,可以通过图像灰度数据的方差来衡量图像的清晰度,方差越大,表示清晰度越好。

 1 #include <highgui/highgui.hpp>
 2 #include <imgproc/imgproc.hpp>
 3
 4 using namespace std;
 5 using namespace cv;
 6
 7 int main()
 8 {
 9     Mat imageSource = imread("2.jpg");
10     Mat imageGrey;
11
12     cvtColor(imageSource, imageGrey, CV_RGB2GRAY);
13     Mat meanValueImage;
14     Mat meanStdValueImage;
15
16     //求灰度图像的标准差
17     meanStdDev(imageGrey, meanValueImage, meanStdValueImage);
18     double meanValue = 0.0;
19     meanValue = meanStdValueImage.at<double>(0, 0);
20
21     //double to string
22     stringstream meanValueStream;
23     string meanValueString;
24     meanValueStream << meanValue*meanValue;
25     meanValueStream >> meanValueString;
26     meanValueString = "Articulation(Variance Method): " + meanValueString;
27
28     putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2);
29     imshow("Articulation", imageSource);
30     waitKey();
31 }

方差数值随着清晰度的降低逐渐降低:

在工业应用中,最清晰的对焦拍摄出来的图像不一定是最好的,有可能出现摩尔纹(水波纹)现象,一般需要在最清晰对焦位置附件做一个微调。

原文地址:https://www.cnblogs.com/ybqjymy/p/12307254.html

时间: 2024-10-16 13:01:28

OpenCV 图像清晰度(相机自动对焦)的相关文章

c++ opencv 图像模糊度检测

参考博客: 1.基于OpenCV的图像模糊与否检测 2.无参考图像的清晰度评价方法 3.无参考图像的清晰度评价方法及c++实现 4.OpenCV 图像清晰度评价(相机自动对焦) 5.图像清晰度评价 原文地址:https://www.cnblogs.com/exciting/p/11423181.html

图像清晰度的评价及分析

图像清晰度的评价及分析 2016年07月28日 17:54:22 clxiaoclxiao 阅读数:17963更多 个人分类: opencv 在无参考图像的质量评价中,图像的清晰度是衡量图像质量优劣的重要指标,它能够较好的与人的主观感受相对应,图像的清晰度不高表现出图像的模糊.本文针对无参考图像质量评价应用,对目前几种较为常用的.具有代表性清晰度算法进行讨论分析,为实际应用中选择清晰度算法提供依据. (1)Brenner 梯度函数 Brenner梯度函数是最简单的梯度评价函数,它只是简单的计算相

opencv图像原地(不开辟新空间)顺时旋转90度

前一阵朋友碰到这么一道题:将图像原地顺时针旋转90度,不开辟新空间.此题看似平易(题目简短),仔细研究发现着实不容易.经过一番探索后,终于找到了正确的算法,但是当使用opencv实现时,有碰到了困难而且费了一番周折才找到问题所在. 首先,解决这个问题,先简化成原地90度旋转一M×N的矩阵A(注意不是N×N方阵).对于2×3的矩阵A = {1,2,3;4,5,6},其目标为矩阵B = {4,1;5,2;6,3}.因为是原地旋转,这里A和B应指向同一大小为6的内存空间. 这里有这样一个重要的导出公式

OpenCV &mdash;&mdash; 图像局部与部分分割(一)

背景减除 一旦背景模型建立,将背景模型和当前的图像进行比较,然后减去这些已知的背景信息,则剩下的目标物大致就是所求的前景目标了 缺点 -- 该方法基于一个不长成立的假设:所有像素点是独立的 场景建模 新的前景(物体移动的新位置) -- 旧的前景 (物体离开后留下的"空洞")-- 背景 cvInitLineIterator()  和  CV_NEXT_LINE_POINT() 对任意直线上的像素进行采样 // 从视频的一行中读出所有像素的RGB值,收集这些数值并将其分成三个文件 #inc

OpenCV &mdash;&mdash; 图像局部与分割(二)

分水岭算法 将图像中的边缘转化成"山脉",将均匀区域转化为"山谷" 分水岭算法首先计算灰度图像的梯度,这对山谷或没有纹理的盆地(亮度值低的点)的形成有效,也对山头或图像中没有主导线段的山脉(山脊对应的边缘)的形成有效.然后开始从用户指定点或算法得到的点开始"灌注"盆地知道这些区域连在一起.基于这样产生的标记就可以把区域合并到一起,合并后的区域又通过聚集的方式进行分割,好像图像被"填充"起来. cvWatershed 用 Inp

[转]OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

[OpenCV入门教程之十三]OpenCV图像金字塔:高斯金字塔.拉普拉斯金字塔与图片尺寸缩放 2014-05-18 18:58 36007人阅读 评论(54) 收藏 举报 本文章已收录于:  OpenCV知识库 本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 知乎:http

【OpenCV入门教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 知乎:http://www.zhihu.com/people/mao-xing-yun 邮箱: [email protected] 写作当前博文时配套使用的OpenCV版本: 2.4.9 这篇文章里,我们将一起探讨图像金字塔的一

Opencv 图像读取与保存问题

本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/49737357 本文仅对 Opencv图像读取与保存进行阐述,重在探讨图像读取与保存过程中应注意的细节问题. 1 图像读取 首先看一下,imread函数的声明: // C++: Mat based Mat imread(const string& filename, int flags=1 ); // C: IplImage based

Opencv 图像叠加 添加水印

Opencv 图像叠加 添加水印 C++: void Mat::copyTo(OutputArray m) const C++: void Mat::copyTo(OutputArray m, InputArray mask) const 这个函数可以复制图像到另一个图像或矩阵上,可选参数是掩码 由于叠加的图像大小不一定相等,比如我们这里把一张小照片加到一张大照片上 我们可以在大照片上设置一个和小照片一样大的感兴趣区域 不使用掩码的时候,我们载入一张png,和一张jpg #include <op