[Python]在Windows系統中使用ZXing模組實現二維碼、條碼讀碼

來源:互聯網
上載者:User

標籤:mat   資料   out   group   rar   turn   mvn   parse   html   

??需要實現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, osclass 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 codesclass 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.rawdef GetCodeString(filename):    """    解碼函數,只處理單個檔案,參數為檔案名稱(含路徑)。    返回編碼字串,如果未能成功解碼或未找到條碼,返回Null 字元串。    """        #將‘\‘替換成‘/‘    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.Datadef 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,GetCodeObjectresult = 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即可。

  • 同樣可以使用第四步的代碼進行測試。

[Python]在Windows系統中使用ZXing模組實現二維碼、條碼讀碼

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.