目的: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.测试运行