项目实战:Qt+OpenCV大家来找茬(Qt抓图,穿透应用,识别左右图区别,框选区别,微调位置)
Posted 长沙红胖子Qt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目实战:Qt+OpenCV大家来找茬(Qt抓图,穿透应用,识别左右图区别,框选区别,微调位置)相关的知识,希望对你有一定的参考价值。
若该文为原创文章,转载请注明出处
本文章博客地址https://hpzwl.blog.csdn.net/article/details/124768637
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)
Qt开发专栏:项目实战(点击传送门)
OpenCV开发专栏(点击传送门)
前言
本项目的出现理由只是笔者的一个念头,于是利用专业Qt和Opencv相关的知识开发一个辅助工具,本文章仅用于Qt和Opencv结合的学习。
Demo演示效果
运行包下载地址(供测试学习)
CSDN粉丝0积分下载地址:https://download.csdn.net/download/qq21497936/85372782
QQ群下载地址:1047134658(点击“文件”搜索“findTheDifference”,群内与博文同步更新)
运行包+源码包下载地址(供测试学习)
CSDN下载地址:https://download.csdn.net/download/qq21497936/85372767
(注意:源码本博客后面都有,若是想一步到位,下载这个,源码编译版本为Qt5.9.x mingw32 + openCV3.4.10)
功能列表
- 应用程序可将某Q游戏界面套入内部区域,游戏方便操作;
- 抓图区域调整,可通过右上角区域,调整区域1和区域2的位置;
- 位置微调功能,点击按钮可像对应方向微调一个像素;
- 识别不同,调用opencv算法,识别不同处在游戏图上绘制显示区域;
- 游戏界面区域操作焦点为游戏界面;
- 可清空已经绘制的区域;
Qt技术点
- Qt窗口部分透明
《Qt实用技巧:实现不规则窗口的鼠标消息穿透,包括穿透到桌面和穿透到父窗口》; - Qt窗口透明区域鼠标穿透
《Qt实用技巧:使用非透明窗体鼠标穿透到桌面的设置方法》; - Qt窗口置顶
《Qt实用技巧:Qt窗口置顶》; - Qt绘图
《Qt开发技术:Qt绘图系统(一)绘图系统介绍》
《Qt开发技术:Qt绘图系统(二)QPainter详解》; - Qt双窗口叠加(底窗口+透明窗口层)
《Qt实用技巧:实现窗口透明的五种方法》中的方法五; - QLabel,QGroupBox,QSpinBox,QPushButton控件的使用
- Qt截取屏幕
《Qt实用技巧:截屏功能的实现》
OpenCV技术点
- OpenCV开发环境的搭建
《OpenCV开发笔记(〇):使用mingw530_32编译openCV3.4.1源码,搭建Qt5.9.3的openCV开发环境》 - OpenCV中的cv::Mat
《OpenCV开发笔记(三):OpenCV图像的概念和基本操作》 - OpenCV中QImage转换为cv::Mat
- OpenCV灰度化
《OpenCV开发笔记(六):OpenCV基础数据结构、颜色转换函数和颜色空间》 - OpenCV阈值化
《OpenCV开发笔记(二十八):带你学习图像识别之阈值化》 - OpenCV的中值滤波
《OpenCV开发笔记(十八):算法基础之非线性滤波-中值滤波》 - OpenCV的闭运算
《OpenCV开发笔记(二十四):算法基础之形态学滤波-闭运算》 - OpenCV的寻找边界
《OpenCV开发笔记(二十八):带你学习图像识别之阈值化》 - OpenCv的最小矩形
《OpenCV开发笔记(五十六):红胖子8分钟带你深入了解多种图形拟合逼近轮廓(图文并茂+浅显易懂+程序源码)》
项目模块化部署
项目的环境为Qt5.9.3 mingw32版本,使用QtCreator开发,配合mingw32版本的Opencv3.4.10,下图左侧为项目结构,右侧为实际文件夹部署结构。
Qt代码:DrawWdget
该类的主要作用:
- 覆盖在游戏窗口上
- 全部透明窗口用以当作游戏界面上的画布
- 对鼠标消息穿透(无法点击中)
- 识别出后绘制标记处不同的区域
Ui界面
为自动生成默认的,没有任何改动。
一共绘制两类图形,一类是框出抓取图的界面,一类是识别出后的区域,定义两个缓存变量,用以绘制对应的区域矩形。
DrawWidegt.h
#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H
#include <QWidget>
namespace Ui
class DrawWidget;
class DrawWidget : public QWidget
Q_OBJECT
public:
explicit DrawWidget(QWidget *parent = 0);
~DrawWidget();
public:
void setRect(int x, int y, int width, int height);
void setRect2(int x, int y, int width, int height);
void clearListRect();
void setListRect(QList<QRect> listRect);
protected:
void initControl();
protected:
void paintEvent(QPaintEvent *event);
protected:
void drawSelectRect(QPainter *painter);
void drawListRect(QPainter *painter);
private:
Ui::DrawWidget *ui;
private:
QColor _colorRect;
QRect _rect;
QRect _rect2;
QList<QRect> _listRect;
;
#endif // DRAWWIDGET_H
DrawWidget.cpp
#include "DrawWidget.h"
#include "ui_DrawWidget.h"
#include <QPainter>
#include <windows.h>
#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")
DrawWidget::DrawWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::DrawWidget),
_colorRect(Qt::red)
ui->setupUi(this);
setWindowFlag(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
initControl();
DrawWidget::~DrawWidget()
delete ui;
void DrawWidget::setRect(int x, int y, int width, int height)
_rect.setRect(x, y, width, height);
void DrawWidget::setRect2(int x, int y, int width, int height)
_rect2.setRect(x, y, width, height);
LOG << _rect << _rect2;
void DrawWidget::clearListRect()
_listRect.clear();
update();
void DrawWidget::setListRect(QList<QRect> listRect)
_listRect = listRect;
update();
void DrawWidget::initControl()
// 置顶
::SetWindowPos(HWND(this->winId()), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
void DrawWidget::paintEvent(QPaintEvent *event)
QPainter painter(this);
drawSelectRect(&painter);
drawListRect(&painter);
void DrawWidget::drawSelectRect(QPainter *painter)
painter->save();
painter->setPen(QPen(_colorRect, 4));
painter->drawRect(_rect);
painter->drawRect(_rect2);
painter->restore();
void DrawWidget::drawListRect(QPainter *painter)
painter->save();
painter->setPen(QPen(Qt::white, 2));
for(int index = 0; index < _listRect.size(); index++)
painter->drawRect(_rect.x() + _listRect.at(index).x(),
_rect.y() + _listRect.at(index).y(),
_listRect.at(index).width(),
_listRect.at(index).height());
painter->setPen(QPen(Qt::blue, 2));
for(int index = 0; index < _listRect.size(); index++)
painter->drawRect(_rect2.x() + _listRect.at(index).x(),
_rect2.y() + _listRect.at(index).y(),
_listRect.at(index).width(),
_listRect.at(index).height());
painter->restore();
Qt代码:FindDifferenceWidget
该类的主要作用:
- 作为主窗口提供一个套入找茬游戏界面的区域;
- 提供可以动态选取抓取区域的控件;
- 提供微调控件,微调应用窗口,并且让DrawWidget窗口与透明区域位置同步改变;
- 提供识别触发按钮,将识别结果反馈到DrawWidget;
- 清空按钮,将识别的结果进行清空,也就是删除识别结果的矩形;
Ui界面
FindDifferenceWidget.h
#ifndef FINDDIFFERENCEWIDGET_H
#define FINDDIFFERENCEWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QRect>
#include <QRegion>
#include <QList>
#include "FindDifferenceManager.h"
#include "DrawWidget.h"
#include <QElapsedTimer>
namespace Ui
class FindDifferenceWidget;
class FindDifferenceWidget : public QWidget
Q_OBJECT
public:
explicit FindDifferenceWidget(QWidget *parent = 0);
~FindDifferenceWidget();
protected:
void initControl();
void updateGameRect();
protected slots:
void slot_initControl();
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
void moveEvent(QMoveEvent *event);
void closeEvent(QCloseEvent *event);
protected slots:
void slot_valueChanged(int value);
protected slots:
void slot_findResult(bool result, QList<QRect> listRect = QList<QRect>());
private slots:
void on_pushButton_do_clicked();
void on_pushButton_up_clicked();
void on_pushButton_left_clicked();
void on_pushButton_right_clicked();
void on_pushButton_down_clicked();
void on_pushButton_clear_clicked();
private:
Ui::FindDifferenceWidget *ui;
private:
FindDifferenceManager *_pFindDifferenceManager;
QRect _rectGame;
QRect _rectApplication;
int _captionHeigh;
int _margin;
DrawWidget *_pDrawWidget;
;
#endif // FINDDIFFERENCEWIDGET_H
FindDifferenceWidget.cpp
#include "FindDifferenceWidget.h"
#include "ui_FindDifferenceWidget.h"
#include <windows.h>
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QTimer>
#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")
FindDifferenceWidget::FindDifferenceWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::FindDifferenceWidget),
_pFindDifferenceManager(0),
_pDrawWidget(0)
ui->setupUi(this);
QString version = "v1.0.0";
setWindowTitle(QString("大家来找茬(仅供学习Qt+OpenCV实战项目) Demo %1(作者:长沙红胖子 QQ:21497936 WX:15173255813 blog:hpzwl.blog.csdn.net").arg(version));
resize(1230, 785);
initControl();
QTimer::singleShot(0, this, SLOT(slot_initControl()));
FindDifferenceWidget::~FindDifferenceWidget()
delete ui;
void FindDifferenceWidget::initControl()
// 置顶
::SetWindowPos(HWND(this->winId()), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
// 识别类
_pFindDifferenceManager = new FindDifferenceManager();
connect(_pFindDifferenceManager, SIGNAL(signal_findResult(bool,QList<QRect>)),
this, SLOT(slot_findResult(bool,QList<QRect>)));
// 初始化
_captionHeigh = 26;
_margin = 3;
updateGameRect();
_pDrawWidget = new DrawWidget();
_pDrawWidget->show();
connect(ui->spinBox_image1X, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
connect(ui->spinBox_image1Y, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
connect(ui->spinBox_image1Width, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
connect(ui->spinBox_image1Height, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
connect(ui->spinBox_image2X, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
connect(ui->spinBox_image2Y, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
connect(ui->spinBox_image2Width, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
connect(ui->spinBox_image2Height, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
_pDrawWidget->setRect(ui->spinBox_image1X->value(),
ui->spinBox_image1Y->value(),
ui->spinBox_image1Width->value(),
ui->spinBox_image1Height->value());
_pDrawWidget->setRect2(ui->spinBox_image2X->value(),
ui->spinBox_image2Y->以上是关于项目实战:Qt+OpenCV大家来找茬(Qt抓图,穿透应用,识别左右图区别,框选区别,微调位置)的主要内容,如果未能解决你的问题,请参考以下文章