一.问题描述
1.完成调用摄像头实现二维码扫码识别的功能原本的方案是Qt中使用QCamera调用摄像头,QZXing进行二维码识别,但是QCamera在一些电脑上无法打开摄像头,软件直接崩溃,这个问题找了很久,也使用qt官方的代码,QCamera打开某些摄像头仍然会使得软件直接崩溃,于是只有想办法用其他方案打开摄像头了.
方案一:ffmpeg打开摄像头.但是环境搭建和代码都比较复杂,放弃了.
方案二:opencv打开摄像头.qt上环境搭建比较麻烦,但是在VS2019+Qt上环境搭建就非常简单了.
2.QZXing在VS2019+Qt中不好使用,在qt中直接复制文件夹在.pro中加入.pri就行了,在VS中搞了好久没有一个合适的方案,问题太多,有好方案的小伙伴麻烦一起交流交流.于是我选择了zbar64进行二维码识别部分,环境搭建和使用方法也比较简单.注意系统是64位的选择zbar64,不然用不了.
二.环境搭建
Qt+VS2019环境搭建省略.
1.opencv3.4.1及zbar64下载
opencv3.4.1下载: https://opencv.org/releases/page/5/
下载不了可以使用我上传的:opencv3.4.1.zip
zbar下载:网上很多,但是不是64位的,zbar64我自己上传的:二维码编码解码库ZBar64.rar
2.环境变量配置:
右键“此电脑”——属性——高级系统设置——环境变量。
在系统变量中找到“Path”,编辑。
新建两个环境变量,找到opencv3.4.1和ZBar的bin目录
例如我的:
D:\opencv3.4.1\build\x64\vc14\bin
D:ZBar\bin
3.项目属性配置
在VS2019中新建项目,右键项目名—配置属性—VC++目录,在包含目录中加入opencv3.4.1和ZBar的include目录.
例如我的:
D:\ZBar\include
D:\opencv3.4.1\build\include\opencv2
D:\opencv3.4.1\build\include\opencv
D:\opencv3.4.1\build\include
在库目录中加入opencv3.4.1和ZBar的lib目录.
例如我的:
D:\ZBar\lib
D:\opencv3.4.1\build\x64\vc14\lib
链接器——输入,在附加依赖项中加入opencv3.4.1和ZBar的*.lib文件名:
opencv_world341d.lib
libzbar-0.lib
libzbar64-0.lib
三.调用摄像头设置
打开摄像头及格式转换核心代码:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
mainwindow::mainwindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
cv::VideoCapture cap;
if(!cap.open(0))//0-前置摄像头,1-后置
return;
cv::Mat frame;
while (1)
{
if (m_VideoCapture.read(frame))
{
//OpenCV使用BGR,QImage使用RGB,通道转换
cv::cvtColor(m_MatRead, m_MatRGB, CV_BGR2RGB);
//cv::Mat转QImage
QImage image = QImage(m_MatRGB.data, m_MatRGB.cols, m_MatRGB.rows, QImage::Format_RGB888);
ui.label_video->setPixmap(QPixmap::fromImage(image));
}
}
}
四.调用扫码识别
#include "zbar.h"
void mainwindow::sloQrDecode(cv::Mat image)
{
zbar::ImageScanner scanner;
//图片转换
cv::Mat imageGray;
cv::cvtColor(image, imageGray, CV_RGB2GRAY);
int width = imageGray.cols;
int height = imageGray.rows;
uchar* raw = (uchar*)imageGray.data;
zbar::Image imageZbar(width, height, "Y800", raw, width * height);
scanner.scan(imageZbar); //扫描条码
zbar::Image::SymbolIterator symbol = imageZbar.symbol_begin();
//扫描结果打印
if (imageZbar.symbol_begin() == imageZbar.symbol_end())
{
qDebug() << "查询条码失败,请检查图片!";
}
for (; symbol != imageZbar.symbol_end(); ++symbol)
{
qDebug() << "类型:" << QString::fromStdString(symbol->get_type_name());
qDebug() << "条码:" << QString::fromStdString(symbol->get_data());
}
}
简单的代码往往含有巨大的价值。
欢迎大家交流。
五.参考文献
还参考了一些文章已经忘了原链接了。
很有价值的一篇文章,感谢原博主,找了很久才看到这篇文章: