?前言: 在前面的教程中,使用openCV的库实现了扫码功能,但实际使用时却很不理想。本次教程使用微信的扫码代码来测试
本教程是在?Qt5.15.2+Qt6.2.1(qml)+opencv4.5.4实现扫码功能(多线程) 示例的基础上修改
QR扫码综合示例教程(二十)Qt5.15.2+Qt6.2.1(qml)+opencv4.5.4实现扫码功能(多线程)_aggs1990的专栏-CSDN博客
一、准备openCV库
微信的扫码在附加库里,所以必需要自己编译官方源码,请需要的小伙伴们自己参考以下链接
Qt+openCV学习笔记_aggs1990的专栏-CSDN博客
笔者使用的是自己编译库?
一、修改pro工程文件
修改工程文件是为了添加openCV的库
若是使用的VS2019 64位编译器,添加如下代码
win32{
CONFIG(release, debug|release){
LIBS += -LOPENCV_DIR/opencv4.5.4/build_vs2019_64/install/x64/vc16/lib/ -lopencv_core454
LIBS += -LOPENCV_DIR/opencv4.5.4/build_vs2019_64/install/x64/vc16/lib/ -lopencv_imgproc454
LIBS += -LOPENCV_DIR/opencv4.5.4/build_vs2019_64/install/x64/vc16/lib/ -lopencv_wechat_qrcode454
}
else:CONFIG(debug, debug|release){
LIBS += -LOPENCV_DIR/opencv4.5.4/build_vs2019_64/install/x64/vc16/lib/ -lopencv_core454d
LIBS += -LOPENCV_DIR/opencv4.5.4/build_vs2019_64/install/x64/vc16/lib/ -lopencv_imgproc454d
LIBS += -LOPENCV_DIR/opencv4.5.4/build_vs2019_64/install/x64/vc16/lib/ -lopencv_wechat_qrcode454d
}
LIBS += -LOPENCV_DIR/opencv4.5.4/build_vs2019_64/install/x64/vc16/bin/
INCLUDEPATH += OPENCV_DIR/opencv4.5.4/build_vs2019_64/install/include
DEPENDPATH += OPENCV_DIR/opencv4.5.4/build_vs2019_64/install/include
}
#OPENCV_DIR为openCV库存放目录
只要加载自己需要的模块就可以了,以减小发布包的体积
若是使用的android arm64-v8a编译器,添加如下代码
unix:!macx{
contains(ANDROID_TARGET_ARCH,arm64-v8a) {
message("arm64-v8a")
ANDROID_OPENCV = opencv_dir/opencv4.5.4/build_android_arm64-v8a/install/sdk/native
INCLUDEPATH += $$ANDROID_OPENCV/jni/include/opencv2 \
$$ANDROID_OPENCV/jni/include
LIBS += \
$$ANDROID_OPENCV/libs/arm64-v8a/libopencv_wechat_qrcode.so \
$$ANDROID_OPENCV/libs/arm64-v8a/libopencv_dnn.so \
$$ANDROID_OPENCV/libs/arm64-v8a/libopencv_imgproc.so \
$$ANDROID_OPENCV/libs/arm64-v8a/libopencv_calib3d.so \
$$ANDROID_OPENCV/libs/arm64-v8a/libopencv_flann.so \
$$ANDROID_OPENCV/libs/arm64-v8a/libopencv_features2d.so \
$$ANDROID_OPENCV/libs/arm64-v8a/libopencv_core.so
ANDROID_EXTRA_LIBS = \
opencv_dir/opencv4.5.4/build_android_arm64-v8a/install/sdk/native/libs/arm64-v8a/libopencv_core.so \
opencv_dir/opencv4.5.4/build_android_arm64-v8a/install/sdk/native/libs/arm64-v8a/libopencv_features2d.so \
opencv_dir/opencv4.5.4/build_android_arm64-v8a/install/sdk/native/libs/arm64-v8a/libopencv_flann.so \
opencv_dir/opencv4.5.4/build_android_arm64-v8a/install/sdk/native/libs/arm64-v8a/libopencv_calib3d.so \
opencv_dir/opencv4.5.4/build_android_arm64-v8a/install/sdk/native/libs/arm64-v8a/libopencv_imgproc.so \
opencv_dir/opencv4.5.4/build_android_arm64-v8a/install/sdk/native/libs/arm64-v8a/libopencv_dnn.so \
opencv_dir/opencv4.5.4/build_android_arm64-v8a/install/sdk/native/libs/arm64-v8a/libopencv_wechat_qrcode.so
}
若是使用的android armeabi-v7a编译器,添加如下代码
unix:!macx{
#添加opencv库(android armeabi-v7a版)
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
message("armeabi-v7a")
ANDROID_OPENCV = opencv_dir/opencv4.5.4/build_android_armeabi-v7a/install/sdk/native
INCLUDEPATH += $$ANDROID_OPENCV/jni/include/opencv2 \
$$ANDROID_OPENCV/jni/include
LIBS += \
$$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_wechat_qrcode.so \
$$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_dnn.so \
$$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_imgproc.so \
$$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_calib3d.so \
$$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_flann.so \
$$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_features2d.so \
$$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_core.so
ANDROID_EXTRA_LIBS = \
opencv_dir/opencv4.5.4/build_android_armeabi-v7a/install/sdk/native/libs/armeabi-v7a/libopencv_core.so \
opencv_dir/opencv4.5.4/build_android_armeabi-v7a/install/sdk/native/libs/armeabi-v7a/libopencv_features2d.so \
opencv_dir/opencv4.5.4/build_android_armeabi-v7a/install/sdk/native/libs/armeabi-v7a/libopencv_flann.so \
opencv_dir/opencv4.5.4/build_android_armeabi-v7a/install/sdk/native/libs/armeabi-v7a/libopencv_calib3d.so \
opencv_dir/opencv4.5.4/build_android_armeabi-v7a/install/sdk/native/libs/armeabi-v7a/libopencv_imgproc.so \
opencv_dir/opencv4.5.4/build_android_armeabi-v7a/install/sdk/native/libs/armeabi-v7a/libopencv_dnn.so \
opencv_dir/opencv4.5.4/build_android_armeabi-v7a/install/sdk/native/libs/armeabi-v7a/libopencv_wechat_qrcode.so
}
}
二、修改处理类
类Tool_Process头文件修改如下
class Tool_Process : public QObject
{
Q_OBJECT
public:
explicit Tool_Process(QObject *parent = nullptr);
~Tool_Process();
//添加待处理的图像
void setImage(const QImage &image, bool isModeMultiQR);
signals:
//返回已解读的二维码数据
void decoded(const QStringList resultStringList, const QImage image);
//启动定时器
void start();
protected:
//处理定时器事件
void timerEvent(QTimerEvent *event) override;
private:
//复制微信模型文件内容
void copyModelFileByteArray();
//二维码解码
void process();
//将QImage对象转换为cv::Mat
cv::Mat QImage2cvMat(QImage image);
//将cv::Mat对象转换为QImage
const QImage MatToQImage(cv::Mat mtx);
//二维码解码并绘制
double processQRCodeDetection(cv::wechat_qrcode::WeChatQRCode *weChatQR, const cv::Mat& input, cv::Mat& result,
std::vector<cv::Mat>& corners, bool isModeMultiQR, QStringList &resultStringList);
//二维码解码
void runQR(cv::wechat_qrcode::WeChatQRCode *weChatQR, const cv::Mat& input,
std::vector<cv::Mat>& corners, std::vector<cv::String>& decode_info,
bool isModeMultiQR);
//二维码边框、用时绘制
void drawQRCodeResults(cv::Mat& frame, const std::vector<cv::Mat>& corners, const std::vector<cv::String>& decode_info, double fps);
//二维码边框绘制
void drawQRCodeContour(cv::Mat &color_image, std::vector<cv::Point>& corners);
//用时绘制
void drawFPS(cv::Mat &color_image, double fps);
//启动定时器
void onStart();
//保存的图像
QImage m_image;
//是否多个二维码
bool m_isModeMultiQR;
//定时器Id
int m_timerId = -1;
//互斥量
QMutex m_mutex;
//微信解码器
cv::wechat_qrcode::WeChatQRCode *m_weChatQR = nullptr;
//微信模型文件
QTemporaryFile *m_file_detector_prototxt = nullptr;
QTemporaryFile *m_file_detector_caffe_model = nullptr;
QTemporaryFile *m_file_super_resolution_prototxt = nullptr;
QTemporaryFile *m_file_super_resolution_caffe_model = nullptr;
};
源文件修改的关键代码
Tool_Process::Tool_Process(QObject *parent) : QObject(parent)
{
//复制微信模型文件内容
copyModelFileByteArray();
//初始化微信解码器
const std::string detector_prototxt_path = m_file_detector_prototxt->fileName().toStdString();
const std::string detector_caffe_model_path = m_file_detector_caffe_model->fileName().toStdString();
const std::string super_resolution_prototxt_path = m_file_super_resolution_prototxt->fileName().toStdString();
const std::string super_resolution_caffe_model_path = m_file_super_resolution_caffe_model->fileName().toStdString();
m_weChatQR=new cv::wechat_qrcode::WeChatQRCode(detector_prototxt_path,detector_caffe_model_path,
super_resolution_prototxt_path,super_resolution_caffe_model_path);
connect(this, &Tool_Process::start, this, &Tool_Process::onStart);
}
/*!
* \brief Tool_Process::copyModelFileByteArray 复制微信模型文件内容
*/
void Tool_Process::copyModelFileByteArray()
{
{
QFile f(":/wechat_qrcode/detect.prototxt");
m_file_detector_prototxt = QTemporaryFile::createNativeFile(f);
}
{
QFile f(":/wechat_qrcode/detect.caffemodel");
m_file_detector_caffe_model = QTemporaryFile::createNativeFile(f);
}
{
QFile f(":/wechat_qrcode/sr.prototxt");
m_file_super_resolution_prototxt = QTemporaryFile::createNativeFile(f);
}
{
QFile f(":/wechat_qrcode/sr.caffemodel");
m_file_super_resolution_caffe_model = QTemporaryFile::createNativeFile(f);
}
}
/*!
* \brief Tool_Process::runQR 二维码解码
* \param qrcode 解码器
* \param input 输入图像
* \param corners 二维码定位点
* \param decode_info 二维码解码信息
* \param isModeMultiQR 是否多个二维码
*/
void Tool_Process::runQR(cv::wechat_qrcode::WeChatQRCode *weChatQR, const cv::Mat &input, std::vector<cv::Mat> &corners,
std::vector<cv::String> &decode_info, bool isModeMultiQR)
{
decode_info = m_weChatQR->detectAndDecode(input, corners);
}
说明:
1.在程序运行时,主线程调用setImage()函数,不停注入新的图像,但处理类只保留最后一张图像
2.process()运行在新开的线程中,被定时触发,若有图像未处理,就处理掉
有关解码处理函数的具体实现方法,修改自openCV官方示例,在此就不再解释
3.微信解码器初始化时,需要载入4个模型相关的文件,笔者为方便大家学习,已经直接放入Qt资源文件中,在处理类初始化时,会复制到临时文件中。
4.关于微信扫码的结果,返回的点放入std::vector<cv::Mat>中。
每个二维码的四个点对应一个cv::Mat
每个cv::Mat是一个4行2列的float矩阵,每行存放x、y坐标,均点4个字节
修改完成以上代码,就可以运行程序了,以下是笔者的运行结果
1.Qt6.2.1在win10下的运行结果
?2.Qt5.15.2在win10下的运行结果
?3.Qt6.2.1在android下的运行结果
?4.Qt5.15.2在android下的运行结果
?划线的效果不是很明显,小伙伴们可以自己加粗或修改下颜色
本次教程源码下载
后记:
经过笔者测试,使用微信开源的二维码扫码代码,无论是扫码速度、准确率、解码时消耗内存,都优于openCV自带的二维码扫码器。
要说美中不足的是,需要自己编译openCV库,且不支持条码扫描比较可惜
下篇可能会写下使用其他开源库解码
感谢项目经理临时给了台平板测试,虽然测试完成后要回收
|