OpenCV 图像清晰度评价算法(相机自动对焦)

el/2024/6/13 11:54:51

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

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

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

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

Tenengrad梯度方法


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


#include <highgui/highgui.hpp>
#include <imgproc/imgproc.hpp>
 
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);
 
    //图像的平均灰度
    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();
}


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

 

Laplacian梯度方法:


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


#include <highgui/highgui.hpp>
#include <imgproc/imgproc.hpp>
 
using namespace std;
using namespace cv;
 
int main()
{
    Mat imageSource = imread("1.jpg");
    Mat imageGrey;
 
    cvtColor(imageSource, imageGrey, CV_RGB2GRAY);
    Mat imageSobel;
 
    Laplacian(imageGrey, imageSobel, CV_16U);
    //Sobel(imageGrey, imageSobel, CV_16U, 1, 1);
 
    //图像的平均灰度
    double meanValue = 0.0;
    meanValue = mean(imageSobel)[0];
 
    //double to string
    stringstream meanValueStream;
    string meanValueString;
    meanValueStream << meanValue;
    meanValueStream >> meanValueString;
    meanValueString = "Articulation(Laplacian Method): " + meanValueString;
    putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2);
    imshow("Articulation", imageSource);
    waitKey();
}


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

方差方法:


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

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


#include <highgui/highgui.hpp>
#include <imgproc/imgproc.hpp>
 
using namespace std;
using namespace cv;
 
int main()
{
    Mat imageSource = imread("2.jpg");
    Mat imageGrey;
 
    cvtColor(imageSource, imageGrey, CV_RGB2GRAY);
    Mat meanValueImage;
    Mat meanStdValueImage;
 
    //求灰度图像的标准差
    meanStdDev(imageGrey, meanValueImage, meanStdValueImage);
    double meanValue = 0.0;
    meanValue = meanStdValueImage.at<double>(0, 0);
 
    //double to string
    stringstream meanValueStream;
    string meanValueString;
    meanValueStream << meanValue*meanValue;
    meanValueStream >> meanValueString;
    meanValueString = "Articulation(Variance Method): " + meanValueString;
 
    putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2);
    imshow("Articulation", imageSource);
    waitKey();
}


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

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


http://www.ngui.cc/el/5545768.html

相关文章

一种新的图像清晰度评价函数

自动聚焦是机器人视觉、数字视频系统中的关键技术之--,是决定图像质量的重要因素,是获取清晰图 像的第1步。聚焦性能取决于调焦评价函数的准确性和有效性,即评价函数必须具有无偏性好、单峰性强和 较好的抗噪性能。图像模糊的本质是高频分量的损失,聚焦图像比离焦图像包含更多的…

委托事件的线程问题

事件注册方法或委托后&#xff0c;事件所在的线程执行注册的方法或委托&#xff0c;所以如果方法中有跨线程控件就需要使用invoke等处理。

图像灰度图,直方图,像素通道问题

1.图像直方图概述   直方图广泛运用于很多计算机视觉运用当中&#xff0c;通过标记帧与帧之间显著的边缘和颜色的统计变化&#xff0c;来检测视频中场景的变化。在每个兴趣点设置一个有相近特征的直方图所构成 “标签”&#xff0c;用以确定图像中的兴趣点。边缘、色彩、角度…

信号傅里叶变换后的实数和虚数部分理解

傅里叶&#xff08;FFT、DFT、傅立叶、Fourier&#xff09;傅里叶变换的结果为什么含有复数&#xff1f; 为什么傅里叶变换的结果含有复数成份&#xff1f; 看了很多关于FFT的资料&#xff0c;现在看到一个资料说FFT转换的结果是实部虚部&#xff0c;所以不理解为什么从时域转…

C++ 简单实现HTTP GET/POST 请求

HTTP(超文本传输协议)是一种客户端与服务端的传输协议&#xff0c;最早用于浏览器和服务器之间的通信&#xff0c;后来因为其使用灵活、方便等特点&#xff0c;广泛用于客户端与服务端的通信。文章将简单介绍HTTP协议&#xff0c;同时以C方式分别实现HTTP GET、POST 请求 HTTP …

C#无损高质量压缩图片实现代码

最近&#xff0c;项目上涉及到了图像压缩&#xff0c;发现原有的图像压缩功能&#xff0c;虽然保证了图像的大小300K以内&#xff0c;但是压缩后的图像看的不在清晰&#xff0c;并且&#xff0c;限定了图片的Height或者是Width。 在CSDN上看到了一个压缩算法&#xff1a;C#无损…

vs中c++项目的配置

首先&#xff0c;我们一般不会修改解决方案的属性&#xff0c;而是设置每个项目各自的属性. 接着上一篇文章&#xff0c;我们来看看我们应该怎样来设置各项目的项目属性更好&#xff1a; 我们以NYOJ_001项目的Debug版的设置为例&#xff1a; 在常规选项里&#xff0c;我们一…

关于opencv中Mat赋值(浅拷贝,深拷贝)原理

问题点&#xff1a; 有两个垫对象&#xff1a;mat_1和mat_2将mat_2赋值给mat_1&#xff08;mat_1 mat_2&#xff09;后&#xff0c;改变mat_1&#xff0c;mat_2也会被改变&#xff08;这里的改变是指图像处理&#xff09;。 原因&#xff1a; mat_1 mat_2是浅拷贝&#xff0…

c#中获取控件窗体句柄,获取窗体等的一些操作

1.Control.Handle 就是获取控件绑定到的窗口句柄。 2.control.IsHandleCreated 控件是否有与其关联的句柄 3.WinForm自定义函数FindControl实现按名称查找控件 public static Control FindControl(Control parentControl, string findCtrlName) { Control _findedCon…

c#滚动条创建实例,多线程

1.滚动条 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplicati…