项目实战: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技术点


OpenCV技术点


项目模块化部署

  项目的环境为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抓图,穿透应用,识别左右图区别,框选区别,微调位置)的主要内容,如果未能解决你的问题,请参考以下文章

实战:QT车牌识别系统综合设计

opencv实战-联合QT资料搜集

大家来找茬 两幅图像相减 其它好的实现? 美女找茬

延时抓图保存

(7拾遗)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练

[OpenCV实战]28 基于OpenCV的GUI库cvui