QT Opencv和Xzing读取二维码信息

一、准备

本人的环境为 VS2015 &  opencv4.1.1 & xzing二维码解码库

另opencv的库解压开需要放到环境变量中声明:比如 D:\Opencv_X64\x64\vc14\bin

 

二、新建工程

首先在qt的pro文件中添加入头文件及库信息,如下所示

#opencv
INCLUDEPATH += D:/Opencv_X64/include
LIBS += -LD:/Opencv_X64/x64/vc14/lib  -lopencv_highgui411 \                                  
                                      -lopencv_video411  \   
                                  -lopencv_videoio411  \
                                  -lopencv_core411   \
                                  -lopencv_imgproc411 \
                                  -lopencv_imgcodecs411
#zxing
unix|win32: LIBS += -L$$PWD/zxing_lib/ -llibzxing
INCLUDEPATH += $$PWD/zxing
DEPENDPATH += $$PWD/zxing

三、程序编写

1、获取摄像头数量,采取最简单的方法,轮流打开摄像头,获取到摄像头的数量,

代码如下所示:

//获取相机及摄像头信息
void Thread_OpenCV::GetCamaraInfo()
{
    cv::VideoCapture temp_camera;
    int maxTested = 10;
    for (int i = 0; i < maxTested; i++)
    {
        cv::VideoCapture temp_camera(i);
        bool res = (!temp_camera.isOpened());
        temp_camera.release();
        //cv::destroyAllWindows();
        if (res)
        {
            CameraInfo.CamaraCnt = i;
            emit this->Sig_Camera_Update(CameraInfo);     //摄像头数量更新    用于外部调用  统计显示数量
            break;
        }
    }
}

2、获取摄像头数据

result = cap.read(src_image);    //读mat

3、将mat数据转成QImage,供图片显示

//Mat转成QImage
QImage  Thread_OpenCV::MatImageToQt(const cv::Mat &src)
{
    //CV_8UC1 8位无符号的单通道---灰度图片
    if(src.type() == CV_8UC1)
    {
        //使用给定的大小和格式构造图像
        //QImage(int width, int height, Format format)
        QImage qImage(src.cols,src.rows,QImage::Format_Indexed8);
        //扩展颜色表的颜色数目
        qImage.setColorCount(256);

        //在给定的索引设置颜色
        for(int i = 0; i < 256; i ++)
        {
            //得到一个黑白图
            qImage.setColor(i,qRgb(i,i,i));
        }
        //复制输入图像,data数据段的首地址
        uchar *pSrc = src.data;
        //
        for(int row = 0; row < src.rows; row ++)
        {
            //遍历像素指针
            uchar *pDest = qImage.scanLine(row);
            //从源src所指的内存地址的起始位置开始拷贝n个
            //字节到目标dest所指的内存地址的起始位置中
            memcmp(pDest,pSrc,src.cols);
            //图像层像素地址
            pSrc += src.step;
        }
        return qImage;
    }
    //为3通道的彩色图片
    else if(src.type() == CV_8UC3)
    {
        //得到图像的的首地址
        const uchar *pSrc = (const uchar*)src.data;
        //以src构造图片
        QImage qImage(pSrc,src.cols,src.rows,src.step,QImage::Format_RGB888);
        //在不改变实际图像数据的条件下,交换红蓝通道
        return qImage.rgbSwapped();
    }
    //四通道图片,带Alpha通道的RGB彩色图像
    else if(src.type() == CV_8UC4)
    {
        const uchar *pSrc = (const uchar*)src.data;
        QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32);
        //返回图像的子区域作为一个新图像
        return qImage.copy();
    }
    else
    {
        return QImage();
    }
}

4、将获取到的QImage转成灰度图像,用于zxing提取二维码

//灰度转换
 cv::cvtColor(src, matGray, CV_BGR2GRAY);

5、zxing解码,并获取到二维码信息 

 try
    {
        //初始化
        zxing::Ref<zxing::LuminanceSource> source = MatSource::create(matGray);
        //    /*int width = source->getWidth();
        //    int height = source->getHeight();*/
        //    /*fprintf(stderr, "image width: %d, height: %d\n", width, height);*/
        zxing::Ref<zxing::Reader> reader;
        reader.reset(new zxing::MultiFormatReader);
        zxing::Ref<zxing::Binarizer> binarizer(new zxing::GlobalHistogramBinarizer(source));
        zxing::Ref<zxing::BinaryBitmap> bitmap(new zxing::BinaryBitmap(binarizer));
        //开始解码
        zxing::Ref<zxing::Result> result(reader->decode(bitmap, zxing::DecodeHints(zxing::DecodeHints::TRYHARDER_HINT)));
        //获取解析结果
        Temp_String = QString::fromStdString(result->getText()->getText());

        //qDebug() << Temp_String;

        emit this->Sig_Camera_Qrcode_Update(State,Temp_String);          //信息发至主界面
    }
    catch (zxing::ReaderException& e)
    {
        qDebug() << e.what() << " (ReaderException)" << endl;
    }
    catch (zxing::IllegalArgumentException& e)
    {
        qDebug() << e.what() << " (IllegalArgumentException)" << endl;
    }
    catch (zxing::Exception& e)
    {
        qDebug() << e.what() << " (Exception)" << endl;
    }

6、获取到摄像头数据并解析,可以定时获取,一般为30ms左右,可以保证图片不会有卡顿的现象。

//显示像素信息
void Thread_OpenCV::ReadCamara()
{
    bool result;
    cv::Mat  matGray;                //灰度值

    result = cap.read(src_image);    //读mat

    if(result)
    {
        //发送数据到主线程 用于显示
        QImage temp_image = MatImageToQt(src_image);  //mat转换
        emit this->Sig_Camera_Show_Image(temp_image);

        //解析二维码
        ZxingAnalysis(src_image);
    }

 //   ZxingPictureQrcode("D:/Downloads/1569737649.png");
}

四、其它

附完整代码如下:

​
#include "thread_opencv.h"
#include <QImage>
#include <QPixmap>
#include <QDebug>

#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/video.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/videoio/videoio_c.h>

#include <zxing/qrcode/QRCodeReader.h>
#include "zxing/LuminanceSource.h"
#include "zxing/Reader.h"
#include "zxing/common/GlobalHistogramBinarizer.h"
#include "zxing/DecodeHints.h"
#include "zxing/datamatrix/DataMatrixReader.h"
#include "zxing/BinaryBitmap.h"
#include "zxing/Binarizer.h"
#include "zxing/Exception.h"
#include "zxing/MatSource.h"
#include <zxing/MultiFormatReader.h>
#include "zxing/Exception.h"
#include "zxing/ReaderException.h"


_VAR_CAMERA  CameraInfo;

//宏定义
#if CV_MAJOR_VERSION >= 4
    #ifndef CV_CAP_PROP_FRAME_WIDTH
        #define CV_CAP_PROP_FRAME_WIDTH cv::CAP_PROP_FRAME_WIDTH
    #endif

    #ifndef CV_CAP_PROP_FRAME_HEIGHT
        #define CV_CAP_PROP_FRAME_HEIGHT cv::CAP_PROP_FRAME_HEIGHT
    #endif

    #ifndef CV_BGR2GRAY
        #define CV_BGR2GRAY cv::COLOR_BGR2GRAY
    #endif
#endif


Thread_OpenCV::Thread_OpenCV()
{
    image = new QImage();
}


//运行
void Thread_OpenCV::run()
{
    static bool first_cam = false;

    for(;;)
    {
        if(!first_cam)
        {
            GetCamaraInfo();
            first_cam = true;
        }
        //开关摄像头
        if(CameraInfo.OpenCloseFlag)
        {
            CameraInfo.OpenCloseFlag = false;

            //开关标记
            if(CameraInfo.CameraOC)
            {
                GetCamaraInfo();

                if(CameraInfo.CurrentID < CameraInfo.CamaraCnt)
                {
                    cap.open(CameraInfo.CurrentID);

                    //检查摄像头是否打开
                    if (!cap.isOpened())
                    {
                        qDebug() << "CV cant open";
                    }

                    CameraInfo.isComOpen = true;
                }
            }
            else
            {
                cap.release();
                //cv::destroyAllWindows();
                CameraInfo.isComOpen = false;
            }
        }
        //读摄像头帧数据
        if(CameraInfo.isComOpen)
        {
            ReadCamara();           //获取到摄像头信息
        }
        msleep(33);             //延时
    }
}


//显示像素信息
void Thread_OpenCV::ReadCamara()
{
    bool result;
    cv::Mat  matGray;                //灰度值

    result = cap.read(src_image);    //读mat

    if(result)
    {
        //发送数据到主线程 用于显示
        QImage temp_image = MatImageToQt(src_image);  //mat转换
        emit this->Sig_Camera_Show_Image(temp_image);

        //解析二维码
        ZxingAnalysis(src_image);
    }

 //   ZxingPictureQrcode("D:/Downloads/1569737649.png");
}


//Mat转成QImage
QImage  Thread_OpenCV::MatImageToQt(const cv::Mat &src)
{
    //CV_8UC1 8位无符号的单通道---灰度图片
    if(src.type() == CV_8UC1)
    {
        //使用给定的大小和格式构造图像
        //QImage(int width, int height, Format format)
        QImage qImage(src.cols,src.rows,QImage::Format_Indexed8);
        //扩展颜色表的颜色数目
        qImage.setColorCount(256);

        //在给定的索引设置颜色
        for(int i = 0; i < 256; i ++)
        {
            //得到一个黑白图
            qImage.setColor(i,qRgb(i,i,i));
        }
        //复制输入图像,data数据段的首地址
        uchar *pSrc = src.data;
        //
        for(int row = 0; row < src.rows; row ++)
        {
            //遍历像素指针
            uchar *pDest = qImage.scanLine(row);
            //从源src所指的内存地址的起始位置开始拷贝n个
            //字节到目标dest所指的内存地址的起始位置中
            memcmp(pDest,pSrc,src.cols);
            //图像层像素地址
            pSrc += src.step;
        }
        return qImage;
    }
    //为3通道的彩色图片
    else if(src.type() == CV_8UC3)
    {
        //得到图像的的首地址
        const uchar *pSrc = (const uchar*)src.data;
        //以src构造图片
        QImage qImage(pSrc,src.cols,src.rows,src.step,QImage::Format_RGB888);
        //在不改变实际图像数据的条件下,交换红蓝通道
        return qImage.rgbSwapped();
    }
    //四通道图片,带Alpha通道的RGB彩色图像
    else if(src.type() == CV_8UC4)
    {
        const uchar *pSrc = (const uchar*)src.data;
        QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32);
        //返回图像的子区域作为一个新图像
        return qImage.copy();
    }
    else
    {
        return QImage();
    }
}

//开关
void Thread_OpenCV::Open_Close_Camera(bool state, uint8_t id)
{
    if(state)
    {

        CameraInfo.OpenCloseFlag = true;
        CameraInfo.CameraOC = true;
        CameraInfo.CurrentID = id;
    }
    else
    {
        CameraInfo.OpenCloseFlag = true;
        CameraInfo.CameraOC = false;
        CameraInfo.CurrentID = id;
    }
}

//解码
void Thread_OpenCV::ZxingAnalysis(cv::Mat src)
{
    bool    State = true;
    QString Temp_String;
    cv::Mat matGray;

    //灰度转换
    cv::cvtColor(src, matGray, CV_BGR2GRAY);

    try
    {
        //初始化
        zxing::Ref<zxing::LuminanceSource> source = MatSource::create(matGray);
        //    /*int width = source->getWidth();
        //    int height = source->getHeight();*/
        //    /*fprintf(stderr, "image width: %d, height: %d\n", width, height);*/
        zxing::Ref<zxing::Reader> reader;
        reader.reset(new zxing::MultiFormatReader);
        zxing::Ref<zxing::Binarizer> binarizer(new zxing::GlobalHistogramBinarizer(source));
        zxing::Ref<zxing::BinaryBitmap> bitmap(new zxing::BinaryBitmap(binarizer));
        //开始解码
        zxing::Ref<zxing::Result> result(reader->decode(bitmap, zxing::DecodeHints(zxing::DecodeHints::TRYHARDER_HINT)));
        //获取解析结果
        Temp_String = QString::fromStdString(result->getText()->getText());

        //qDebug() << Temp_String;

        emit this->Sig_Camera_Qrcode_Update(State,Temp_String);          //信息发至主界面
    }
    catch (zxing::ReaderException& e)
    {
        qDebug() << e.what() << " (ReaderException)" << endl;
    }
    catch (zxing::IllegalArgumentException& e)
    {
        qDebug() << e.what() << " (IllegalArgumentException)" << endl;
    }
    catch (zxing::Exception& e)
    {
        qDebug() << e.what() << " (Exception)" << endl;
    }
}


//图片解码
void Thread_OpenCV::ZxingPictureQrcode(QString FileName)
{
    cv::Mat  FileInfo;

    FileInfo = cv::imread(FileName.toStdString(),1);

    //读取失败则返回
    if (!FileInfo.data)
    {
        qDebug() << "error!!!";
    }

    ZxingAnalysis(FileInfo);            //解析
}

//获取相机及摄像头信息
void Thread_OpenCV::GetCamaraInfo()
{
    cv::VideoCapture temp_camera;
    int maxTested = 10;
    for (int i = 0; i < maxTested; i++)
    {
        cv::VideoCapture temp_camera(i);
        bool res = (!temp_camera.isOpened());
        temp_camera.release();
        //cv::destroyAllWindows();
        if (res)
        {
            CameraInfo.CamaraCnt = i;
            emit this->Sig_Camera_Update(CameraInfo);     //摄像头数量更新    用于外部调用  统计显示数量
            break;
        }
    }
}

​

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值