【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】

简介: 【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】

模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术。利用给定的已知模板与待匹配的图像或数组计算匹配度,以达到寻找目标的目的。模板可以是矩形块也可以是一维数组,如果模板是一个矩阵,一般待匹配的数据也矩阵,如果模板是一个一维数据,那么待匹配的数据也最好是一维数据。模板匹配在图像处理中应用较为广泛,如通过设置匹配度的阈值用在异常检测中,通过阈值设定寻找给定的目标等等。

前言

越来越多的开发人员选择基于开源的Qt框架与OpenCV来实现界面和算法,其原因不单单是无版权问题,更多是两个社区的发展蓬勃,可用来学习的资料与例程特别丰富。以下是关于利用Qt构建GUI并使用OpenCV中的matchTemplate/minMaxLoc函数进行图像的模板匹配。

软件版本:Qt-5.12.0/OpenCV-4.5.3

平台:Windows10/11–64


一、函数介绍

1、matchTemplate

函数原型

cv::matchTemplate(InputArray image, InputArray templ, OutputArray result, int method );

参数解释

image:是输入图像,一般是Mat类数组;

templ:是模板数据,一般也是Mat类数组,长宽必须小于输入图像image的长宽;

result:是输出结果,大小为(w1-w2+1,h1-h2+1),其中w1为输入图像image的宽,w2为模板的宽,h1为输入图像image的高,h2为模板的高;

method:是模板匹配的匹配计算方式,可设置的参数有:


TM_SQDIFF:平均差匹配法

TM_SQDIFF_NORMED:归一化平均差匹配法

TM_CCORR:相关匹配法

TM_CCORR_NORMED:归一化相关匹配法

TM_CCOEFF:系数匹配法

TM_CCOEFF_NORMED:归一化系数匹配法

2、minMaxLoc

函数原型

cv::minMaxLoc(const SparseMat& src, double* minVal, double* maxVal, int* minIdx=0, int* maxIdx=0);


参数解释:

src:输入单通道数组(图像);

minVal:返回最小值的指针,若无须返回,此值置为NULL;

maxVal:返回最大值的指针,若无须返回,此值置为NULL;

minLoc:返回最小位置的指针(二维情况下),若无须返回,此值置为NULL;

maxLoc:返回最大位置的指针(二维情况下),若无须返回,此值置为NULL;

mask:用于选择子阵列的可选掩膜;

二、演示

1、GUI

如上图创建Method的QComboBox控件进行选择,Template的PushButton按钮选择掩膜,Match的PushButton按钮执行,对当前窗口的图像进行模板检测,并输出状态信息。

2、代码实现

matchBtn的clicked()槽函数的实现代码如下:

void MainWindow::on_matchBtn_clicked()
{
    std::size_t numView = ui->tabWidget->currentIndex() % 3;
    if (dispMat[numView]->empty())
    {
        outputInfo(2, tr("Please make sure the Mat exist!"));
        return;
    }

    QString fileName = ui->templateLineEdit->text();
    cv::Mat templateMat;

    if (!fileName.isEmpty())
    {
        templateMat = cv::imread(fileName.toStdString());
        if (templateMat.empty())
        {
            outputInfo(2, tr("Please make sure the template exist."));
            return;
        }
        else
        {
            outputInfo(1, tr("Template Mat success."));
        }
    }
    else
    {
        outputInfo(2, tr("Please make sure the template file name exist."));
        return;
    }

    *tmpMat = dispMat[numView]->clone();
    int matchMethod = ui->matchCombo->currentIndex();
    int resultCols = tmpMat->cols - templateMat.cols + 1;
    int resultRows = tmpMat->rows - templateMat.rows + 1;

    cv::Mat resultMat = cv::Mat::zeros(resultCols, \
                                       resultRows, \
                                       tmpMat->type());
    double startTime = static_cast<double>(cv::getTickCount());
    cv::matchTemplate(*tmpMat, templateMat, resultMat, matchMethod);
    cv::normalize(resultMat, resultMat, 0, 1, cv::NORM_MINMAX, -1, \
                  cv::Mat());
    double timeCost = (static_cast<double>(cv::getTickCount()) - \
                       startTime) / cv::getTickFrequency();
    QString costTime = "Cost time: " + QString::number(timeCost);
    outputInfo(1, costTime);

    double minVal, maxVal;
    cv::Point maxLoc, minLoc, matchLoc;
    cv::minMaxLoc(resultMat, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());

    /*
    if (matchMethod < 2)
    {
        matchLoc = minLoc;
    }
    else
    {
        matchLoc = maxLoc;
    }
    */

    matchLoc = (matchMethod < 2) ? minLoc : maxLoc;
    cv::rectangle(*tmpMat, matchLoc, \
                  cv::Point(matchLoc.x + templateMat.cols, \
                            matchLoc.y + templateMat.rows), \
                  cv::Scalar::all(0), 2, 8, 0);



    if (ui->matchChkBox->isChecked())
    {
        *dispMat[numView] = tmpMat->clone();
        cvtMatPixmap(dispMat, dispPixmap, numView);
    }
    else
    {
        if (tmpMat->channels() == 3)
        {
            QImage tmpImage = QImage(tmpMat->data, tmpMat->cols,tmpMat->rows, \
                         static_cast<int>(tmpMat->step), \
                         QImage::Format_RGB888);
            dispPixmap[numView]->setPixmap(QPixmap::fromImage(tmpImage.rgbSwapped()));
        }
        else
        {
            QImage tmpImage = QImage(tmpMat->data, tmpMat->cols,tmpMat->rows, \
                         static_cast<int>(tmpMat->step), \
                         QImage::Format_Grayscale8);
            dispPixmap[numView]->setPixmap(QPixmap::fromImage(tmpImage.rgbSwapped()));
        }

    }
    outputInfo(1, tr("Match done."));

    std::stringstream tmpStream;
    std::streambuf* coutBuf = std::cout.rdbuf();
    std::cout.rdbuf(tmpStream.rdbuf());
    std::cout << " matchLoc: " << matchLoc << std::endl;
    std::string matchLocString(tmpStream.str());
    std::cout.rdbuf(coutBuf);
    QString matchLocInfo = QString::fromStdString(matchLocString);

    int x = matchLoc.x;
    int y = matchLoc.y;
    ui->matchLineEdit->setText(QString::number(x) + "," \
                               + QString::number(y) + "," \
                               + QString::number(templateMat.cols + x) + "," \
                               + QString::number(templateMat.rows + y));
    outputInfo(1, matchLocInfo);
}

总结

以上是关于利用Qt进行GUI构建并使用OpenCV中的matchTemplate/minMaxLoc函数进行图像的模板匹配。

目录
相关文章
|
3月前
|
算法 计算机视觉
基于qt的opencv实时图像处理框架FastCvLearn实战
本文介绍了一个基于Qt的OpenCV实时图像处理框架FastCvLearn,通过手撕代码的方式详细讲解了如何实现实时人脸马赛克等功能,并提供了结果展示和基础知识回顾。
137 7
基于qt的opencv实时图像处理框架FastCvLearn实战
|
3月前
|
文字识别 计算机视觉 开发者
基于QT的OCR和opencv融合框架FastOCRLearn实战
本文介绍了在Qt环境下结合OpenCV库构建OCR识别系统的实战方法,通过FastOCRLearn项目,读者可以学习Tesseract OCR的编译配置和在Windows平台下的实践步骤,文章提供了技术资源链接,帮助开发者理解并实现OCR技术。
167 9
基于QT的OCR和opencv融合框架FastOCRLearn实战
|
2月前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
505 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
3月前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
53 4
|
3月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
|
3月前
|
计算机视觉
基于QT的opencv插件框架qtCvFrameLearn实战
这篇文章详细介绍了如何基于Qt框架开发一个名为qtCvFrameLearn的OpenCV插件,包括项目配置、插件加载、Qt与OpenCV图像转换,以及通过各个插件学习OpenCV函数的使用,如仿射变换、卡通效果、腐蚀、旋转和锐化等。
48 10
|
3月前
|
机器学习/深度学习 Java 计算机视觉
opencv4.5.5+qt5.15.2+vtk9.1+mingw81_64编译记录
本文记录了使用mingw81_64编译OpenCV 4.5.5、Qt 5.15.2、VTK 9.1的详细过程,包括编译结果截图、编译步骤、遇到的问题及其解决方案,以及相关参考链接。文中还提到了如何编译boost源码为静态库,并提供了测试代码示例。
opencv4.5.5+qt5.15.2+vtk9.1+mingw81_64编译记录
|
4月前
|
算法 计算机视觉 Python
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
WK
|
4月前
|
编解码 计算机视觉 Python
如何在OpenCV中进行图像转换
在OpenCV中,图像转换涉及颜色空间变换、大小调整及类型转换等操作。常用函数如`cvtColor`可实现BGR到RGB、灰度图或HSV的转换;`resize`则用于调整图像分辨率。此外,通过`astype`或`convertScaleAbs`可改变图像数据类型。对于复杂的几何变换,如仿射或透视变换,则可利用`warpAffine`和`warpPerspective`函数实现。这些技术为图像处理提供了强大的工具。
WK
123 1
|
4月前
|
计算机视觉
使用QT显示OpenCV读取的图片
使用QT显示OpenCV读取的图片
95 1