天天看点

Qt +opencv模板匹配

目的:Qt+opencv实现模板匹配

结果:只实现了个壳子,opencv的模板匹配不能旋转,放缩,匹配多目标,因此放弃了。或者可以但是我没有找到资料,了解的,麻烦码友们直接在评论通知我。

1.新建Qt项目,配置opencv

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

win32:CONFIG(release, debug|release): LIBS += -LE:/opencv/opencv4.1.0/opencv/build/x64/vc15/lib/ -lopencv_world410
else:win32:CONFIG(debug, debug|release): LIBS += -LE:/opencv/opencv4.1.0/opencv/build/x64/vc15/lib/ -lopencv_world410d
else:unix: LIBS += -LE:/opencv/opencv4.1.0/opencv/build/x64/vc15/lib/ -lopencv_world410

INCLUDEPATH += E:/opencv/opencv4.1.0/opencv/build/include
DEPENDPATH += E:/opencv/opencv4.1.0/opencv/build/include
           

2.widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include "opencv2/opencv.hpp"

#include <QWidget>
#include <QPushButton>
#include <QGroupBox>
#include <QRadioButton>
#include <QVBoxLayout>
#include <QCheckBox>
#include <QLabel>
#include <QTextEdit>
#include <QDebug>
#include <QMouseEvent>
#include <QPainter>
#include <math.h>

using namespace std;
using namespace cv;

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    QLabel *label1;
    QLabel *label2;
    QPushButton *Btn1;
    QPushButton *Btn2;
    QTextEdit *tEdit;

    Mat Img1;
    Mat Img2;

    Point2d Spoint = Point2d(0,0);
    Point2d Epoint = Point2d(0,0);

    bool IsCutting = false;


private slots:
    void on_clicked1();
    void on_clicked2();

protected:
    void mousePressEvent(QMouseEvent * event);
    void mouseMoveEvent(QMouseEvent * e);
    void mouseReleaseEvent(QMouseEvent * e);
    //void paintEvent(QPaintEvent *event);
    Point getNextMinLoc(Mat &result, Point minLoc, int maxValue, int templatW, int templatH);
};
#endif // WIDGET_H
           

Widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->setFixedSize(1000,600);//设置窗口的大小
    this->setWindowTitle("TemplateMatching");
    //cv::Mat src = cv::imread("E:/Images/tiffany.bmp");
    //cv::imshow("图像显示",src);
    //cv::waitKey(0);
    //cv::destroyAllWindows();
    //this->setMouseTracking(false);

    //this->setAttribute(Qt::WA_TransparentForMouseEvents, f);

    label1 = new QLabel(this);
    label1->setGeometry(25,25,200,200);

    //Img1 = imread("E:/Images/tiffany.bmp");
    //F:\backup\learnOpenCV4-master\learnOpenCV4-master\data/
    Img1 = imread("F:/backup/learnOpenCV4-master/learnOpenCV4-master/data/rice.png");
    //Mat grayImg;
    //cvtColor(srcImg, grayImg, COLOR_BGR2GRAY);

    Mat temp = Img1;
    QImage Qtemp;
    //int isGray = 1;

    //cvtColor(srcImg, temp, COLOR_BGR2GRAY);//BGR convert to RGB
    //Qtemp = QImage((const unsigned char*)(temp.data), temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
    Qtemp = QImage((const unsigned char*)(temp.data), temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
    Mat M(label1->width(),label1->height(), CV_8UC3, Scalar(128,128,128));
    QImage Qtemp1 = QImage((const unsigned char*)(M.data), M.cols, M.rows, M.step, QImage::Format_RGB888);
    //QImage Qtemp1 = Qtemp.scaled(label1->width(), label1->height());
    label1->setPixmap(QPixmap::fromImage(Qtemp1));
    //label1->resize(Qtemp.size());
    label1->show();



    label2 = new QLabel(this);
    label2->setGeometry(425,25,550,550);
    //Mat out(img.size(), img.type(), Scalar(255));

    QImage Qtemp2 = Qtemp.scaled(label2->width(), label2->height());
    label2->setPixmap(QPixmap::fromImage(Qtemp2));
    //label1->resize(Qtemp.size());
    label2->show();

    Btn1 = new QPushButton(this);
    Btn1->setText("Template");
    Btn1->setGeometry(250,25,100,50);

    Btn2 = new QPushButton(this);
    Btn2->setText("Matching");
    Btn2->setGeometry(250,100,100,50);


    tEdit = new QTextEdit(this);
    tEdit->setGeometry(25,250,325,325);
    tEdit->setReadOnly(true);


    connect(this->Btn1,SIGNAL(clicked()),this,SLOT(on_clicked1()));
    connect(this->Btn2,SIGNAL(clicked()),this,SLOT(on_clicked2()));


}

Widget::~Widget()
{
}

void Widget::on_clicked1(){
    qDebug() << "ok1";
    qDebug() << "Start clipping";
    IsCutting = true;

}

void Widget::on_clicked2(){
    qDebug() << "ok2";
    /*
    Mat dstImg;
    dstImg.create(Img1.dims, Img1.size, Img1.type());
    matchTemplate(Img1, Img2, dstImg, TM_SQDIFF);
    cv::Point minPoint;
    cv::Point maxPoint;
    //double* minVal = 0;
    //double* maxVal = 0;
    //cv::minMaxLoc(dstImg, minVal, maxVal, &minPoint, &maxPoint);
    double minVal = 0;
    double maxVal = 0;
    cv::minMaxLoc(dstImg, &minVal, &maxVal, &minPoint, &maxPoint);
    Mat Img3 = Img1.clone();
    cv::rectangle(Img3, minPoint, cv::Point(minPoint.x + Img2.cols, minPoint.y + Img2.rows), cv::Scalar(255, 255, 0), 2, 8);
    qDebug()<<"minVal2:"<<minVal;
    QImage Qtemp = QImage((const unsigned char*)(Img3.data), Img3.cols, Img3.rows, Img3.step, QImage::Format_RGB888);
    QImage Qtemp1 = Qtemp.scaled(label2->width(), label2->height());
    label2->setPixmap(QPixmap::fromImage(Qtemp1));
    label2->show();
    */

    /*

    Mat src = Img1;
    Mat srcCopy = src.clone();

    Mat temp = Img2;
    Mat result;

    vector<Mat> templat;
    vector<float> minV;
    vector<Point> minL;



    int srcW, srcH, templatW, templatH, resultH, resultW;
    srcW = src.cols;
    srcH = src.rows;
    templat.push_back(temp);
    double minValue, maxValue;
    Point minLoc, maxLoc;

    for (int i=0;i<10;i++)
    {
        cout << i << ": ";
        templatW = templat[i].cols;
        templatH = templat[i].rows;



        resultW = srcW - templatW + 1;
        resultH = srcH - templatH + 1;

        result.create(Size(resultW, resultH), CV_32FC1);
        matchTemplate(src, templat[i], result, TM_SQDIFF_NORMED);

        minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc);

        cout << "min1: " << minValue << endl;
        //if (minValue<=0.070055)
        if (minValue<=0.04055)
        {
            rectangle(srcCopy, minLoc, Point(minLoc.x + templatW, minLoc.y + templatH), Scalar(0, 0, 255), 2, 8, 0);

            Point new_minLoc;
            new_minLoc = getNextMinLoc(result, minLoc, maxValue, templatW, templatH);

            float *data = result.ptr<float>(new_minLoc.y);

            cout << "min2: " << data[new_minLoc.x] << " ";
            if (data[new_minLoc.x]<=0.5)
            {

                rectangle(srcCopy, new_minLoc, Point(new_minLoc.x + templatW, new_minLoc.y + templatH),
                          Scalar(0, 255, 0), 2, 8, 0);
                new_minLoc = getNextMinLoc(result, new_minLoc, maxValue, templatW, templatH);
            }

            float *data1 = result.ptr<float>(new_minLoc.y);
            cout << "min3: " << data1[new_minLoc.x] << " " << endl;
            if (data1[new_minLoc.x] <= 0.4)
            {

                rectangle(srcCopy, new_minLoc, Point(new_minLoc.x + templatW, new_minLoc.y + templatH),
                          Scalar(255, 0, 0), 2, 8, 0);
            }

        }
        cout << "#" << endl;
        Mat temp_templat;
        //cv::resize(templat[i], temp_templat, Size(templat[i].cols / 1.1, templat[i].rows / 1.1));
        cv::resize(templat[i], temp_templat, Size(templat[i].cols / 1.0, templat[i].rows / 1.0));
        templat.push_back(temp_templat);
    }

    imshow("result", srcCopy);
    waitKey(0);

   */


    Mat src = Img1;
    Mat srcCopy = src.clone();

    Mat temp = Img2;
    Mat result;

    vector<Mat> templat;
    vector<float> minV;
    vector<Point> minL;

    int srcW, srcH, templatW, templatH, resultH, resultW;
    srcW = src.cols;
    srcH = src.rows;
    templat.push_back(temp);
    double minValue, maxValue;
    Point minLoc, maxLoc;

    for (int i=0;i<10;i++)
    {
        cout << i << ": ";
        templatW = templat[i].cols;
        templatH = templat[i].rows;

        resultW = srcW - templatW + 1;
        resultH = srcH - templatH + 1;

        result.create(Size(resultW, resultH), CV_32FC1);
        matchTemplate(src, templat[i], result, TM_SQDIFF_NORMED);

        minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc);

        cout << "min1: " << minValue << endl;
        //if (minValue<=0.070055)
        if (minValue<=0.5)
        {
            rectangle(srcCopy, minLoc, Point(minLoc.x + templatW, minLoc.y + templatH), Scalar(0, 0, 255), 2, 8, 0);

            Point new_minLoc;
            new_minLoc = getNextMinLoc(result, minLoc, maxValue, templatW, templatH);

            float *data = result.ptr<float>(new_minLoc.y);

            cout << "min2: " << data[new_minLoc.x] << " ";
            if (data[new_minLoc.x]<=0.5)
            {

                rectangle(srcCopy, new_minLoc, Point(new_minLoc.x + templatW, new_minLoc.y + templatH),
                          Scalar(0, 255, 0), 2, 8, 0);
                new_minLoc = getNextMinLoc(result, new_minLoc, maxValue, templatW, templatH);
            }

            float *data1 = result.ptr<float>(new_minLoc.y);
            cout << "min3: " << data1[new_minLoc.x] << " " << endl;
            if (data1[new_minLoc.x] <= 0.5)
            {

                rectangle(srcCopy, new_minLoc, Point(new_minLoc.x + templatW, new_minLoc.y + templatH),
                          Scalar(255, 0, 0), 2, 8, 0);
            }

        }
        cout << "#" << endl;
        Mat temp_templat;
        //cv::resize(templat[i], temp_templat, Size(templat[i].cols / 1.1, templat[i].rows / 1.1));
        cv::resize(templat[i], temp_templat, Size(templat[i].cols / 1.0, templat[i].rows / 1.0));
        templat.push_back(temp_templat);
    }

    //imshow("result", srcCopy);
    //waitKey(0);
    QImage Qtemp = QImage((const unsigned char*)(srcCopy.data), srcCopy.cols, srcCopy.rows, srcCopy.step, QImage::Format_RGB888);
    QImage Qtemp1 = Qtemp.scaled(label2->width(), label2->height());
    label2->setPixmap(QPixmap::fromImage(Qtemp1));
    label2->show();


}

//鼠标 点击
void Widget::mousePressEvent(QMouseEvent *e)
{
    //获取点击的下标
    //qDebug() << e->x() << ":" << e->y();
    //label2->geometry().y();
    if(e->button() == Qt::LeftButton && e->x()>label2->geometry().x() && e->x() < label2->geometry().x()+label2->width() \
            && e->y()>label2->geometry().y() && e->y() < label2->geometry().y()+label2->height())
    {
        qDebug() << "左键" ;
        Spoint.x = e->x();
        Spoint.y = e->y();
    }
    qDebug() <<  Spoint.x << ":" << Spoint.y;
    /*
    if(e->button() == Qt::LeftButton)
    {
        qDebug() << "左键" ;
    }
    else if(e->button() == Qt::RightButton)
    {
        qDebug() << "右键" ;
    }
    */
}

//鼠标 移动
void Widget::mouseMoveEvent(QMouseEvent * e)
{
    //qDebug() << "move" << e->x() << ":" << e->y();

    //未出界

    Epoint.x = e->x();
    Epoint.y = e->y();

    if(e->x()<label2->geometry().x())
    {
        Epoint.x = label2->geometry().x();
    }
    if(e->x()>label2->geometry().x()+label2->width())
    {
        Epoint.x =label2->geometry().x()+label2->width();
    }
    if(e->y()<label2->geometry().y())
    {
        Epoint.y =label2->geometry().y();
    }
    if(e->y()>label2->geometry().y()+label2->height())
    {
        Epoint.y =label2->geometry().y()+label2->height();
    }
    qDebug() << "move" << Epoint.x<< ":" << Epoint.y;
    /*
    Rect rect(Spoint.x, Spoint.y, Epoint.x-Spoint.x, Epoint.y-Spoint.y);

    rectangle (Img1,  rect,Scalar(0, 0, 0), -1, 8, 0);
    QImage Qtemp = QImage((const unsigned char*)(Img1.data), Img1.cols, Img1.rows, Img1.step, QImage::Format_RGB888);
    QImage Qtemp1 = Qtemp1.scaled(label2->width(), label2->height());
    label2->setPixmap(QPixmap::fromImage(Qtemp1));
    //label1->resize(Qtemp.size());
    label2->show();
    */


    qDebug()<<"Rect1:"<<Spoint.x-label2->geometry().x();
    qDebug()<<"Rect2:"<<Spoint.y-label2->geometry().y();
    qDebug()<<"Rect3:"<<Epoint.x-Spoint.x;
    qDebug()<<"Rect4:"<<Epoint.y-Spoint.y;
    int Rect_width;
    int Rect_height;
    if (Epoint.x-Spoint.x<=0){
        Rect_width = 0;
    }else{
        Rect_width = Epoint.x-Spoint.x;
    }
    if (Epoint.y-Spoint.y<=0){
        Rect_height = 0;
    }else{
        Rect_height = Epoint.y-Spoint.y;
    }
    Rect rect(Spoint.x-label2->geometry().x(), Spoint.y-label2->geometry().y(),Rect_width, Rect_height);


    Mat Img3;
    Img1.copyTo(Img3);

    //Img3.reshape(3,label2->width(),label2->height());
    cv::resize(Img3,Img3,Size(label2->width(), label2->height()),0,0,INTER_NEAREST);
    rectangle (Img3,  rect,Scalar(0, 255, 0), 3, 8, 0);

    QImage Qtemp = QImage((const unsigned char*)(Img3.data), Img3.cols, Img3.rows, Img3.step, QImage::Format_RGB888);
    //QImage Qtemp1 = Qtemp.scaled(label2->width(), label2->height());
    label2->setPixmap(QPixmap::fromImage(Qtemp));
    //label1->resize(Qtemp.size());
    label2->show();





}




//鼠标 松开
void Widget::mouseReleaseEvent(QMouseEvent * e)
{
    //qDebug() << "Release" << e->x() << ":" << e->y();
    //Rect rect(0, 0, 100, 100);
    //qDebug() << "Release" << rect.data;
    /*
    Rect rect(Spoint.x-label2->geometry().x(), Spoint.y-label2->geometry().y(),Epoint.x-Spoint.x, Epoint.y-Spoint.y);

    rectangle (Img1,  rect,Scalar(0, 0, 0), 1, 8, 0);
    QImage Qtemp = QImage((const unsigned char*)(Img1.data), Img1.cols, Img1.rows, Img1.step, QImage::Format_RGB888);
    QImage Qtemp1 = Qtemp.scaled(label2->width(), label2->height());
    label2->setPixmap(QPixmap::fromImage(Qtemp1));
    //label1->resize(Qtemp.size());
    label2->show();
    */
    /*
    Rect rect(Spoint.x-label2->geometry().x(), Spoint.y-label2->geometry().y(),Epoint.x-Spoint.x, Epoint.y-Spoint.y);
    Mat ROI = Img1(rect);
    QImage Qtemp = QImage((const unsigned char*)(ROI.data), ROI.cols, ROI.rows, ROI.step, QImage::Format_RGB888);
    QImage Qtemp1 = Qtemp.scaled(label1->width(), label1->height());
    label1->setPixmap(QPixmap::fromImage(Qtemp1));
    label1->show();
    */
    /*
    Rect rect(Spoint.x-label2->geometry().x(), Spoint.y-label2->geometry().y(),Epoint.x-Spoint.x-10, Epoint.y-Spoint.y-10);
    Mat ROI = Img1(rect);
    QImage Qtemp = QImage((const unsigned char*)(ROI.data), ROI.cols, ROI.rows, ROI.step, QImage::Format_RGB888);
    QImage Qtemp1 = Qtemp.scaled(label1->width(), label1->height());
    label1->setPixmap(QPixmap::fromImage(Qtemp1));
    label1->show();
    */
    qDebug()<<"myx1:"<<Spoint.x-label2->geometry().x();
    qDebug()<<"myy1:"<<Spoint.y-label2->geometry().y();
    qDebug()<<"myx2:"<<Epoint.x-Spoint.x;
    qDebug()<<"myy2:"<<Epoint.y-Spoint.y;

    int Rect_width;
    int Rect_height;
    if (Epoint.x-Spoint.x<=0){
        Rect_width = 0;
    }else{
        Rect_width = Epoint.x-Spoint.x;
    }
    if (Epoint.y-Spoint.y<=0){
        Rect_height = 0;
    }else{
        Rect_height = Epoint.y-Spoint.y;
    }
    Rect rect(Spoint.x-label2->geometry().x(), Spoint.y-label2->geometry().y(),Rect_width, Rect_height);


    //Rect rect(Spoint.x-label2->geometry().x(), Spoint.y-label2->geometry().y(),Epoint.x-Spoint.x, Epoint.y-Spoint.y);
    Mat Img3;
    Img1.copyTo(Img3);

    //Img3.reshape(3,label2->width(),label2->height());
    cv::resize(Img3,Img3,Size(label2->width(), label2->height()),0,0,INTER_NEAREST);

    Mat ROI = Img3(rect);
    QImage Qtemp = QImage((const unsigned char*)(ROI.data), ROI.cols, ROI.rows, ROI.step, QImage::Format_RGB888);
    QImage Qtemp1 = Qtemp.scaled(label1->width(), label1->height());
    label1->setPixmap(QPixmap::fromImage(Qtemp1));
    label1->show();

    Img2 = ROI;

}

Point Widget::getNextMinLoc(Mat &result, Point minLoc, int maxValue, int templatW, int templatH)
{
    //imshow("result", result);
    //cout << "maxvalue: " << maxValue << endl;
    int startX = minLoc.x - templatW / 3;
    int startY = minLoc.y - templatH / 3;
    int endX = minLoc.x + templatW / 3;
    int endY = minLoc.y + templatH / 3;
    if (startX < 0 || startY < 0)
    {
        startX = 0;
        startY = 0;
    }
    if (endX > result.cols - 1 || endY > result.rows - 1)
    {
        endX = result.cols - 1;
        endY = result.rows - 1;
    }
    int y, x;
    for (y = startY; y < endY; y++)
    {
        for (x = startX; x < endX; x++)
        {
            float *data = result.ptr<float>(y);

            data[x] = maxValue;
        }
    }
    double new_minValue, new_maxValue;
    Point new_minLoc, new_maxLoc;
    minMaxLoc(result, &new_minValue, &new_maxValue, &new_minLoc, &new_maxLoc);
    //imshow("result_end", result);
    return new_minLoc;

}
           

3.测试运行

Qt +opencv模板匹配
Qt +opencv模板匹配