5.29. 條碼與 Data Matrix 碼¶
另外兩個碼類別讓相機的解碼器更為完整。一維條碼(One-dimensional barcodes) -- 麥片盒側面的條紋、醫院的手腕帶、貨運標籤 -- 是至今仍日常使用、歷史最悠久的機器可讀符號。Data Matrix 碼像 QR 碼一樣是二維的,但在相同酬載大小下密度更高,且專為工業標記而設計 -- 雷射蝕刻在電路板上的製造商標記,而非牆上的海報。image 模組為各自配備了專屬的解碼器,涵蓋了消費性二維碼從未真正觸及的工業、零售與庫存應用。
5.29.1. 一維條碼¶
一維 條碼將其酬載編碼為一系列寬度各異的垂直長條,由左至右讀取(垂直方向的碼則由上至下讀取)。這些寬度會量化為少數幾個值之一,而寬度序列會依印製方所選的符號體系拼出字元:UPC 產品碼為數字、倉庫零件編號為英數字、Code 128 標籤則為任意文字。
find_barcodes() 會在影格中掃描任一受支援符號體系的一維條碼,並回傳一份 BarCode 結果物件清單:
codes = img.find_barcodes()
for c in codes:
img.draw_rectangle(c.rect, color=(0, 255, 0))
print(c.payload, c.type, c.quality)
解碼器在單次呼叫中同時橫向與縱向掃描整張影格,因此以任意角度印製的條碼都能在一次處理中找到,應用程式無需旋轉輸入。roi 可限制搜尋範圍;不存在其他調整參數 -- 此解碼器是自成一體的。
受支援的 符號體系 涵蓋常見的消費性與工業類別。零售類包括 image.EAN2、image.EAN5、image.EAN8、image.UPCE、image.UPCA、image.EAN13(多數消費性包裝上的固定長度數字碼)、image.ISBN10 與 image.ISBN13(同類體系改用於書籍)。通用類包括 image.I25(Interleaved 2 of 5,常見於貨運標籤)、image.CODABAR(用於圖書館與血庫)、image.CODE39、image.CODE93 與 image.CODE128(用於任意文字的可變長度英數字符號體系)。貨架邊緣類的 image.DATABAR(RSS-14)與 image.DATABAR_EXP(RSS-Expanded)則使清單更為完整。
每筆偵測都帶有邊界框相關屬性 -- x、y、w、h、rect、corners -- 以及解碼後以字串形式呈現的 payload。type 是上述清單中的符號體系常數,當應用程式特別在意解碼出的是哪個類別時就會加以檢查(例如雜貨掃描應用程式只接受 EAN13)。
對於篩選而言最重要的兩個欄位是 rotation 與 quality。rotation 是條碼在影像平面內的角度,以弧度表示:解碼器能應付任意旋轉,但若下游程式想乾淨地顯示偵測結果,可能會想濾除傾斜超過某個閾值的碼。
quality 是解碼計數:成功解碼出相同酬載的掃描線數量。解碼器會掃過影格中與條碼相交的每一列(與每一行),每當解碼成功就將計數器加一。對焦清晰、光線良好的印製條碼,其 quality 可達數十;而部分遮擋或污損的條碼可能只在一兩條掃描線上解碼成功,回報 quality 為 1 -- 2。濾除 quality > 5 以下的偵測結果,能在不影響真正偵測的前提下丟棄短暫出現的單一掃描線誤解碼。
一維條碼應用程式很精簡。擷取一張影格、呼叫 find_barcodes()、走訪回傳的清單、依 c.type 與 c.quality 篩選,再將 c.payload 透過 UART 或 USB 轉送給負責記錄或結帳掃描的下游階段。
5.29.2. Data Matrix¶
Data Matrix 碼是一種二維符號,會像 QR 碼那樣將其酬載編碼為黑白儲存格構成的網格。它在兩個實務面向上與 QR 碼不同:在相同酬載大小下它 更小(編碼更密),且它針對 工業 用途而非消費性用途(QR 碼在後者佔主導地位)。雷射蝕刻在工廠車間金屬零件上的圖樣、印製在積體電路封裝上的標籤、放置在醫用注射器上的標記 -- 這些通常都是 Data Matrix,而非 QR 碼。
find_datamatrices() 會在影格中掃描 Data Matrix 碼,並回傳一份 DataMatrix 結果物件清單:
codes = img.find_datamatrices()
for c in codes:
img.draw_rectangle(c.rect, color=(0, 255, 0))
print(c.payload, c.rows, c.columns)
roi 以慣常的方式限制搜尋範圍。唯一專屬於此解碼器的調整旋鈕是 effort,這是一個整數,用以控制解碼器為了找到匹配而付出多大的努力。較高的值能改善對微弱、受損或斜置碼的偵測,但代價是影格率;較低的值執行較快,但可能漏掉較高 effort 本可找到的碼。低於約 160 的值實際上會無法偵測;高於約 240 的值則報酬遞減。預設值 200 對清晰影像而言是合理的平衡,而新應用程式的正確起點是以預設值為基準上下加減 20,視目標是乾淨的(較低)或受損的(較高)而定。
每筆偵測都帶有邊界框相關屬性與四個偵測到的角點、解碼後的 payload,以及以弧度表示、位於影像平面內的 rotation。版面中繼資料 描述了解碼器所讀取符號的大小與密度:rows 與 columns 是資料網格的儲存格數量;capacity 是該尺寸符號所能承載的最大酬載字元數;padding 則是其中有多少格位未被使用(capacity - len(payload))。
對於需要驗證蝕刻標記之 格式 而非其內容的應用程式而言,版面欄位很有用。零件追蹤系統可能要求所有標記皆為 12×12 碼且至多兩個填充字元;若某筆偵測結果回傳為 8×8(比規格要求更小的符號)或帶有 10 個填充字元(大多為空),即會被標記為需重新標記。
5.29.3. 何時該選哪一種¶
QR 與 AprilTag 之間的取捨歸結於 酬載種類(任意資料相對於小型 ID),而條碼與 Data Matrix 碼之間的取捨則歸結於 物理密度 與 產業。
當應用程式面向消費者,且這些碼早已存在於現場 -- 雜貨、書籍、貨運標籤、圖書館書籍 -- 正確的偵測器是 find_barcodes()。應用程式所讀取的碼是為了讓另一個系統讀取而印製的,而標準化的零售符號體系正是該系統所預期的。
當應用程式屬於工業用途,且這些碼是 為了該應用程式而被印製的 -- 工廠車間的庫存追蹤、蝕刻在零件上的批號、醫療器材上的可追溯性標記 -- 正確的偵測器是 find_datamatrices() 或 find_qrcodes(),取決於應用程式需要的是 Data Matrix 較高的密度,還是 QR 較廣泛的工具支援。
少數應用程式會在單一流程中混用全部四種偵測器。包裹檢測相機可能會在同一張擷取的影格上,執行一次 find_barcodes() 處理以讀取印製的 UPC、一次 find_qrcodes() 處理以讀取同一個箱子上的貨運 QR 碼,以及一次 find_datamatrices() 處理以讀取蝕刻的零件碼;這三份結果清單會依邊界框位置加以關聯,並回報為單一筆偵測記錄。每個偵測器的成本會累加,因此這麼做的應用程式通常會以適當的 roi 縮小每次處理的範圍,而非為每種碼都搜尋整張影格。