使用zbar库识别条形码与二维码

1、图形编码类别

1.1 条形码

条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符。常见的条形码是由反射率相差很大的黑条(简称条)和白条(简称空)排成的平行线图案。

常见的条码有:Code39码(标准39码)、Codabar码(库德巴码)、Code25码(标准25码)、ITF25码(交叉25码)、Matrix25码(矩阵25码)、UPC-A码、UPC-E码、EAN-13码(EAN-13国际商品条码)、EAN-8码(EAN-8国际商品条码)、中国邮政码(矩阵25码的一种变体)、Code-B码、MSI码、Code11码、Code93码、ISBN码、ISSN码、Code128码(Code128码,包括EAN128码)、Code39EMS(EMS专用的39码)等一维条码和PDF417等二维条码。更多条形码知识可以参考:https://zhuanlan.zhihu.com/p/582084617 常见的商品条形码为code128

条形码可以标出物品的生产国、制造厂家、商品名称、生产日期、图书分类号、邮件起止地点、类别、日期等许多信息 。还具有信息采集速度快、可靠性高、采集信息量大、灵活、实用、自由度大、易于制作等优点。因而在商品流通、图书管理、邮政管理、银行系统等许多领域都得到广泛的应用 。

常见的条形码如下图所示:

在这里插入图片描述

1.2 二维码

二维码又称二维条码,常见的二维码为QR Code,QR全称Quick Response,是一种编码方式。它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。

二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的、黑白相间的、记录数据符号信息的图形;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。

二维码具有信息量大、易识别、成本低等特点,因而 在扫码支付、商业活动、网络链接、电商平台等许多领域都得到广泛的应用。
常见的二维码如下图所示:
在这里插入图片描述
二维码结构说明如下图所示:

在这里插入图片描述

2、二维码识别库简介

2.1 Quirc

QR 码是一种高密度矩阵条码,Quirc是一个基于C/C++的一个二维码库 ,从图像中提取和解码QR 码。其部分功能还需依赖OpenCV库共同实现,比如quirc-demo-opencv(即图形的显示);inspect-opencv(测试)。
特点:

  • 1.足够快,可以用于实时视频:在现代x86内核上,从VGA帧提取和解码大约需要50毫秒。
  • 2.具有鲁棒且宽容的识别算法。 可以正确识别和解码旋转和/或倾斜于相机的QR码。 它还可以区分和解码同一图像中的多个代码。
  • 3.易于使用,并且在单个带注释的头文件中描述了一个简单的API 。
  • 4.它很小,易于嵌入,除了标准C函数外没有任何依赖关系。
  • 5.它的内存占用非常小:每个图像像素一个字节,再加上每个解码器对象几kB。
  • 6.不使用全局可变状态,并且可以在多线程应用程序中安全使用。
  • 7.BSD许可,几乎没有关于使用和/或修改的限制。 除了库之外,该发行版还附带了一些测试程序。

简单的来概括Quirc的特点就是:简单,方便移植,识别准确率高。具体使用方法可参考其官网:https://github.com/dlbeer/quirc

2.2 OpenCV

Opencv在对象检测模块中 QRCodeDetector 有两个相关API分别实现二维码检测与二维码解析。
1.检测API points = QRCodeDetector.detect(img)
其中:
img为输入图像,灰度或者彩色图像;
points输出得到的二维码四个点的坐标信息

2.识别API straight_qrcode = QRCodeDetector.decode(img, points)
其中:
img为输入图像,灰度或者彩色图像;
points是二维码ROI最小外接矩形顶点坐标;
straight_qrcode输出的是二维码区域ROI图像信息 返回的二维码utf-8字符串;

3.结合检测识别的API
points,straight_qrcode = QRCodeDetector.detectAndDecode(img)
其中:
img为输入图像,灰度或者彩色图像;
points输出二维码ROI最小外接矩形顶点坐标;
straight_qrcode输出的是二维码区域ROI图像信息 返回的二维码utf-8字符串;

其c++识别二维码的使用案例可以参考:https://blog.csdn.net/u014072827/article/details/112270853。

opencv4 以上可以对二维码进行检测并识别,但在使用过程中发现,其效果不是特别好, 在很多情况识别失败, 而且不支持barcode失败

2.3 ZXing (“zebra crossing”)

ZXing是一个开源的,用Java实现的多种格式的一维/二维条码图像处理库,它包含了联系到其他语言的端口。zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。

基本功能:

  • 通过摄像头扫描二维码图片,读取图片内容
  • 从相册中选取二维码图片,读取图片内容
  • 自己输入字符串内容,生成二维码图片
  • 长按识别自己生成的二维码图片

2.4 ZBar

ZBar 是一个开源软件套件,用于读取来自各种来源的条形码,例如视频流、图像文件和原始强度传感器。它支持许多流行的符号系统(条形码类型),包括 EAN-13/UPC-A、UPC-E、EAN-8、Code 128、Code 39、Interleaved 2 of 5 和 QR 码。

灵活的分层实施有助于任何应用程序的条码扫描和解码:与随附的 GUI 和命令行程序独立使用,轻松将条码扫描小部件集成到您的 Qt、GTK+ 或 PyGTK GUI 应用程序中。

特征
*跨平台 - Linux/Unix、Windows、iPhone®、嵌入式…
*高速 - 实时扫描视频流
*内存占用小
*不限于图像,无浮点运算
*适用于嵌入式应用,使用价格低廉 处理器/硬件
*模块化组件可以一起使用,也可以单独使用

2.5 结论

选择哪个库取决于你的应用,如果二维码比较标准建议BoofCV(一种用Java实现的开源、实时的计算机视觉库),它的检测精度高而且速度也很好,如果二维码有污损或外观变化,ZXing是不错的选择。如果只能使用C++,则推荐Zbar。OpenCV则是毫无疑问总是最差。
二维码识别检测的几大开源库比较的具体结果可参考:
https://blog.csdn.net/yangdashi888/article/details/99093756

3、Zbar库安装使用

3.1 Zbar库安装

Zbar库默认提供的是32位的库文件,其下载安装地址为:https://zbar.sourceforge.net/download.html,windows用户在官网安装以下连接进行下载,下载软件后一路点默认选择即可。安装好软件后,需要在系统环境变量path中添加zbar/bin路径。
在这里插入图片描述
如果是64位的电脑,可以到以下链接下载64位的zbar库。ZBar库(含64位库与32位库文件)免安装版

更多zbar库安装配置细节可以参考: C++利用Zbar识别二维码

3.2 配置vs环境

使用zbar进行二维码识别,需要依赖opencv进行图像的读取。故此需要配置zbar与opencv。
其中opencv的安装可以参考 opencv 一 基本运行环境配置(下载安装、编写代码、配置环境)

配置细节
include目录、lib目录以及lib文件的配置如下,其中需要注意这些配置与运行环境(如下图中红色区域是Release 64位环境,该配置在其他环境下是无效的)密切相关。
在这里插入图片描述
在这里插入图片描述

3.3 使用案例

具体使用案例如下,通过recognition_qrcode函数可以调用zbar库完成二维码识别并返回识别结果。使用zbar进行二维码识别时,识别性能与图像尺寸密切相关,当图像尺寸较大时,识别时间较长,可以通过对图像进行resize来提升识别速度


#include <iostream>
#include "zbar.h"
#include "string.h"
#include <opencv2/opencv.hpp>
#include <chrono>
using namespace std;
using namespace zbar;  //添加zbar名称空间      
using namespace cv;

string recognition_qrcode(cv::Mat image)
{
    
    
    zbar::ImageScanner scanner;
    scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
    auto beforeTime = std::chrono::steady_clock::now();
    int width = image.cols;
    int height = image.rows;
    uchar* raw = (uchar*)image.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())
    {
    
    
        std::cout << "查询条码失败,请检查图片!" << std::endl;
    }
    string result;
    for (; symbol != imageZbar.symbol_end(); ++symbol)
    {
    
    
        std::cout << "类型:" << symbol->get_type_name() << std::endl;
        std::cout << "条码:" << symbol->get_data() << std::endl;
        result = symbol->get_type_name() + ":"+ symbol->get_data();
    }
   // cv:imshow("Source Image", image);
    //cv::waitKey();
    auto afterTime = std::chrono::steady_clock::now();

    std::cout << "总耗时:" << std::endl;
    //毫秒级
    double duration_millsecond = std::chrono::duration<double, std::milli>(afterTime - beforeTime).count();
    std::cout << duration_millsecond << "毫秒" << std::endl;

    return result;
}

int main(int argc, char* argv[]) {
    
    
    std::string path = "D:\\二维码识别\\t2.png";
    Mat imageSource = imread(path, 0);
    if (imageSource.cols >= 2048) {
    
    
        resize(imageSource, imageSource, {
    
    }, 0.25, 0.25);
        std::cout << "图像被resize了!!!!" << std::endl;
    }
    string res = recognition_qrcode(imageSource);
    imshow("res", imageSource);
    waitKey();
}

二维码识别效果如下所示
在这里插入图片描述
条形码识别效果如下所示
在这里插入图片描述

3.4 使用技巧

在某些复杂的图像场景中,zbar库不一定能识别出条形码或二维码,这并不是zbar性能不行,而是其无法准确的找到要识别的对象。我们可以自己设计算法先实现条形码或者二维码的粗定位,提升条形码或者二维码在原图中的占比,然后在使用zbar库就可以识别二维码或条形码的识别了。
其中,二维码的粗定位可以参考:opencv 十四 二维码的粗定位提取,关于条形码的粗定位也可以参考该博文的思路。

猜你喜欢

转载自blog.csdn.net/m0_74259636/article/details/134742584