树莓派python实现二维码识别——ZBar
阅读原文时间:2021年04月24日阅读:1

树莓派二维码识别

最近一直忙于科研,好久没有更新博客了。今天更新一篇关于使用树莓派进行二维码识别的文章,是笔者树莓派项目开发的第四篇博客,希望能够给大家带来一丝的帮助。
现在二维码活跃在我们身边的大街小巷,基本上每天都会和二维码打交道,共享单车啊,移动支付等。那么如何实现二维码的识别呢,其实我们仔细观察二维码的特征的话,可能会看出一些特征,每一个QR码,都有三个定位块。识别二维码时会先找到定位块,然后开始读取二维码的的编码信息,然后遵循一定的规则对二维码的编码信息进行解码(翻译),解码出的内容就是我们想要的内容了,可以跳转网站,查看文字信息等。二维码识别的原理基于以上的过程,当然现在也有很多开源的二维码识别工具,如zbar和zxing。

1、开发环境搭建

硬件:树莓派3B plus 和 usb摄像头
软件: python2.7版本、二维码识别开源工具ZBar和opencv(opencv的安装可参考我的博客)

zbar 官网 http://zbar.sourceforge.net/

ZBar是一个开源软件套件,用于从各种来源读取条形码,例如视频流,图像文件和原始强度传感器。 它支持许多流行的符号(条形码类型),包括EAN-13 / UPC-A,UPC-E,EAN-8,
Code 128,Code 39,Interleaved 2 of 5和QR Code。灵活的分层实现方便了任何应用程序的条形码扫描和解码,可轻松地将条形码扫描小部件集成到您的Qt,GTK +或PyGTK GUI应用程序中,具备python,C++等多种语言API接口。广泛应用于零售、自动文档处理、库存跟踪、移动应用等领域。ZBar的特性如下:

  • 跨平台 - Linux / Unix,Windows,iPhone®,嵌入式
  • 高速 - 从视频流中实时扫描
  • 内存占用少
  • 小代码大小 - 核心扫描器和EAN解码器代表1K行的C代码
  • 没有浮点运算
  • 适用于使用廉价处理器/硬件的嵌入式应用
  • 模块化组件可以一起使用或单独使用

zbar 安装

方案一

命令行安装:sudo apt-get install python-zbar
直接安装,识别英文一点问题都没有,识别中文不支持。

测试安装成功,进入python 环境: import zbar

方案二

源码安装,可识别中文
1、wget命令用来从指定的URL下载zbar源码,命令如下:

wget  http://downloads.sourceforge.net/project/zbar/zbar/0.10/zbar-0.10.tar.gz

下载不成功的话,先用电脑下载zbar-0.10.tar.gz,上传到树莓派的pi目录下
2、解压zbar的源文件,解压至pi目录下的zbar-0.10文件夹

tar -zvxf  zbar-0.10.tar.gz 

3、zbar是基于C语言开发的,安装编译时需要编译器,安装python-gtk和libqt4-dev

sudo apt-get install python-gtk2-dev 

4、安装libqt4-dev

sudo apt-get install libqt4-dev

5、进入zbar-0.10文件夹,运行configure 命令如下,此步运行成功生成makefile

./configure --without-imagemagick -disable-video  -without-qt  -without-gtk  -without-x


6、 编译makefile : make

7、 make安装: sudo make install

8、 测试进入python环境:import zbar

注意:第5步安装时要进入/home/pi/zbar-0.10目录,第6、7步安装时可能会出现错误,但是并不影响使用。

zbar 中文支持修改

ZBar是日本人写的,若要识别带有中文文字的二维码,需要在安装的时候加个小插曲,需要修改一下ZBar源文件里面的函数:修改源文件下zbar-0.10/zbar/qrcode/qrdectxt.c
终端使用nano或者vim编辑器修改zbar-0.10/zbar/qrcode/qrdectxt.c函数,以下该步骤需要在下载完源码后进行,修改完成后再进行编译和安装。
1、打开qrdectxt.c,采用nano编辑器

2、找到默认编码的函数,修改编码,将 ISO8859-1,换成 GB18030 将SJIS,换成GB2312

3、找到默认编码定义的list,修改解码编码顺序

4、编译源码,安装ZBar
按照以上的步骤安装基本不会出现问题,如果出现问题仔细检查是否缺少相应的依赖安装即可。

2、二维码识别实践

ZBar可以直接对输入的图像提取二维码、扫码和解码,下面是笔者根据zbar的帮助文档改写的一个快速实现二维码识别的Demo,可实现对实施视频流中的二维码或者一维条码的识别,当二维码或者一维码的排放位置相对摄像头比较正时识别效果较好。

#-*- coding: UTF-8 -*-   
# Simple QR code recognition
# @author: zdl

# import the necessary packages
#import simple_barcode_detection
import cv2
import numpy as np
import zbar
from PIL import Image

# create a reader
scanner = zbar.ImageScanner()
# configure the reader
scanner.parse_config('enable')
font=cv2.FONT_HERSHEY_SIMPLEX
camera=cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    grabbed, frame = camera.read()
    if not grabbed:
        break
    pil= Image.fromarray(frame).convert('L') # 转成灰度图像
    width, height = pil.size
    raw = pil.tobytes()
    zarimage = zbar.Image(width, height, 'Y800', raw)
    scanner.scan(zarimage)
    for symbol in zarimage:  
    # do something useful with results 
        if not symbol.count: 
            print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data 
        cv2.putText(frame,symbol.data,(20,100),font,1,(0,255,0),4)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

但是为提高扫码和解码的效率,我们先使用图像处理算法实现对二维码的定位并提取二维码的图像,将该部分的图像送入ZBar的扫码器中。如何实现对二维码的定位呢,方法如下:

  • 基于梯度算子,水平垂直交叉定位
  • 角点检测,仿射变换法,可校正倾斜的二维码
  • 轮廓法,寻找最小外接矩形。
  • 轮廓层析结构法,寻找二维码的三个定位点,可校正二维码。
    我们采用第三种方法实现静态二维码的提取,实现二维码的识别。具体实现的步骤如下:
  1. 输入图像进行灰度化,滤波

  2. 图像进行Otsu自适应二值化。

  3. 二值化的图像进行图像形态学操作,实现细小连通区域的闭合。

  4. 图像位运算进行反色,这时二维码区域为白色。

  5. 寻找反色图像中的轮廓,二维码区域为轮廓中面积最大的那个,实现对二维码区域 的定位。

  6. 将定位的二维码图像取出,输入至zbar进行扫码和解码。
    源代码如下:

    -- coding: UTF-8 --

    Simple QR code detection

    @author: zdl

    ZBar+python2.7.13

    import cv2
    import numpy as np
    import zbar

    基于轮廓定位QR位置

    def find_code(img):
    # 高斯滤波
    blur = cv2.GaussianBlur(img,(5,5),0)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 二值化
    ret,th = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    # 形态学操作
    mask=cv2.erode(th,None,iterations=4)
    mask=cv2.dilate(mask,None,iterations=4)
    # 图像反色
    cv2.bitwise_not(mask, mask)
    # 寻找轮廓
    _,contours,hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # 寻找QR码的位置
    if len(contours)>0:
    cnt = max(contours, key=cv2.contourArea)
    x,y,w,h = cv2.boundingRect(cnt)
    img = cv2.rectangle(img,(x-15,y-15),(x+w+15,y+h+15),(0,255,0),3)

        img_ROI = img[y-15:y+h+15, x-15:x+w+15]
    
    else:
        img_ROI = img
    
    return img_ROI

    main函数

    if name == 'main':

    # 读入图片
    img = cv2.imread('introduce.jpg', 1)
    # 定位QR码的位置
    img_ROI = find_code(img)
    
    # 初始化scanner
    scanner = zbar.ImageScanner()
    scanner.parse_config('enable')
    
    font = cv2.FONT_HERSHEY_SIMPLEX # openCV 字体
    
    img_ROI_gray = cv2.cvtColor(img_ROI, cv2.COLOR_BGR2GRAY)
    # 扫码
    width, height = img_ROI_gray.shape  # 获取图片大小
    raw = img_ROI_gray.tobytes()        # 图像矩阵数据转为字节数据
    zarimage = zbar.Image(width, height, 'Y800', raw) # 设置参数
    scanner.scan(zarimage)   # 扫码
    # 解码
    for symbol in zarimage:  
    # do something useful with results 
        if not symbol.count:
            print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data
        else:
            print 'no'
        #cv2.putText(img,symbol.data,(20,100),font,1,(0,255,0),4) # 打印字符在图片上
    # DisPlay
    cv2.imshow('img_ROI', img_ROI_gray)
    cv2.imshow('image', img)
    cv2.waitKey(0)

运行效果:

基于本文,我们已经实现了二维码的识别,那么结合树莓派语音合成和树莓派控制方面的知识,是不是可以做点好玩的事情呢。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章