当前位置: 首页 > article >正文

QT + Opencv 实现灰度模板匹配

QT + Opencv 实现灰度模板匹配

实现思路

1.模板创建代码思路

1 初始化和准备:

使用 cv::buildPyramid 函数构建图像金字塔。图像金字塔是一种多分辨率表示,每个层级的图像分辨率逐步降低。
调整 m_TemplData 的大小以匹配图像金字塔的层级数。
计算每个层级的统计数据:

2遍历图像金字塔的每个层级。

计算当前层级图像的倒数面积 invArea,用于后续的归一化处理。
使用 cv::meanStdDev 函数计算当前层级图像的均值 templMean 和标准差 templSdv。
计算模板图像的归一化范数 templNorm,这是模板图像的归一化标准差的平方和。
检查 templNorm 是否小于 DBL_EPSILON,如果是,表示当前层级图像的方差接近于零,将其标记为 vecResultEqual1 为 true。
计算 templSum2,这是 templNorm 加上均值的平方和,然后除以 invArea。
计算 templNorm 的平方根,并归一化。
将计算得到的 invArea、templMean 和 templNorm 存储到 m_TemplData 中对应的位置。

模板训练代码:

//训练模板
void frmTemplateMatch::LearnPattern(const cv::Mat model, const int num_levels,s_TemplData &m_TemplData)
{
    qDebug()<<"train mode...";
    m_TemplData.clear();
    cv::buildPyramid(model, m_TemplData.vecPyramid, num_levels);
    int iSize = m_TemplData.vecPyramid.size();
    m_TemplData.resize(iSize);
    for (int i = 0; i < iSize; i++)
    {
        double invArea = 1. / ((double)m_TemplData.vecPyramid[i].rows * m_TemplData.vecPyramid[i].cols);
        cv::Scalar templMean, templSdv;
        double templNorm = 0, templSum2 = 0;
        cv::meanStdDev(m_TemplData.vecPyramid[i], templMean, templSdv);
        templNorm = templSdv[0] * templSdv[0] + templSdv[1] * templSdv[1] + templSdv[2] * templSdv[2] + templSdv[3] * templSdv[3];
        if (templNorm < DBL_EPSILON)
        {
            m_TemplData.vecResultEqual1[i] = true;
        }
        templSum2 = templNorm + templMean[0] * templMean[0] + templMean[1] * templMean[1] + templMean[2] * templMean[2] + templMean[3] * templMean[3];
        templSum2 /= invArea;
        templNorm = std::sqrt(templNorm);
        templNorm /= std::sqrt(invArea);
        m_TemplData.vecInvArea[i] = invArea;
        m_TemplData.vecTemplMean[i] = templMean;
        m_TemplData.vecTemplNorm[i] = templNorm;
    }
//    qDebug()<<"train mode end...";
    m_TemplData.bIsPatternLearned = true;
}

2.匹配思路

1同样先对原图进行构建金字塔,模板和原图的金字塔层数要一致。
2.角度计算与旋转

计算旋转角度步长dAngleStep,基于模板金字塔某层的尺寸和atan函数得到。初始化角度向量vecAngles,并分别向其中添加从0到angle_start_end以及从-dAngleStep到-angle_start_end的递增角度值。

3.一层一层进行匹配

匹配代码:

int frmTemplateMatch::MatchTemplate(const cv::Mat source, const cv::Mat model, cv::Mat& out_source, const bool use_roi, const MRectangle m_rectangle,  const int num_levels, const int angle_start_end, const int num_matches, const double max_overlap,
                                    const double int_score, const bool show_result, const int thickness,s_TemplData pTemplData,
                                    vector<s_SingleTargetMatch> &m_vecSingleTargetData)
{

        if (source.empty() || model.empty() || (model.size().area() > source.size().area()))
        {
            qDebug()<<"error1";
            return -1;
        }
        if ((model.cols < source.cols && model.rows > source.rows) || (model.cols > source.cols && model.rows < source.rows))
        {
            qDebug()<<"error2";
            return -1;
        }
        cv::Mat gray_source, gray_model;
        if (source.channels() == 3)
        {
            cv::cvtColor(source, gray_source, cv::COLOR_BGR2GRAY);
        }
        else if (source.channels() == 4)
        {
            cv::cvtColor(source, gray_source, cv::COLOR_RGBA2GRAY);
        }
        else
        {
            source.copyTo(gray_source);
        }
        if (model.channels() == 3)
        {
            cv::cvtColor(model, gray_model, cv::COLOR_BGR2GRAY | cv::COLOR_RGB2GRAY);
        }
        else if (model.channels() == 4)
        {
            cv::cvtColor(model, gray_model, cv::COLOR_RGBA2GRAY);
        }
        else
        {
            model.copyTo(gray_model);
        }
       // LearnPattern(gray_model, num_levels,pTemplData);
        qDebug()<<"is traind"<<pTemplData.bIsPatternLearned;

        vector<cv::Mat> vecMatSrcPyr = vector<cv::Mat>(100);
        vecMatSrcPyr.clear();
        cv::buildPyramid(gray_source, vecMatSrcPyr, num_levels);



        double dAngleStep = atan(2.0 / max(pTemplData.vecPyramid[num_levels].cols, pTemplData.vecPyramid[num_levels].rows)) * R2D;
        vector<double> vecAngles = vector<double>(360);
        vecAngles.clear();
        for (double dAngle = 0; dAngle < angle_start_end + dAngleStep; dAngle += dAngleStep)
        {
            vecAngles.push_back(dAngle);
        }
        for (double dAngle = -dAngleStep; dAngle > -angle_start_end - dAngleStep; dAngle -= dAngleStep)
        {
            vecAngles.push_back(dAngle);
        }

        qDebug()<<"match ----- 1";
        int iTopSrcW = vecMatSrcPyr[num_levels].cols, iTopSrcH = vecMatSrcPyr[num_levels].rows;
        cv::Point2f ptCenter((iTopSrcW - 1) / 2.0f, (iTopSrcH - 1) / 2.0f);
        int iSize = (int)vecAngles.size();
        vector<s_MatchParameter> vecMatchParameter(iSize * (num_matches + MATCH_CANDIDATE_NUM));
        vector<double> vecLayerScore(num_levels + 1, int_score);
        for (int iLayer = 1; iLayer <= num_levels; iLayer++)
            vecLayerScore[iLayer] = vecLayerScore[iLayer - 1] * 0.9;
#pragma omp parallel for  //并发处理

        for (int i = 0; i < iSize; i++)
        {

3实现效果

项目文件:
在这里插入图片描述

在这里插入图片描述


http://www.kler.cn/a/500115.html

相关文章:

  • 【Rust】切片类型
  • 解决ERROR: This version of pnpm requires at least Node.js xxx 的问题
  • element ui前端小数计算精度丢失的问题如何解决?
  • C语言期末回忆
  • 【权限管理】CAS(Central Authentication Service)
  • 【xLua】xLua-master签名、加密Lua文件
  • SVM赛道概览:MoveVM落地,SVM能走多远
  • 食堂采购系统源码:基于PHP的校园食堂供应链管理平台开发全解析
  • web前端-html
  • phpenc加密程序源码
  • 快速上手Git——Windows系统下Git的安装与简单使用流程
  • 【网络云SRE运维开发】2025第2周-每日【2025/01/09】小测-【第9章 VRRP原理及基本配置考试】理论和实操解析
  • 代理模式简介
  • 【深度学习】运算符
  • 树莓集团:数字资产什么意思?包括哪些?
  • vscode 无法使用npm, cmd命令行窗口可以正常执行
  • OpenCV的双边滤波函数
  • RabbitMQ 交换机、队列和路由键的命名规范
  • 大数据高级ACP学习笔记(4)
  • 【数据库】四、数据库管理与维护
  • 初识verilog HDL
  • 数学建模_基于支持回归向量机SVR的回归预测之预测新数据+Matlab代码包教会使用,直接替换数据即可
  • PHP与ThinkPHP连接数据库示例
  • 【漫话机器学习系列】043.提前停止训练(Early Stopping)
  • Java(五十)java-IO流-缓冲流(BufferedInputStream和BufferedOutputStream)
  • ubuntu NVIDIA 驱动程序安装指南