學習OpenCV——對圖像中的多個條形碼進行定位

最近搞了搞條碼識別相關的東西,今天總結一下。

我們常用的條碼識別工具有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

發佈了14 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章