本篇使用 python-barcode 套件製作條碼,再使用 pyzbar 套件辨識條碼。請注意,安裝 python-barcode 時,還要手動安裝 Pillow,否則 python-barcode 會發生例外。
BarCode 格式
BarCode 有一維條碼及二維條碼,
一維條碼如下圖:
二維條碼如下圖
EAN13
EAN13 是市面上商品的條碼格式,格式為 “國碼+公司碼+流水號”,共有12碼,而且只能是數字。但仔細算一下條碼上的文字卻有 13 碼,因為最後一碼是檢查號碼。
code128
code128 沒有碼數限制,可以是英文字母或數字。
安裝套件
在 python 中製作條碼最方便的套件為 python-barcode。
本例需安裝套件
pip install python-barcode matplotlib pandas pyside6 matplotlib pillow mysql-connector-python
製作條碼
barcode 提供 barcode.get() 製作條碼圖像,再用 code.render 轉成 Pillow 格式。
import pylab as plt import barcode from barcode.writer import ImageWriter n="123456789012" code=barcode.get('EAN13', '4713268582114', writer=ImageWriter()) #bar.save("barcode") opts={ "module_width":0.2,#預設為 0.2 "module_height":10, "text_distance":4, "font_size":9 } img=code.render(writer_options=opts) img.save("barcode.jpg") plt.imshow(img) plt.show()
輸出 Pillow 選項
code.render 轉成 Pillow 格式,writer_options 參數可以設定輸出選項,常用參數如下。
"module_width" : 每個條碼寬度,單位為毫米,預設為0.2 "module_height" : 條碼高度,單位為毫米,預設為15.0 "quiet_zone" : 兩端空白寬度,單位為毫米,預設為 6.5 "font_size" : 字体大小,單位為磅,預設為 10 "text_distance": 本文和條碼之間的距離,單位為毫米,預設為5 "background": 背景色,預設為白色 "foreground": 前景色,預設為黑色 "write_text": 是否顯示本文,預設為 True "center_text" : 本文是否置中, 預設為 True "format" : 圖片格式,預設為 'PNG' "dpi" : 圖片分辨率,預設 300 dpi (ImageWriter 時才有效)
module_width 盡可能不要改變,不然顯示出來的圖片 BarCode 機器不易掃瞄,甚至掃瞄不正確。
Pillow 轉 QPixmap
經由 barcode 取得的 Pillow 圖像,若要置入 Pyside6 的 QLabel 中,請先了解如下順序
Pillow.ImageQt(pil) => QImage => QPixmap => QLabel
先使用Pillow 的 ImageQt.toqimage(pil) 轉成 QImage 格式,再轉成 QPixmap,最後餵給 QLabel ,完整代碼如下。
no="123456789012"
code = barcode.get('EAN13', no, writer=ImageWriter())
opts = {
"module_width": 0.1, # 預設為 0.2
"module_height": 2,
"write_text":''
}
pil = code.render(writer_options=opts)
pix = QPixmap(ImageQt.toqimage(pil))
self.lblBarcode.setPixmap(pix)
pyzbar 辨識 BarCode
可以辨識 barcode 圖片的套件蠻多的,比如 cv2 。但 cv2 只能辨識 EAN13 格式,對於 code128 就沒轍。
pyzbar 經本人測試認為是最方便且準確的套件,本例以此進行說明。
本例需安裝套件
pip install opencv-python pyzbar
首先由 cv2 讀入圖片,再將 numpy 格式的圖片傳入 pyzbar 進行辨識
import numpy as np import cv2 from pyzbar import pyzbar img=cv2.imdecode( np.fromfile("19690507.jpg", dtype=np.uint8), cv2.IMREAD_UNCHANGED ) codes=pyzbar.decode(img) for code in codes: data=code.data.decode("utf-8") type=code.type print(f"BarCode資料 : {data}") print(F"BarCode格式 : {type}") 結果: BarCode資料 : 4713268582114 BarCode格式 : CODE128
barcode 深入研究
1. 首先指定條碼的格式
import barcode format=barcode.get_barcode_class("code128")
2. 將條碼資料傳入 format 中.產生 barcode 格式的圖像。format 中的 writer = ImageWriter(format=”jpeg”) 是指定要轉換成那一種圖像格式,所以當使用 save 儲存檔案時不需指定副檔名。圖像格式跟 Pillow 完全一樣,可以是 “png”,”jpeg” 等, 但就是沒有 “jpg”。
import barcode
format=barcode.get_barcode_class("code128")
from barcode.writer import ImageWriter
img=format("123456", writer=ImageWriter(format="png"))
img.save("a")
3. save 時的 options 參數可以設定前景色、間距(module_width)、高度(module_height)。間距預設為 0.2
import barcode
format=barcode.get_barcode_class("code128")
from barcode.writer import ImageWriter
img=format("123456", writer=ImageWriter(format="png"))
opts={
"foreground":"red",
"module_width":0.1,#預設為 0.2
"module_height":10
}
img.save("a", options=opts)
4. 使用 render 轉成 Pillow 格式,將 options 傳入,最後使用 Pillow 的 save 即可轉成 “.jpg” 格式
import barcode
format=barcode.get_barcode_class("code128")
from barcode.writer import ImageWriter
import pylab as plt
img=format("123456", writer=ImageWriter(format="png"))
opts={
"foreground":"red",
"module_width":0.1,#預設為 0.2
"module_height":10
}
img.save("a", options=opts)
pil=img.render(writer_options=opts)
pil.save("b.jpg")
plt.imshow(pil)
plt.show()
5. 結果 : format=”png” 其實可以省略,因為最後都是由 Pillow 輸出存檔。
barcode.generate
barcode 套件也可以使用 barcode.generate 產生檔案格式,再由 image.imread 讀取轉成 Pillow 格式。但這種作法比是何用意,本人也不太清楚,所以僅作記錄用。
from barcode import EAN13 import pylab as plt import barcode from barcode.writer import ImageWriter from matplotlib import image n="123456789012" bar=barcode.generate( "code128", n, writer=ImageWriter(), output="barcode_png" ) img=image.imread(bar) plt.imshow(img) plt.show()