[Python]在Windows系统中使用ZXing模块实现二维码、条形码读码

??需要实现Python读取图片中二维码、条形码信息。前段时间研究使用zbarlight模块,费了很大功夫安装调试好,但是发现有些图片读取不正确,而且如果图片中二维码倾斜,就读取不了,不能满足要求。昨天琢磨着试一试ZXing,下载ZXing模块安装后,却一直报错。打开模块源码仔细分析,原来该模块是通过调用java程序,使用ZXing的java库来实现的,通过分析命令行输出得到解码结果。忙活了一天多,各种测试、查资料,终于解决了问题。调试过程非常艰辛,现将做法整理如下(Windows 10系统):

?一、 因为需要调用java程序,必须安装jdk。

  • 下载java安装程序,根据提示一步步安装。

  下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html

  • 设置环境变量。

  添加JAVA_HOME环境变量,其值设置为jdk安装目录。将java运行程序所在目录(%JAVA_HOME%\bin)添加到PATH。

  • 在命令行输入java -version并执行,如果没有问题则说明安装成功。

?二、下载ZXing的jar库文件,以及所需java库文件。

  • 下载ZXing Core和ZXing Java SE Extensions库文件。

  登录网址http://www.mvnrepository.com,在搜索栏中输入"zxing"并查找,就能找到这两个库,下载库文件并将其分别改名为core.jar和javase.jar。

  • 下载 JCommander库文件。

  在测试中,安装了上面两个库以后,仍然报错,错误信息中提示JCommander模块找不到,后来下载了这个库文件,经过多番调试,终于成功。登录网址http://www.mvnrepository.com,在搜索栏中输入"jcommander"并查找,就能找到这个库,下载库文件并将其改名为jcommander.jar。

  • 创建一个目录,并将以上三个jar文件复制到其中。

  这个目录可以创建在java安装目录下。我是在java目录下建了一个名为jar的文件夹,将上面三个文件复制到里面。

  • 设置环境变量。

  添加ZXING_JAR_PATH环境变量,将其值设为上面创建的那个文件夹的绝对路径,我的路径是“d:\java\jar”。

?三、在ZXing源代码基础上进行修改,实现二维码、条形码解码功能;增加了两个函数,解决了不支持图片Windows格式绝对路径的问题。

#导入模块
import subprocess, re, os

class BarCodeReader():
    """
    解码器类,调用java执行ZXing库命令实现解码,通过分析输出获得结果。
    此模块在ZXing源码基础上修改,改动较大。
    """

    #ZXing库路径
    location = ""
    #ZXing库
    libs = ["javase.jar", "core.jar", "jcommander.jar"]
    #subprocess.Popen参数
    args = ["java", "-cp", "LIBS", "com.google.zxing.client.j2se.CommandLineRunner"]

    def __init__(self, loc=None):
        """
        初始化函数,参数loc设置ZXing库所在位置
        """

        #如果loc为空或者不是字符串对象,读取环境变量ZXING_JAR_PATH的值(没找到就设为空字符串)
        if not loc or not isinstance(loc,str):
            loc = os.environ.get("ZXING_JAR_PATH", "")

        #如果loc不为空,在末尾加上‘\‘,否则设为默认值(即在当前目录的zxing子目录下)
        if loc:
            loc = loc.rstrip("\\") + "\\"
        else:
            loc = "zxing\\"

        #设置location
        self.location = loc

    def decode(self, files, try_harder = False, qr_only = False):
        """
        解码方法,参数files可以是一个文件名(字符串),也可以是一个文件名列表。
        """

        #根据try_harder和qr_only参数设置,添加相应选项
        if try_harder:
            self.args.append("--try_harder")
        if qr_only:
            self.args.append("--possibleFormats=QR_CODE")

        #为ZXing库加上路径
        libraries = [self.location + lib for lib in self.libs]

        #生成命令列表
        cmd = [ c if c != "LIBS" else os.pathsep.join(libraries) for c in self.args ]

        #单文件标志设为False
        SINGLE_FILE = False

        #如果files不是列表,将文件files添加到cmd列表,单文件标志设为True
        if not isinstance(files, list):
            cmd.append(files)
            SINGLE_FILE = True
        #否则,将文件列表files添加到cmd列表
        else:
            cmd += files

        #利用subprocess.Popen函数执行命令
        (stdout, stderr) = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True).communicate()

        #初始化编码列表
        codes = []

        #分析输出内容
        file_results = stdout.split("\nfile:")
        for result in file_results:
            lines = result.split("\n")
            if re.search("No barcode found", lines[0]):
                codes.append(None)
            else:
                codes.append(BarCode(result))

        #如果是单文件,返回第一个BarCode对象;否则,返回BarCode对象列表
        if SINGLE_FILE:
            return codes[0]
        else:
            return codes

class BarCode:
    """
    BarCode信息类,包含解码所得各项信息。
    此模块基本使用了ZXing源码,为方便使用,添加了几个属性。
    """
    format = ""
    points = []
    data = ""
    raw = ""

    def __init__(self, zxing_output):
        lines = zxing_output.split("\n")
        raw_block = False
        parsed_block = False
        point_block = False

        self.points = []
        for l in lines:
            m = re.search("format:\s([^,]+)", l)
            if not raw_block and not parsed_block and not point_block and m:
                self.format = m.group(1)
                continue

            if not raw_block and not parsed_block and not point_block and l == "Raw result:":
                raw_block = True
                continue

            if raw_block and l != "Parsed result:":
                self.raw += l + "\n"
                continue

            if raw_block and l == "Parsed result:":
                raw_block = False
                parsed_block = True
                continue

            if parsed_block and not re.match("Found\s\d\sresult\spoints", l):
                self.data += l + "\n"
                continue

            if parsed_block and re.match("Found\s\d\sresult\spoints", l):
                parsed_block = False
                point_block = True
                continue

            if point_block:
                m = re.search("Point\s(\d+):\s\(([\d\.]+),([\d\.]+)\)", l)
                if (m):
                    self.points.append((float(m.group(2)), float(m.group(3))))

        #去除多余换行符
        self.raw = self.raw.rstrip("\n")
        self.data = self.data.rstrip("\n")

    @property
    def Format(self):
        """
        返回编码格式
        """
        return self.format

    @property
    def Data(self):
        """
        返回编码数据
        """
        return self.data

    @property
    def Points(self):
        """
        返回坐标点
        """
        return self.points

    @property
    def RawData(self):
        """
        返回解码所得原始数据
        """
        return self.raw

def GetCodeString(filename):
    """
    解码函数,只处理单个文件,参数为文件名(含路径)。
    返回编码字符串,如果未能成功解码或未找到条码,返回空字符串。
    """

    #将‘\‘替换成‘/‘
    filename = filename.replace("\\", "/")

    #如果带有盘符(绝对路径),前面加上‘file:/‘
    if re.match(‘^[A-Za-z]:‘, filename):
        filename = "file:/" + filename

    #创建解码器对象
    zxcode = BarCodeReader()

    #解码,并将结果保存到barcode
    barcode = zxcode.decode(filename)

    #如果结果为None,返回空串,否则返回编码字符串
    if barcode is None:
        return ""
    else:
        return barcode.Data

def GetCodeObject(filename):
    """
    解码函数,只处理单个文件,参数为文件名(含路径)。
    返回编码对象,其属性如下:
        Data,编码信息;
        Format,编码类别;
        Points,坐标点;
        RawData,未处理的编码信息。
    如果未能成功解码或未找到条码,返回None
    """

    #将‘\‘替换成‘/‘
    filename = filename.replace("\\", "/")

    #如果带有盘符(绝对路径),前面加上‘file:/‘
    if re.match(‘^[A-Za-z]:‘, filename):
        filename = "file:/" + filename

    #创建解码器对象
    zxcode = BarCodeReader()

    #解码,并将结果保存到barcode
    barcode = zxcode.decode(filename)

    #返回结果
    return barcode

?四、测试。将上述代码保存到zxing.py文件中,编辑测试代码如下:

from zxing import GetCodeString,GetCodeObject
result = GetCodeString("d:\\barcode.png")
print(result)
result = GetCodeObject("d:\\qr.png")
if result:
    print("Format:", result.Format)
    print("Data:  ", result.Data)
    print("Points:")
    for point in result.Points:
        print(point)

?五、可以将以上面的代码安装到Python库(注册为zxing模块)。

  • 下载python-zxing模块。下载地址为https://github.com/oostendo/python-zxing
  • 解压缩到python-zxing文件夹。
  • 将python-zxing\zxing文件夹内__init__.py文件的内容替换成第三步的代码。
  • 在python-zxing文件夹下打开命令行,运行python setup.py install即可。
  • 同样可以使用第四步的代码进行测试。

原文地址:https://www.cnblogs.com/syh6324/p/9508134.html

时间: 2024-10-10 07:49:20

[Python]在Windows系统中使用ZXing模块实现二维码、条形码读码的相关文章

有关iOS系统中调用相机设备实现二维码扫描功能的注意点(3/3)

今天我们接着聊聊iOS系统实现二维码扫描的其他注意点. 大家还记得前面我们用到的输出数据的类对象吗?AVCaptureMetadataOutput,就是它!如果我们需要实现目前主流APP扫描二维码的功能,即只有当二维码进入视图中心的方框中时才进行扫描识别功能,这样做的目的主要是为了提高用户的使用体验,需要用到这个类里面的一个属性:rectOfInterest,这个属性是一个CGRect结构体类型.但和我们平时经常使用的CGRect有点不一样.以下截取了官网文档对这个属性的表述: /*! @pro

安卓开发中使用ZXing生成解析二维码

编码示例 package com.wolf_pan.qrcodesample; import android.graphics.Bitmap; import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Log; imp

python在windows系统上创建文件

正确方法为:open("test1.txt",'wb')或open("test1.txt",'w') 以下是网上的方法创建遇到的问题 使用Python2.7在windows系统中os.mknod调用错误 一直想学习一门脚本语言,用来做一些快速的脚本处理.在同事的强烈推荐下,我选择了Python.最开始被它吸引的是 缩进即代码块 的风格.在c++开发中,不规范的缩进风格让人总是产生一种不舒服的代码阅读体验.我非常欣赏这种新的语言可以优雅的解决这个问题. 开始安装Pty

Windows系统中Xshell与Linux连接时遇到的问题

前提条件:在Windows系统中已经安装了Xshell,并且安装了虚拟机软件和Linux系统 步骤1.在Linux系统中root用户下,使用ifconfig命令查看虚拟系统Linux的IP地址.如图1 图1 步骤2.打开Xshell,创建连接,在新建会话属性对话框中,登记连接的名字,选择使用的协议,以及需要连接的虚拟机IP地址.如图2 图2 当连接建立好,只需根据提示输入用户名和密码就可以在Xshell终端使用Linux系统. 下面讨论当连接不能连接时,需要在哪许方面找原因: 原因1:虚拟机网络

如何将USBKey中的证书注册到Windows系统中

本篇文章就介绍一下如何使用微软CAPI接口完成将USBKey中的证书注册到Windows系统中. (1)        获取CSP句柄. CryptAcquireContext(&hTokenProv,NULL,“EnterSafe ET199Auto CSP V1.0”,PROV_RSA_FULL,NULL) (2)        获取USBKey内密钥句柄,这时要注意锁内密钥的类型是签名密钥(AT_SIGNATURE)或者交换密钥(AT_KEYEXCHANGE). CryptGetUserK

python同步windows系统时间

import os com1 = 'net use \\\\192.168.0.90\\ipc$ PPss01!123/user:administrator' os.system(com1) com2='net time \\\\192.168.0.90 /set /yes ' os.system(com2) com3='pause' os.system(com3) python同步windows系统时间

在windows系统中使用backoff2005的测试脚本来测试分词结果

分词程序的测试一般用backoff2005的脚本,但是backoff2005脚本是运行在linux系统上的.如果在windows系统中时,怎么使用该脚本呢?假设用户已经有了icwb2-data压缩包了. 首先得安装perl开发环境.下载地址: https://dwimperl.googlecode.com/files/dwimperl-5.14.2.1-v7-32bit.exe接下来,需要安装diff工具,下载地址: http://superb-dca3.dl.sourceforge.net/p

在Windows系统中安装集成的PHP开发环境

原文:在Windows系统中安装集成的PHP开发环境 刚想学php的,又不会配置复杂php的环境,可以使用集成的,目前网上提供常用的PHP集成环境主要有AppServ.phpStudy.WAMP和XAMPP等软件,这些软件之间的差别不大.每种集成包都有多个不同的版本,可以下载版本比较高的任意一个集成软件安装使用. 我用的是appserv-win32-2.5.10.exe下载地址:http://www.appservnetwork.com/index.php?newlang=chinese App

Cmder命令行工具在Windows系统中的配置

一.Cmder简介 Cmder:一款用于Windows系统中,可增强传统cmd命令行工具的控制台模拟器(类似于Linux系统中的终端控制窗口) 特点: 无需安装,解压即用 可使用较多Linux命令,如:vi.vim.ls.pwd.grep.unzip.bash.perl.ssh 可在窗口内外自由使用常规的复制和粘贴操作 支持多Tab页的cmd窗口 提供了对命令窗口中的字符串进行快速搜索定位的功能 在传统cmd命令行工具的基础上,增加了Monokai配色方案,界面美观 命令窗口尺寸大小可自由调整