1. 程式人生 > >Python製作二維碼和條形碼掃描器 (pyzbar)

Python製作二維碼和條形碼掃描器 (pyzbar)

條碼在生活中隨處可見,其可分為三類:一維條碼、二維條碼、三維條碼

一維條碼:

       我們平時習慣稱為條形碼。條形碼是將寬度不等的多個黑條和空白,按照一定的編碼規則排列,用以表達一組資訊的圖形識別符號。常見的條形碼是由反射率相差很大的黑條(簡稱條)和白條(簡稱空)排成的平行線圖案。

二維條碼:

      二維條碼簡稱為二維碼,常見的二維碼為QR Code,QR全稱Quick Response,是一個近幾年來移動裝置上超流行的一種編碼方式,它比傳統的Bar Code條形碼能存更多的資訊,也能表示更多的資料型別。

三維條碼:

    三維條碼具有更大的資訊容量、相同的識別便易性和較好的安全性。三維碼的主要特徵在於利用色彩或灰度(或稱黑密度)表示不同的資料並進行編碼。

 

一、實現效果

           

 

二、安裝所需的庫

2.1、安裝掃描庫

安裝命令:pip3 install pyzbar

其實Python的條碼掃描庫,一直都有一個很是出名,那就是zbar,但此庫雖然牛,卻已經停止維護了,如果是python3,則不能使用zbar庫了,python2.7還是可以用的。忙活了一下午才發現我的python3.5不能用zbara庫,哈哈藍瘦

 

2.2、安裝其他必要庫

後續功能需要用到PIL和OpenCV-Python相關庫,可參考以下連結進行簡單認識和庫的安裝

玩轉Python圖片處理(OpenCV-Python)

Python的GUI程式設計(TK)

 

三、系統環境準備

3.1、Windows環境

 如果是Windows電腦則可以跳過。*  0  *

 

3.2、樹莓派環境

第一步:插入並開啟CSI攝像頭(參考:https://www.cnblogs.com/dongxiaodong/p/9814119.html)

第二步:配置系統啟動之後載入bcm2835-v4l2這個模組,原因是樹莓派中的camera module是放在/boot/目錄中以韌體形式載入的,不是一個標準的V4L2的攝像頭驅動,所以用opencv的(cv2.VideoCapture(0)會無視訊資料),加上這句之後就可以解決以上問題。

命令:sudo vi /etc/modules

加入:bcm2835-v4l2

 

四、實現簡單的圖識別

 使用pyzbar和PIL 進行圖片的二維碼識別,並輸出識別結果

識別結果:

 

找到一張二維碼圖片,並下載其中二維碼:

基本程式碼:

 1 import pyzbar.pyzbar as pyzbar
 2 from PIL import Image,ImageEnhance
 3 
 4 image = "imgx\dongxiao.png"
 5 
 6 img = Image.open(image)
 7 #處理圖片
 8 #img = ImageEnhance.Brightness(img).enhance(2.0)#增加亮度
 9 
10 #img = ImageEnhance.Sharpness(img).enhance(17.0)#銳利化
11 
12 #img = ImageEnhance.Contrast(img).enhance(4.0)#增加對比度
13 
14 #img = img.convert('L')#灰度化
15 
16 #顯示原圖,呼叫系統預設的圖片顯示器
17 img.show()
18 
19 texts = pyzbar.decode(img)
20 #輸出結果
21 for text in texts:
22     tt = text.data.decode("utf-8")
23     print(tt)

五、圖識別進階

使用pyzbar和PIL 及OpenCV-Python,實現二維碼圖片框選和在圖片上印字型

識別結果:

基本程式碼:

 1 import cv2
 2 import pyzbar.pyzbar as pyzbar
 3 import numpy
 4 from PIL import Image, ImageDraw, ImageFont
 5 
 6 def decodeDisplay(imagex1):
 7     # 轉為灰度影象
 8     gray = cv2.cvtColor(imagex1, cv2.COLOR_BGR2GRAY)
 9     barcodes = pyzbar.decode(gray)
10 
11     for barcode in barcodes:
12 
13         # 提取條形碼的邊界框的位置
14         # 畫出影象中條形碼的邊界框
15         (x, y, w, h) = barcode.rect
16         cv2.rectangle(imagex1, (x, y), (x + w, y + h), (255, 255, 0), 2)
17 
18         # 條形碼資料為位元組物件,所以如果我們想在輸出影象上
19         # 畫出來,就需要先將它轉換成字串
20         barcodeData = barcode.data.decode("utf-8")
21         barcodeType = barcode.type
22 
23         #不能顯示中文
24         # 繪出影象上條形碼的資料和條形碼型別
25         #text = "{} ({})".format(barcodeData, barcodeType)
26         #cv2.putText(imagex1, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,5, (0, 0, 125), 2)
27 
28         #更換為:
29         img_PIL = Image.fromarray(cv2.cvtColor(imagex1, cv2.COLOR_BGR2RGB))
30 
31         # 引數(字型,預設大小)
32         font = ImageFont.truetype('fontx/hwst.ttf', 25)
33         # 字型顏色(rgb)
34         fillColor = (255,0,0)
35         # 文字輸出位置
36         position = (x, y-10)
37         # 輸出內容
38         str = barcodeData
39 
40         # 需要先把輸出的中文字元轉換成Unicode編碼形式(  str.decode("utf-8)   )
41 
42         draw = ImageDraw.Draw(img_PIL)
43         draw.text(position, str, font=font, fill=fillColor)
44         # 使用PIL中的save方法儲存圖片到本地
45         # img_PIL.save('02.jpg', 'jpeg')
46 
47         # 轉換回OpenCV格式
48         imagex1 = cv2.cvtColor(numpy.asarray(img_PIL), cv2.COLOR_RGB2BGR)
49 
50 
51         # 向終端列印條形碼資料和條形碼型別
52         print("掃描結果==》 類別: {0} 內容: {1}".format(barcodeType, barcodeData))
53     cv2.imshow("camera", imagex1)
54     # 視窗等待任意鍵盤按鍵輸入,0為一直等待,其他數字為毫秒數
55     cv2.waitKey(0)
56 
57     # 銷燬視窗,退出程式
58     cv2.destroyAllWindows()
59 
60 def detect():
61     cv2.namedWindow("camera",cv2.WINDOW_NORMAL)
62     frame=cv2.imread("imgx\dongxiao2.png")
63     decodeDisplay(frame)
64 
65 
66 if __name__ == '__main__':
67     detect()

六、實現視訊實時讀取

 OpenCV-Python視訊讀取,並幀處理視訊,實現條碼的動態框選和識別

識別結果:

基本程式碼:

 1 import cv2
 2 import pyzbar.pyzbar as pyzbar
 3 import numpy
 4 from PIL import Image, ImageDraw, ImageFont
 5 
 6 def decodeDisplay(imagex1):
 7     # 轉為灰度影象
 8     gray = cv2.cvtColor(imagex1, cv2.COLOR_BGR2GRAY)
 9     barcodes = pyzbar.decode(gray)
10 
11     for barcode in barcodes:
12 
13         # 提取條形碼的邊界框的位置
14         # 畫出影象中條形碼的邊界框
15         (x, y, w, h) = barcode.rect
16         cv2.rectangle(imagex1, (x, y), (x + w, y + h), (0, 255, 0), 2)
17 
18         # 條形碼資料為位元組物件,所以如果我們想在輸出影象上
19         # 畫出來,就需要先將它轉換成字串
20         barcodeData = barcode.data.decode("utf-8")
21         barcodeType = barcode.type
22 
23         #不能顯示中文
24         # 繪出影象上條形碼的資料和條形碼型別
25         #text = "{} ({})".format(barcodeData, barcodeType)
26         #cv2.putText(imagex1, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,5, (0, 0, 125), 2)
27 
28 
29         #更換為:
30         img_PIL = Image.fromarray(cv2.cvtColor(imagex1, cv2.COLOR_BGR2RGB))
31 
32         # 引數(字型,預設大小)
33         font = ImageFont.truetype('fontx/hwst.ttf', 35)
34         # 字型顏色(rgb)
35         fillColor = (0,255,255)
36         # 文字輸出位置
37         position = (x, y-10)
38         # 輸出內容
39         str = barcodeData
40 
41         # 需要先把輸出的中文字元轉換成Unicode編碼形式(  str.decode("utf-8)   )
42 
43 
44         draw = ImageDraw.Draw(img_PIL)
45         draw.text(position, str, font=font, fill=fillColor)
46         # 使用PIL中的save方法儲存圖片到本地
47         # img_PIL.save('02.jpg', 'jpeg')
48 
49         # 轉換回OpenCV格式
50         imagex1 = cv2.cvtColor(numpy.asarray(img_PIL), cv2.COLOR_RGB2BGR)
51 
52 
53         # 向終端列印條形碼資料和條形碼型別
54         print("掃描結果==》 類別: {0} 內容: {1}".format(barcodeType, barcodeData))
55     cv2.imshow("camera", imagex1)
56 
57 
58 def detect():
59     cv2.namedWindow("camera",cv2.WINDOW_NORMAL)
60     camera = cv2.VideoCapture(0)
61 
62     while True:
63         # 讀取當前幀
64         ret, frame = camera.read()
65         #print(ret.shape)
66         decodeDisplay(frame)
67 
68         if(cv2.waitKey(5)==27):
69             break
70     camera.release()
71     cv2.destroyAllWindows()
72 
73 
74 if __name__ == '__main__':
75     detect()

 

 


 

參考:

http://www.cnblogs.com/xushengming/p/9872061.html

https://blog.csdn.net/zx66zx/article/details/82785334

https://blog.csdn.net/x115104/article/details/78878599

https://blog.csdn.net/shanzhizi/article/details/50755168