前言:
前面准备了这么多,现在终于可以加入解码相关的代码了
本次教程是在 Qt5.15.2+Qt6.2.1(widget)取出视频帧 取景器帧(示例合并)的示例源码上修改
一、准备第三方库
本次教程,使用opencv的二维码解码器,若还未准备相关的库,可以到opencv官方下载,或参考笔者的文档,自行编译。在此不再重复。
二、修改pro工程文件
笔者使用的是自己编译的opencv, 以下代码供读者参考
win32{
CONFIG(release, debug|release){
LIBS += -LOPENCV_DIR/install/x64/vc16/lib/ -lopencv_core454
LIBS += -LOPENCV_DIR/install/x64/vc16/lib/ -lopencv_imgproc454
LIBS += -LOPENCV_DIR/install/x64/vc16/lib/ -lopencv_objdetect454
}
else:CONFIG(debug, debug|release){
LIBS += -LOPENCV_DIR/install/x64/vc16/lib/ -lopencv_core454d
LIBS += -LOPENCV_DIR/install/x64/vc16/lib/ -lopencv_imgproc454d
LIBS += -LOPENCV_DIR/install/x64/vc16/lib/ -lopencv_objdetect454d
}
LIBS += -LOPENCV_DIR/install/x64/vc16/bin/
INCLUDEPATH += OPENCV_DIR/install/include
DEPENDPATH += OPENCV_DIR/install/include
}
#OPENCV_DIR为opencv的安装目录
三、添加处理类
新建一个处理类Tool_Process,继承自QObject,头文件修改如下
#include "opencv2/opencv.hpp"
#include <QObject>
#include <QImage>
class Tool_Process : public QObject
{
Q_OBJECT
public:
explicit Tool_Process(QObject *parent = nullptr);
//添加待处理的图像
void setImage(const QImage &image);
signals:
//返回已解读的二维码数据
void qrString(const QString string);
private:
//将QImgae对象转换为cv::Mat
cv::Mat QImage2cvMat(QImage image);
QImage m_image;
};
源文件的关键代码如下
void Tool_Process::setImage(const QImage &image)
{
// qDebug()<<"Tool_Qr::setImage"<<image;
m_image = image;
cv::QRCodeDetector decoder;
cv::Mat mat,bbox,rect;
mat=QImage2cvMat(image);
if(decoder.detect(mat,bbox)){
qDebug()<<"getQRCode";
std::string result = decoder.decode(mat,bbox);
const QString resultString = QString::fromStdString(result);
qDebug() << "QRdecoder"<<resultString;
if(!resultString.isEmpty())
emit qrString(resultString);
}
}
cv::Mat Tool_Process::QImage2cvMat(QImage image)
{
cv::Mat mat;
// qDebug() << image.format();
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());
break;
case QImage::Format_RGB888:
mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);
break;
case QImage::Format_Indexed8:
mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
break;
}
return mat;
}
四、调用处理类进行二维码识别
在Qt5中,将newVideoFrame信号放出的图像直接送入到Tool_Process中
//初始化取摄像头帧的类
// m_camera->setViewfinder(ui->videoWidget);
m_videoSurface = new VideoSurface;
m_camera->setViewfinder(m_videoSurface);
// ui->videoWidget->videoSurface()
connect(m_videoSurface, &VideoSurface::newVideoFrame,
[this](const QImage videoFrame){
ui->label->setPixmap(QPixmap::fromImage(videoFrame.scaled(ui->label->size(),Qt::KeepAspectRatio)));
m_tool_Process->setImage(videoFrame);
});
在Qt6中,将videoFrameChanged信号放出的图像直接送入到Tool_Process中
//初始化取摄像头帧的类
// m_videoSink = new QVideoSink;
m_videoSink = ui->videoWidget->videoSink();
connect(m_videoSink, &QVideoSink::videoFrameChanged,
[this](const QVideoFrame &frame){
const QImage image = frame.toImage();
ui->label->setPixmap(QPixmap::fromImage(image.scaled(ui->label->size(),Qt::KeepAspectRatio)));
m_tool_Process->setImage(image);
});
完成以上操作,就可以运行程序了,笔者运行结果如下
可能遇到的问题
1.应用程序编译通过,但一运行就异常退出
原因:很大概率是引入了opencv库后,运行时未将dll库放在程序可以找到的地方
解决方法:将opencv的库放入系统环境变量中,或复制到可执行程序当前目录中,或直接在pro中加入opencv的动态库
本次教程的源代码
后记:
据说,opencv的识别相对低一些,笔者还没有对比测试
笔者当前的程序已在win10下测试通过,其他操作系统,会在后面的教程中添加一部分
经过测试的小伙伴已经注意到了,解码过程需要较长的时间,导致程序比较卡,这个问题在下个教程中解决