项目实战:Qt+OpenCV大家来找茬(Qt抓图,穿透应用,识别左右图区别,框选区别,微调位置)

简介: 项目实战:Qt+OpenCV大家来找茬(Qt抓图,穿透应用,识别左右图区别,框选区别,微调位置)

前言

  本项目的出现理由只是笔者的一个念头,于是利用专业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->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 1
    QRegion r1(_rectApplication);
    QRegion r2(_rectGame);
    QRegion r3 = r1 - r2;
    setMask(r3);
#endif
    QWidget::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::Mat
    cv::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;
            }
        }
    }
#endif
    cv::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);
#else
    mdianMat = threshMat.clone();
#endif
    cv::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);
#else
    closeMat = 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;
        }
#endif
        listRect.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;
}



相关文章
|
2月前
|
算法 计算机视觉
基于qt的opencv实时图像处理框架FastCvLearn实战
本文介绍了一个基于Qt的OpenCV实时图像处理框架FastCvLearn,通过手撕代码的方式详细讲解了如何实现实时人脸马赛克等功能,并提供了结果展示和基础知识回顾。
105 7
基于qt的opencv实时图像处理框架FastCvLearn实战
|
2月前
|
文字识别 计算机视觉 开发者
基于QT的OCR和opencv融合框架FastOCRLearn实战
本文介绍了在Qt环境下结合OpenCV库构建OCR识别系统的实战方法,通过FastOCRLearn项目,读者可以学习Tesseract OCR的编译配置和在Windows平台下的实践步骤,文章提供了技术资源链接,帮助开发者理解并实现OCR技术。
131 9
基于QT的OCR和opencv融合框架FastOCRLearn实战
|
4月前
|
计算机视觉 Python
opencv识别颜色
opencv识别颜色
|
1月前
|
机器学习/深度学习 API 计算机视觉
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(下)
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(下)
25 2
|
1月前
|
机器学习/深度学习 存储 算法
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(上)
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(上)
30 1
|
2月前
|
计算机视觉
基于QT的opencv插件框架qtCvFrameLearn实战
这篇文章详细介绍了如何基于Qt框架开发一个名为qtCvFrameLearn的OpenCV插件,包括项目配置、插件加载、Qt与OpenCV图像转换,以及通过各个插件学习OpenCV函数的使用,如仿射变换、卡通效果、腐蚀、旋转和锐化等。
45 10
|
2月前
|
机器学习/深度学习 Java 计算机视觉
opencv4.5.5+qt5.15.2+vtk9.1+mingw81_64编译记录
本文记录了使用mingw81_64编译OpenCV 4.5.5、Qt 5.15.2、VTK 9.1的详细过程,包括编译结果截图、编译步骤、遇到的问题及其解决方案,以及相关参考链接。文中还提到了如何编译boost源码为静态库,并提供了测试代码示例。
opencv4.5.5+qt5.15.2+vtk9.1+mingw81_64编译记录
|
2月前
|
设计模式 前端开发 安全
Qt注册类对象单例与单类型区别
在进行开发时,应当根据具体的应用场景和需求来选择使用单例模式或是单类型。如果是全局服务或状态管理,可能需要单例模式;如果是为了使QML环境下的不同组件能够访问到同一个后端服务对象,则可能需要使用单类型。
36 2
|
3月前
|
计算机视觉
使用QT显示OpenCV读取的图片
使用QT显示OpenCV读取的图片
72 1
|
4月前
|
机器学习/深度学习 数据采集 算法
Python基于OpenCV和卷积神经网络CNN进行车牌号码识别项目实战
Python基于OpenCV和卷积神经网络CNN进行车牌号码识别项目实战
298 19