[Qt学习笔记]Qt下使用Halcon实现采图时自动对焦的功能(Brenner梯度法)

目录

1、介绍

在机器视觉的开发中,现在有很多通过电机去做相机的聚焦调节,对比手工调节,自动调节效果更好,而且其也能满足设备自动的需求,尤其在一些高倍成像的环境下应用场景更广泛,图像清晰度是衡量图像质量的一个重要的指标,手动调焦的过程是通过人为去判定图像的清晰度,调节镜头的焦距,使得图像从模糊到清洗,再到模糊的过程,确定清洗度的峰值,自动调焦就是通过算法对采集的每一张图像的清晰度进行评价,最终给出图像清晰的峰值,从而确定调焦获取的焦距最佳。

常见的图像清晰度评价一般都是基于梯度的方法,本文主要介绍Brenner梯度法。

本节使用了30张不同清晰度的图像来模拟相机采图时从对焦模糊到清晰再到模糊的过程。

2、实现方法

2.1 算法实现过程

复制代码
void MainWindow::AutoFocus(HObject ho_Image)
{
 
    HObject  ho_ImagePart00, ho_ImagePart20;
    HObject  ho_ImageSub, ho_ImageResult, ho_ImagePart01, ho_ImagePart10;
    HObject  ho_ImageSub1, ho_ImageResult1, ho_ImageSub2, ho_ImageResult2;

    HTuple  hv_I, hv_Width, hv_Height, hv_WindowID;
    HTuple  hv_Value, hv_Deviation;
    try
    {
        GetImageSize(ho_Image,&hv_Width,&hv_Height);
        CropPart(ho_Image, &ho_ImagePart00, 0, 0, hv_Width, hv_Height-2);
        ConvertImageType(ho_ImagePart00, &ho_ImagePart00, "real");
        CropPart(ho_Image, &ho_ImagePart20, 2, 0, hv_Width, hv_Height-2);
        ConvertImageType(ho_ImagePart20, &ho_ImagePart20, "real");
        SubImage(ho_ImagePart20, ho_ImagePart00, &ho_ImageSub, 1, 0);
        MultImage(ho_ImageSub, ho_ImageSub, &ho_ImageResult, 1, 0);
        Intensity(ho_ImageResult, ho_ImageResult, &hv_Value, &hv_Deviation);

        double d=hv_Deviation.D();
        QString strDev=QString::number(d,'f',3);
        ui->labDev->setText(strDev);

        //记录最大偏差值
        if(hv_PreDeviation<hv_Deviation)
        {
            hv_PreDeviation=hv_Deviation;
        }
    }
    catch(HalconCpp::HException &except)
    {
        qDebug()<<except.ProcName().Text()<<endl;
        qDebug()<<except.ErrorMessage().Text()<<endl;
        qDebug()<<except.ErrorCode()<<endl;
    }
}

如Brenner算法的公式所示,首先将图像转换成real类型,然后对图像进行图像差处理,然后进行图像乘积,最后获得平均值及偏差,把偏差作为清晰度的评价参数

2.2 模拟采集流程

这里创建一个线程,然后使用延时的定时器,从文件夹中依次读取30张图像,每张图像进行Brenner算法处理。

线程定义如下:

复制代码
    camera = new CameraCtrl();
    liveThread = new QThread();
    camera->moveToThread(liveThread);
    connect(liveThread,&QThread::finished,camera,&QObject::deleteLater);
    connect(this,&MainWindow::ContinuousGrab,camera,&CameraCtrl::HandleContinuousGrab);
    liveThread->start();

然后线程开始后进行连续读取图像处理流程

复制代码
//读取图像并调用Brenner算法函数
void CameraCtrl::HandleContinuousGrab()
{    
    HTuple  hv_I;
    HObject  ho_Image;    
    for (hv_I=1; hv_I<=30; hv_I+=1)
    {
        ReadImage(&ho_Image, ("E:/Qt_Test/AutoFacus/Buddha/"+hv_I)+".png");
        Delay_MSec(tInter);
        emit hobjectReady(ho_Image);
        if(isFocus==true)
        {
            emit hobjectFocus(ho_Image);
        }
    }
}

其中定义延时定时器

复制代码
void CameraCtrl::Delay_MSec(unsigned int msec)
{
    QEventLoop loop;//定义一个新的事件循环
    QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
    loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
}

3、总结

一个好的评价函数需要具有单峰性,无偏性,灵敏性,常见的图像清晰度评价的算法有多种,比如Brenner梯度法、Tenegrad梯度法、laplace梯度法、方差法、能量梯度法等等,本节只介绍了Brenner梯度法,目前反馈的Brenner梯度法效果较好,以后有机会会介绍一下其他的方法。

4、代码展示

本小例程的代码放到我的开源gitte项目里,欢迎一起学习,也希望能收获你的小星星。
AutoFacus源码

相关推荐
爱思考的小伙2 小时前
Qt-02:信号与槽
开发语言·qt
森G3 小时前
22、GUI控件类---------常见界面组件类
qt
森G5 小时前
21、信号和槽详解---------QT基础
qt
西装没钱买5 小时前
QT组播的建立和使用(绑定特定的网卡,绑定特定IP)
网络·c++·qt·udp·udp组播
森G6 小时前
20、元对象系统---------QT基础
qt
Laurence6 小时前
CMake 报错 Failed to find required Qt component WebEngineWidgets
qt·webengine·cmake·找不到
习惯就好zz6 小时前
Qt Quick 系统托盘完整实践
开发语言·qt·qml·系统托盘·system tray·qapplication·qguiapplication
笨笨马甲6 小时前
Qt集成OpenCV
开发语言·qt
笨笨马甲6 小时前
Qt 工业机器视觉开发
开发语言·qt
小灰灰搞电子7 小时前
Qt 打印输出:printf与qDebug的区别
开发语言·qt