各種掃碼軟件
最近要做個二維碼識別的項目,查到二維碼識別有好多開源的不開源的軟件
http://www.oschina.net/project/tag/238/
Zbar
首先試了一下Zbar,python加載ZBar時各種報錯。可能的原因是zbar的dll文件是32位的,而我系統是64位的,所以運行不了。只能自己拿源碼編譯一個64位的出來,對於我這種伸手黨來說自己編譯源碼是難以接受的,所以就放棄了。后來看到文章說Zbar不能識別傾斜的條形碼,而且也不能定位條形碼區域。
Zxing
zbar不可行,就試一下zxing吧。很容易的找到了zxing在github上的頁面。
https://github.com/zxing/zxing/
然后發現zxing還有python版本:
一陣激動啊,點進去(https://github.com/oostendo/python-zxing),發現作者對這個python包的描述是:A quick and dirty wrapper for the ZXing barcode library.(一個快速且簡陋的zxing外殼)
把zxing文件夾還有其他幾個文件都下載下來,下面開始折騰這個簡陋的包。
建立Python Zxing項目
在Eclipse里新建一個PyDev項目,把zxing文件夾拷貝進去。
由於包含__init__.py這個文件,文件夾被自動識別為一個包。
tests.py是一個調用zxing識別條形碼的例程。主函數中調用了一個test_codereader()函數來識別當前目錄下一張圖片 sample.png 中的條形碼。
而test_codereader()則調用了這個為python開發的zxing包中decode()函數
zx = BarCodeReader()
barcode = zx.decode(testimage)
順藤摸瓜,打開__init__.py,里面有BarCodeReader()這個類的實現代碼。
Python調用jar包
在decode函數中,用subprocess包中的Popen實現了調用jar包的操作,類似於VB,VC中的管道通訊。
(stdout, stderr) = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True).communicate()
上面這句就是調用jar包的核心代碼,cmd是發給jar包的命令。cmd的類型是list,每個元素是一個參數,最終輸入給jar的命令形式如下。
['java', '-cp', '.;javase.jar;core.jar;jcommander-1.48.jar', 'com.google.zxing.client.j2se.CommandLineRunner', 'sample.png']
subprocess的使用方法網上有好多教程,這里主要的問題出在了調用jar包的命令本身。
出現的問題及解決方法
既然是例程,拿到手當然直接運行,卻卡在了subprocess.Popen()這里,報的錯誤是無法加載java主類。
1、錯誤: 找不到或無法加載主類 com.google.zxing.client.j2se.CommandLineRunnercmd
於是把cmd命令輸出了一下,這句命令是 java –cp 包路徑/jar報名.jar java類名。
首先發現的問題是我的目錄里沒有程序里指定的這兩個jar包(javase.jar;core.jar),而且路徑也不對。於是從網上搜到這兩個包的地址下載下來(當然也可以下載zxing的源碼手動編譯)。
關於如何編譯zxing的文章: http://blog.sina.com.cn/s/blog_76adb0160102uxqb.html
下載zxing的兩個jar包的文章:http://blog.csdn.net/rongbo_j/article/details/47055795
“zxing的jar包我們可以從maven資源庫中獲取,打開maven資源庫http://www.mvnrepository.com/,搜索zxing即可”
下載完jar包,把名字改為core.jar和javase.jar(為了跟代碼配合去掉了后面一串數字),拷貝到剛才項目的中的zxing文件夾中即可。
注意到原版程序中還給jar包加了目錄 libs = ["javase/javase.jar", "core/core.jar"]
我們需要把這句改成libs = ["javase.jar", "core.jar"],就是這么簡單粗暴。
再試一下,還是不行,輸出的cmd為:
['java', '-cp', '../javase.jar;../core.jar', 'com.google.zxing.client.j2se.CommandLineRunner', 'sample.png']
中jar包的路徑變成了../javase.jar;../core.jar,這斜杠和點一加,目錄就不對了。
於是找到給路徑加斜杠的那句代碼:
libraries = [self.location + "/" + l for l in self.libs]
把斜杠給刪掉,改成
libraries = [ l for l in self.libs]
這樣就去掉了路徑中的雙點和斜杠,再次運行,迎接新的問題。
2、NoClassDefFoundError: com/beust/jcommander/JCommander
具體信息如下:
Exception in thread "main" java.lang.NoClassDefFoundError: com/beust/jcommander/JCommander
at com.google.zxing.client.j2se.CommandLineRunner.main(CommandLineRunner.java:52)
Caused by: java.lang.ClassNotFoundException: com.beust.jcommander.JCommander
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
找不到JCommander類,雖然還是有問題,但主類總算找到了。。。
查了一下,原來JCommander是一個Java的命令行解析類,並不包含在zxing的jar包里面。需要單獨下載並放到項目目錄下。
鏈接里5樓的回復比較給力,因為給出了JCommander的下載地址:http://central.maven.org/maven2/com/beust/jcommander/1.48/jcommander-1.48.jar
把jar包放到zxing文件里,並在lib中添加這個包,即:
libs = ["javase.jar", "core.jar","jcommander-1.48.jar"]
現在的cmd命令變成了:
['java', '-cp', 'javase.jar;core.jar;jcommander-1.48.jar', 'com.google.zxing.client.j2se.CommandLineRunner', 'sample.png']
程序運行成功,但是條形碼的信息並沒有輸出,我們可以在調試的時候手動輸出一下。返回的信息存儲在file_results中,輸出一下即可。
可以看出這個二維碼對應的是一個網址,大家可以用手機的掃一掃驗證一下對不對。
條形碼也可以
找了個條形碼的圖片,放到目錄下試了試,也可以識別。
本文源碼
本文項目的源碼(包含那幾個jar文件)已上傳到CSDN: