基于opencv的模板匹配【C++/Qt】【附源码】

文章目录

前言

本文主要简述基于C++结合opencv做的一个机器视觉的标准软件,主要实现功能是工件的定位,在自动化生产线中做视觉检测,本次功能实现的有3中定位算法:形状匹配,灰度匹配,可旋转匹配,界面开发使用标准的QT框架,当然此项目精度是没法保证的,如果想保障精度应用到生产环境中,建议使用halcon,halcon也会在后续的文章中提到, 此项目仅用于学习

一、项目工程及目录结构

1.编程环境

环境安装步骤百度一大堆我这里就不描述了,而且百度出来的安装教程基本都能用。
IDE:VisualStudio 2010
QT:V5.3
opencv:2.4
编程环境使用比较低的版本,本人测试过可以往高版本配置,代码不需要修改,只需要修改对应的库即可,
;本人测试过的环境:
IDE:VisualStudio 2019
QT:V5.12
opencv:4.2

2.项目目录结构及介绍

基于opencv的模板匹配【C++/Qt】【附源码】
本项目比较简单,从目录看,主要分为2个界面,主界面+标定界面,标定算法可以用在工业上的,因为里边其实就是普通的矩阵计算,没有设计什么算法优化。
还有一个封装的QT线程类,因为原生的线程本人认为不太好用也不太好控制,因此自己继承QThread后重写线程启动的方法。

; 二、代码构建

1.界面的编辑

基于opencv的模板匹配【C++/Qt】【附源码】
RobitVision.ui
此界面比较简单,中间窗体只有一个QLabel控件,然后还有一个菜单栏,此菜单栏就包含了本项目的功能:
基于opencv的模板匹配【C++/Qt】【附源码】
基于opencv的模板匹配【C++/Qt】【附源码】
基于opencv的模板匹配【C++/Qt】【附源码】
基于opencv的模板匹配【C++/Qt】【附源码】
从以上信息即可看到有哪些功能

; 2.代码构建

1.连接相机+预览


bool ConnectedCamera(int Type,int Num)
{
    if(Type == 0)
    {
        try{
            cap.open(Num);
            OpenCameraFlag = true;
            CameraType = Type;
            CameraNum = Num;
        }catch(...){}
    }
    return OpenCameraFlag;
}

bool DisConnectedCamera()
{
    if(CameraType == 0)
    {
        try{
            cap.release();
            OpenCameraFlag = false;
        }catch(...){}
    }
    return !OpenCameraFlag;
}

void RobotVision::on_QAction_Open_Close_Video_triggered()
{
    if(ui.QAction_Open_Close_Video->text() == QStringLiteral("开始预览") && CtuLibLink::CameraIsConnected())
    {
        connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
        workerThread->SetThreadFunc(&GetImage);
        workerThread->ThreadFlag = true;
        workerThread->start();
        ui.QAction_Open_Close_Video->setText(QStringLiteral("停止预览"));
    }
    else
    {
        disconnect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
        workerThread->stop();
        ui.QAction_Open_Close_Video->setText(QStringLiteral("开始预览"));
    }
}

workerThread是自定义的线程类,线程类代码如下:

QtThread::QtThread(QObject *parent)
    : QThread(parent)
{
    ThreadFlag = false;
    SleepTime = 50;
    pp = NULL;
}

QtThread::~QtThread()
{
    requestInterruption();
    stop();
    quit();
    wait();
}

void QtThread::run()
{
    while(ThreadFlag)
    {
        msleep(SleepTime);
        (*pp)();
    }
}

void QtThread::stop()
{
    m_bStopped = true;
    ThreadFlag = false;
}

void QtThread::SetThreadFunc(Fun pCallback)
{
    pp = pCallback;
}

我这里使用了一个函数指针,方便函数的回调,而且可让用户自定义,使用及其方便

2.定位算法


void RobotVision::on_QAction_CreateModel_triggered()
{
    std::string fileName= "";
    switch(Current_ModelNum)
    {
    case 0:
        fileName = "Model1.yml";
        break;
    case 1:
        fileName = "Model2.yml";
        break;
    case 2:
        fileName = "Model3.yml";
        break;
    default:
        return;
    }
    cv::FileStorage fs(fileName,cv::FileStorage::WRITE);
    fs<<"ModelNum"<< Current_ModelNum;
    fs<<"ModelFunc"<<Current_ModelFunc;
    fs<<"OrigianImage"<<ho_img;
    fs<<"ModelImage"<<model_roi;
    fs<<"ModelRect"<<Model_Rect;
    fs<<"Target_Point"<<Target_Point;
    fs<<"SeartchImage"<<Seartch_roi;
    fs<<"Seartch_Rect"<<Seartch_Rect;
    fs.release();

    myModelCom[Current_ModelNum].Current_ModelFunc = Current_ModelFunc;
    myModelCom[Current_ModelNum].O_Image = ho_img.clone();
    myModelCom[Current_ModelNum].Model_Image = model_roi.clone();
    myModelCom[Current_ModelNum].Model_Rect = Model_Rect;
    myModelCom[Current_ModelNum].Target_Point = Target_Point;
    myModelCom[Current_ModelNum].Seartch_Image = Seartch_roi.clone();
    myModelCom[Current_ModelNum].Seartch_Rect = Seartch_Rect;
    myModelCom[Current_ModelNum].Flag = true;
}

bool FindModel1(cv::Mat img,cv::Mat model,cv::Mat* dst,cv::Point* p)
    {
        try{

            cv::Mat img_display,result;

            int match_method = CV_TM_SQDIFF;
            img.copyTo(img_display);
            int result_cols = img.cols - model.cols+1;
            int result_rows = img.rows - model.rows+1;
            result.create(result_cols,result_rows,CV_32FC1);

            cv::matchTemplate(img,model,result,match_method);
            cv::normalize(result,result,0,1,cv::NORM_MINMAX,-1,cv::Mat());
            double minVal,maxVal;
            cv::Point minLoc,maxLoc,matchLoc;

            cv::minMaxLoc(result,&minVal,&maxVal,&minLoc,&maxLoc,cv::Mat());
            if(match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED)
            {
                matchLoc = minLoc;
            }
            else
            {
                matchLoc = maxLoc;
            }

            cv::rectangle(img_display,matchLoc,cv::Point(matchLoc.x+model.cols,matchLoc.y+model.rows),cv::Scalar::all(0),2,8,0);

            cv::rectangle(result,matchLoc,cv::Point(matchLoc.x+model.cols,matchLoc.y+model.rows),cv::Scalar::all(0),2,8,0);

            *dst = img_display.clone();
            *p = cv::Point(matchLoc.x+model.cols/2,matchLoc.y+model.rows/2);
            return true;
        }catch(...){return false;}
    }

3.标定算法

bool SetCalib(double ImageX[3],double Image_Y[3],double Robot_X[3],double Robot_Y[3])
{
    try{
        cv::Point2f srcTri[3];
        cv::Point2f dstTri[3];
        srcTri[0] = cv::Point2f(ImageX[0],Image_Y[0]);
        srcTri[1] = cv::Point2f(ImageX[1],Image_Y[1]);
        srcTri[2] = cv::Point2f(ImageX[2],Image_Y[2]);
        dstTri[0] = cv::Point2f(Robot_X[0], Robot_Y[0]);
        dstTri[1] = cv::Point2f(Robot_X[1], Robot_Y[1]);
        dstTri[2] = cv::Point2f(Robot_X[2], Robot_Y[2]);
        warp_mat = cv::getAffineTransform(srcTri, dstTri );
        return true;
    }catch(...){return false;}
}

总结

本项目最终效果:

RobotVision_Opencv 模板匹配视屏

源码:RobotVision_Opencv

Original: https://blog.csdn.net/ctu_sue/article/details/126966317
Author: 爱学习的广东仔
Title: 基于opencv的模板匹配【C++/Qt】【附源码】

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/704668/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球