最近搞了搞條碼識別相關的東西,今天總結一下。
我們常用的條碼識別工具有zxing、zbar等等。zxing的使用比較簡單,一個函數直接調用就可以了,但是目前我發現它只能識別一張圖中的一個條碼,如果你要讀多個條碼那是不行的。這裏貼一下使用方法:
Bitmap code_bmp = roi.ToBitmap();
BarcodeReader reader = new BarcodeReader();
reader.Options.CharacterSet = "UTF-8";
reader.Options.PureBarcode = false;
using (Bitmap bmp = code_bmp)
{
Result result = reader.Decode(bmp);
inf = result.Text.ToString();
}
然後就是zbar,python有pyzbar這個包,親測是比較好用的,它可以同時識別一張圖上的多個條碼,而且還可以給出每個條碼的位置信息。這是我在網上找到的代碼,並且也自己試了一下:
frame = cv2.imread('/test/9.bmp')
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
barcodes = pyzbar.decode(gray)
for barcode in barcodes:
# 提取條形碼的邊界框的位置
# 畫出圖像中條形碼的邊界框
(x, y, w, h) = barcode.rect
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 0), 2)
# 條形碼數據爲字節對象,所以如果我們想在輸出圖像上
# 畫出來,就需要先將它轉換成字符串
barcodeData = barcode.data.decode("utf-8")
# 繪出圖像上條形碼的數據和條形碼類型
barcodeType = barcode.type
# 把cv2格式的圖片轉成PIL格式的圖片然後在上標註二維碼和條形碼的內容
img_PIL = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
font = ImageFont.truetype('STFANGSO.TTF', 25)
# 字體顏色
fillColor = (0, 255, 0)
# 文字輸出位置
position = (x, y - 25)
# 輸出內容
strl = barcodeData
# 需要先把輸出的中文字符轉換成Unicode編碼形式(str.decode("utf-8))
# 創建畫筆
draw = ImageDraw.Draw(img_PIL)
draw.text(position, strl, font=font, fill=fillColor)
# 使用PIL中的save方法保存圖片到本地
img_PIL.save('結果圖.jpg', 'jpeg')
# 向終端打印條形碼數據和條形碼類型
print("掃描結果==》 類別: {0} 內容: {1}".format(barcodeType, barcodeData))
測試了一些圖片,可以同時解析條碼和QR二維碼。但是會出現一些漏檢的情況。
我需要在C#上實現這個功能,去找了相關的庫,而且只能在x86平臺上運行,目前還不知道怎麼搞在x64上,如果有好心的大佬指點一二就好了。爲什麼沒有深究呢?也是因爲我測試之後發現準確率不夠,因此就放棄了。
後來在網上調研了一些條碼定位的方法,在此基礎上我根據自己的需求做了一些修改和優化,目前達到了比較好的效果。下面是用OpenCVSharp實現的源碼:
這個算法的前提是條碼是水平放置的,不能歪斜。因爲我們需要計算圖像在X和Y方向上的梯度。條碼由於它的特徵,在Y方向上的梯度幾乎是0,X方向上幾乎是1,如圖:
因此根據這個性質,我們可以濾掉一些條碼外的信息,得到一個比較好的條碼二值圖。但是在對多種條碼類型進行測試時,我發現很多碼的中間間隔是很稀疏的,因此採用直接二值化再膨脹腐蝕的方法就不太好,不好調參。中間擱置了幾天,有一天突然想着把圖像伸縮一下會不會好點,結果確實很有效。
伸縮之後,這種條碼區域就已經非常的明顯了。接下來是要過濾掉一下其他的信息,由於條碼上下通常就會印有對應的字符,有的格式還好,碼和字隔得很開,用簡單的開運算就可以過濾掉,但是有的就隔得很近,很容易粘連在一起。而且條碼中間始終會有空隙,所以效果不好。後來想到再不同方向上先做膨脹腐蝕,就可以很好的填充條碼中心,並分開字符和條碼了。
這樣初步可以得到以下結果:
最後再做一次後處理。我們能看到條碼基本上是矩形的,我們可以計算它的輪廓以及最小外接矩,通過計算輪廓面積與最小外接矩的面積比,來判斷這個區域是否最接近矩形。
最後就是檢測結果啦~在很多圖像上試驗了表明效果還挺好~
目前該方法只適用於條碼基本水平的情況,我在嘗試使用頻譜圖先檢測出文字方向,把圖片校正之後再識別的方法,後續繼續更新~
如果大佬有更好的方法,希望多多交流哦~
源碼請移步:https://github.com/zhanzhanmiao/BarCode-Location-Recognition