项目实战: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_OBJECTpublic: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_OBJECTpublic: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->value(),ui->spinBox_image2Width->value(),ui->spinBox_image2Height->value());}void FindDifferenceWidget::updateGameRect()
{_rectApplication = QRect(-_margin,-_captionHeigh,rect().width() + _margin*2,rect().height() + _captionHeigh + _margin);_rectGame = QRect(_margin, rect().height() - _margin - 780, 1032, 780);
}void FindDifferenceWidget::slot_initControl()
{_pDrawWidget->setGeometry(ui->frame_mask->mapToGlobal(QPoint(0, 0)).x(),ui->frame_mask->mapToGlobal(QPoint(0, 0)).y(),ui->frame_mask->width(),ui->frame_mask->height());}void FindDifferenceWidget::paintEvent(QPaintEvent *event)
{#if 1QRegion r1(_rectApplication);QRegion r2(_rectGame);QRegion r3 = r1 - r2;setMask(r3);
#endifQWidget::paintEvent(event);
}void FindDifferenceWidget::resizeEvent(QResizeEvent *event)
{// 初始化updateGameRect();if(_pDrawWidget){_pDrawWidget->setGeometry(ui->frame_mask->mapToGlobal(QPoint(0, 0)).x(),ui->frame_mask->mapToGlobal(QPoint(0, 0)).y(),ui->frame_mask->width(),ui->frame_mask->height());}
}void FindDifferenceWidget::moveEvent(QMoveEvent *event)
{if(_pDrawWidget){_pDrawWidget->setGeometry(ui->frame_mask->mapToGlobal(QPoint(0, 0)).x(),ui->frame_mask->mapToGlobal(QPoint(0, 0)).y(),ui->frame_mask->width(),ui->frame_mask->height());}LOG << geometry();
}void FindDifferenceWidget::closeEvent(QCloseEvent *event)
{_pDrawWidget->hide();_pDrawWidget->deleteLater();
}void FindDifferenceWidget::slot_valueChanged(int value)
{_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->value(),ui->spinBox_image2Width->value(),ui->spinBox_image2Height->value());_pDrawWidget->update();QSpinBox *pSpinBox = dynamic_cast<QSpinBox *>(sender());if(pSpinBox == ui->spinBox_image1Width){ui->spinBox_image2Width->setValue(value);}else if(pSpinBox == ui->spinBox_image2Width){ui->spinBox_image1Width->setValue(value);}else if(pSpinBox == ui->spinBox_image1Height){ui->spinBox_image2Height->setValue(value);}else if(pSpinBox == ui->spinBox_image2Height){ui->spinBox_image1Height->setValue(value);}
}void FindDifferenceWidget::slot_findResult(bool result, QList<QRect> listRect)
{if(result){LOG << listRect;_pDrawWidget->setListRect(listRect);}
}void FindDifferenceWidget::on_pushButton_do_clicked()
{_pDrawWidget->clearListRect();QElapsedTimer elapsedTimer;elapsedTimer.start();while(elapsedTimer.elapsed() < 500){qApp->processEvents();}QScreen * pScreen = QApplication::primaryScreen();QImage gameImage = pScreen->grabWindow(QApplication::desktop()->winId(),ui->frame_mask->mapToGlobal(QPoint(0, 0)).x(),ui->frame_mask->mapToGlobal(QPoint(0, 0)).y(),ui->frame_mask->width(),ui->frame_mask->height()).toImage();QImage image1 = gameImage.copy(ui->spinBox_image1X->value(),ui->spinBox_image1Y->value(),ui->spinBox_image1Width->value(),ui->spinBox_image1Height->value());QImage image2 = gameImage.copy(ui->spinBox_image2X->value(),ui->spinBox_image2Y->value(),ui->spinBox_image2Width->value(),ui->spinBox_image2Height->value());_pFindDifferenceManager->slot_findDiffrence(image1, image2);
}void FindDifferenceWidget::on_pushButton_up_clicked()
{setGeometry(geometry().x(), geometry().y() - 1, geometry().width(), geometry().height());
}void FindDifferenceWidget::on_pushButton_left_clicked()
{setGeometry(geometry().x() - 1, geometry().y(), geometry().width(), geometry().height());
}void FindDifferenceWidget::on_pushButton_right_clicked()
{setGeometry(geometry().x() + 1, geometry().y(), geometry().width(), geometry().height());
}void FindDifferenceWidget::on_pushButton_down_clicked()
{setGeometry(geometry().x(), geometry().y() + 1, geometry().width(), geometry().height());
}void FindDifferenceWidget::on_pushButton_clear_clicked()
{_pDrawWidget->setListRect(QList<QRect>());
}
OpenCV代码:FindDifferenceManager
识别不同处代码类功能:
- 引入OpenCV头文件和库文件
- 提供接口输入2个同样大小的矩形、阈值和能识别的最小矩形。
- 核心算法:先灰度图->阈值化->寻找边界->识别最小矩形
(最开始算法进行了滤波,闭运算,因为实际有可能存在两幅图截屏就有色差导致灰度图色差小,实际有可能原图色差较小导致灰度色差较小,实际有可能不同的点较少导致滤波去掉了这些点,以上三种经过测试都是存在的)。
FindDifferenceManager.h
#ifndef FINDDIFFERENCEMANAGER_H
#define FINDDIFFERENCEMANAGER_H#include <QObject>
#include <QImage>// opencv
#include "opencv/highgui.h"
#include "opencv/cxcore.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/xphoto.hpp"
#include "opencv2/dnn/dnn.hpp"
// opencv_contrib
#include <opencv2/xphoto.hpp>
#include <opencv2/ximgproc.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>class FindDifferenceManager : public QObject
{Q_OBJECT
public:explicit FindDifferenceManager(QObject *parent = 0);private:bool getRunning() const;signals:void signal_findResult(bool result, QList<QRect> listRect = QList<QRect>());public slots:void slot_start();void slot_stop();public slots:void slot_findDiffrence(QImage image, QImage image2, int thresh = 20, QRect minRect = QRect(0, 0, 4, 4));protected:cv::Mat image2Mat(QImage image);private:bool _running;
};#endif // FINDDIFFERENCEMANAGER_H
FindDifferenceManager.cpp
#include "FindDifferenceManager.h"
#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")FindDifferenceManager::FindDifferenceManager(QObject *parent): QObject(parent),_running(false)
{qRegisterMetaType<QList<QRect>>("QList<QRect> ");
}bool FindDifferenceManager::getRunning() const
{return _running;
}void FindDifferenceManager::slot_start()
{if(_running){LOG << "Failed to" << __FUNCTION__ << ", it's already running.";return;}_running = true;
}void FindDifferenceManager::slot_stop()
{if(!_running){LOG << "Failed to" << __FUNCTION__ << ", it's not running.";return;}_running = false;
}void FindDifferenceManager::slot_findDiffrence(QImage image, QImage image2, int thresh, QRect minRect)
{QList<QRect> listRect;// 将QImage转换为cv::Matcv::Mat srcMat = image2Mat(image);cv::Mat srcMat2 = image2Mat(image2);if ((srcMat.rows != srcMat2.rows) || (srcMat.cols != srcMat2.cols)){emit signal_findResult(false);}cv::Mat srcMatGray;cv::Mat srcMat2Gray;// 转灰度图cv::cvtColor(srcMat, srcMatGray, cv::COLOR_BGR2GRAY);cv::cvtColor(srcMat2, srcMat2Gray, cv::COLOR_BGR2GRAY);// cv::imshow("1", srcMatGray);
// cv::imshow("2", srcMat2Gray);cv::Mat diffMatGray;// 图1减去图2:查看差异(灰度,可能差距不大,0-255, 0 1 2 3差距小看不出)cv::subtract(srcMatGray, srcMat2Gray, diffMatGray, cv::Mat(), CV_16SC1);// 绝对值(有负数,变正数)
// cv::imshow("3", diffMatGray);cv::Mat diffAbsMatGray = cv::abs(diffMatGray);// 改变位深(归一化试过,但是可能存在0和255,导致漏掉一些)diffAbsMatGray.convertTo(diffAbsMatGray, CV_8UC1, 1, 0);
// cv::imshow("4", diffAbsMatGray);#if 0// 整个像素降低5个点的误差(色差)for(int row = 0; row < diffAbsMatGray.rows; row++){for( int col = 0; col < diffAbsMatGray.cols; col++){if(diffAbsMatGray.at<uchar>(row, col) < 3){diffAbsMatGray.at<uchar>(row, col) = 0;}else{diffAbsMatGray.at<uchar>(row, col) = diffAbsMatGray.at<uchar>(row, col) - 5;}}}
#endifcv::Mat threshMat;//阈值处理cv::threshold(diffAbsMatGray, threshMat, thresh, 255, cv::THRESH_BINARY);
// cv::imshow("5", threshMat);cv::Mat mdianMat;
#if 0//中值滤波cv::medianBlur(threshMat, mdianMat, 3);cv::imshow("6", mdianMat);
#elsemdianMat = threshMat.clone();
#endifcv::Mat closeMat;
#if 0// 闭运算: 用拟合小裂缝,消除小型黑洞,并且在平滑较大物体的边界的同时不明显改变其面积。cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1));cv::morphologyEx(mdianMat, closeMat, cv::MORPH_CLOSE, kernel, cv::Point(-1, -1), 2, cv::BORDER_REPLICATE);
#elsecloseMat = mdianMat.clone();
#endif
// cv::imshow("7", closeMat);// 寻找边界std::vector<std::vector<cv::Point>> contours;std::vector<cv::Vec4i> hierarchy;cv::findContours(closeMat,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,cv::Point(0, 0));std::vector<std::vector<cv::Point>> contoursPoly(contours.size());for(int index = 0; index < contours.size(); index++){cv::approxPolyDP(cv::Mat(contours[index]), contoursPoly[index], 5, true);cv::Rect rect = cv::boundingRect(cv::Mat(contoursPoly[index]));#if 0// 小于最小矩形则忽略if(rect.width < minRect.width() || rect.height < minRect.height()){continue;}
#endiflistRect.append(QRect(rect.x, rect.y, rect.width, rect.height));
// cv::rectangle(srcMat, rect, cv::Scalar(0, 255, 0), 2);
// cv::rectangle(srcMat2, rect, cv::Scalar(0, 255, 0), 2);}
// cv::imshow("8", srcMat2);// cv::waitKey(0);emit signal_findResult(true, listRect);
}cv::Mat FindDifferenceManager::image2Mat(QImage image)
{cv::Mat mat;switch(image.format()){case QImage::Format_ARGB32:case QImage::Format_RGB32:case QImage::Format_ARGB32_Premultiplied:mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());cv::cvtColor(mat, mat, CV_BGRA2BGR);break;case QImage::Format_RGB888:mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());cv::cvtColor(mat, mat, CV_BGR2RGB);break;case QImage::Format_Indexed8:case QImage::Format_Grayscale8:mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());break;default:qDebug() << __FILE__ << __LINE__ << "error to image2Mat !!! imge.format =" << image.format();}return mat;
}
若该文为原创文章,转载请注明出处
本文章博客地址https://hpzwl.blog.csdn.net/article/details/124768637
项目实战:Qt+OpenCV大家来找茬(Qt抓图,穿透应用,识别左右图区别,框选区别,微调位置)相关推荐
- 找茬小程序源码、看图找不同小程序,前端+后端+教程,微信小程序游戏一起来找茬,全网首发一款可以完美运营的找茬小程序源码
演示小程序搜[最强脑洞I全民烧脑] 一共有2510关, 达到高级后会随机出现关卡: 一共7个能量, 每闯关一次扣除一个能量值, 看激励视频可以获得一个能量值: 金币获取: 段位升级 或者 观看激励视频 ...
- 【优秀课设】基于OpenCV的Python人脸识别、检测、框选(遍历目录下所有照片依次识别 视频随时标注)
基于OpenCV的Python人脸识别.检测.框选 (遍历目录下所有照片依次识别 视频随时标注) 移步: https://blog.csdn.net/weixin_53403301/article/d ...
- 【项目实战课】NLP入门第1课,人人免费可学,基于TextCNN的新闻文本分类实战...
欢迎大家来到我们的项目实战课,本期内容是<基于TextCNN的新闻文本分类实战>. 所谓项目课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的实战讲解,可以 ...
- 【CV冬季划】终极进阶,超30个项目实战+3本书+3年知识星球
大家好,今天正式发布2022年有三AI-CV冬季划,这是我们最高等级的CV季划小组,表示对参与者有更高的技术要求.在这个小组里,我们不再去系统性地学习基础知识,而是假设大家已经有了非常好的基础功底,我 ...
- 【项目实战课】微信小程序图像识别模型前后端部署实战
欢迎大家来到我们的项目实战课,本期内容是<微信小程序图像识别模型前后端部署实战>.所谓项目实战课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的实战讲解. ...
- 【项目实战课】基于Pytorch的SRGAN图像超分辨实战
欢迎大家来到我们的项目实战课,本期内容是<基于Pytorch的SRGAN图像超分辨实战>.所谓项目实战课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的实战 ...
- 【项目实战课】人人免费可学!基于Pytorch的图像分类简单任务数据增强实战
欢迎大家来到我们的项目实战课,本期内容是<基于Pytorch的图像分类简单任务数据增强实战>.所谓项目实战课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的 ...
- 【项目实战课】基于Pytorch的UGATIT人脸动漫风格化实战
欢迎大家来到我们的项目实战课,本期内容是<基于Pytorch的UGATIT人脸动漫风格化实战>.所谓项目课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的实 ...
- 【项目实战课】基于Pytorch的InceptionNet花卉图像分类实战
欢迎大家来到我们的项目实战课,本期内容是<基于Pytorch的InceptionNet花卉图像分类实战>.所谓项目课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行 ...
- 【项目实战课】基于Pytorch的Semantic_Human_Matting(人像软分割)实战
欢迎大家来到我们的项目实战课,本期内容是<基于Pytorch的Semantic_Human_Matting(人像软分割)实战>.所谓项目实战课,就是以简单的原理回顾+详细的项目实战的模式, ...
最新文章
- 软件质量与测试 第4周小组作业
- Linux预备知识(三):系统调用-用户态/内核态
- 对话美摄科技侯康:提升技术,拓展场景 美摄智能汽车视频处理方案已就位
- java hive demo_java 操作hive通过jdbc
- linux的基础知识——CS模型流程图
- phoshop cs6软件提示试用版已过期,怎么办
- 【开发工具】之MinGW下makefile的编写
- mysql 分区 key 写法_mysql数据库KEY分区用法
- 基于序列图像的三维体绘的视线投射算法
- 嵌入式C语言编码规范
- oracle得oem,Oracle--OEM与常见故障处理
- word域转换html,word域代码转换html丢失解决办法.docx
- donet 微服务开发 学习-熔断降级 Polly
- 如何使用Hyper-V Manager和Powershell合并Hyper-V检查点
- html + js实现马赛克画板
- Java实习生常规技术面试题每日十题Java基础(三)
- 【年度盘点】2016年互联网10大热点,谁在沸腾谁在死去?
- python控制画笔尺寸_Python turtle库的画笔控制说明
- iOS开发:兼容适配iPhone X
- [乐意黎原创]OFO小黄车提示你有未完成订单/未知错误的解决方法