利用python識別圖片中的條碼(pyzbar)及條碼圖片矯正和增強

2020-11-13 12:01:25

利用python識別圖片中的條碼(pyzbar)

前言

這周和大家分享如何用python識別影象裡的條碼。用到的庫可以是zbar。希望西瓜6辛苦碼的程式碼不要被盜了。(zxing的話,我一直沒有裝好,等裝好之後再寫一篇)

具體步驟

前期準備

用opencv去讀取圖片,用pip進行安裝。

pip install opencv-python

所用到的圖片就是這個
西瓜6的barcode

使用pyzbar

windows的安裝方法是

pip install pyzbar

而mac的話,最好用brew來安裝。
(有可能直接就好,也有可能很麻煩)
裝好之後就是讀取圖片,識別條碼。
程式碼如下

import cv2
import pyzbar.pyzbar as pyzbar

image=cv2.imread("/Users/phoenix/Downloads/barcode.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
texts = pyzbar.decode(gray)
for text in texts:
    tt = text.data.decode("utf-8")
print(tt)

結果如圖:
在這裡插入圖片描述

特殊情況處理(條碼圖片矯正和增強)

只以pyzbar舉例

條碼是顛倒的是否會影響識別?

不影響,單純顛倒180度和90度是不會影響識別的。
我們把上一個圖的顛倒180度,用顛倒後的圖試一下
barcode_180

import cv2
import pyzbar.pyzbar as pyzbar
import numpy as np

image=cv2.imread("/Users/phoenix/Downloads/barcode_180.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
texts = pyzbar.decode(gray)
print(texts)
if texts==[]:
    print("未識別成功")
else:
    for text in texts:
        tt = text.data.decode("utf-8")
    print("識別成功")
    print(tt)

結果如圖
在這裡插入圖片描述
90度的話也是同樣可以成功的。但是其它角度就會GG。

條碼是傾斜的是否會影響識別?

會的,但這種還比較好處理。
如圖
在這裡插入圖片描述
這張圖用上面的程式碼就會
在這裡插入圖片描述
解決的思路是把這個圖片旋轉回來,至於如何判斷轉多少度,可以通過opencv來處理。通過膨脹和腐蝕將其變為如圖。
在這裡插入圖片描述
接著再用cv2.minAreaRect函數,這個函數會返回如下,
在這裡插入圖片描述
裡面的第三個-45就是我們需要的角度。

綜合起來的實現程式碼,我就放在下面了。(我自己寫的,如果有幫到你,快點關注和贊)

import cv2
import pyzbar.pyzbar as pyzbar
import numpy as np

def barcode(gray):
    texts = pyzbar.decode(gray)
    if texts == []:
        angle = barcode_angle(gray)
        if angle < -45:
            angle = -90 - angle
        texts = bar(gray, angle)
    if texts == []:
        gray = np.uint8(np.clip((1.1 * gray + 10), 0, 255))
        angle = barcode_angle(gray)
        #西瓜6寫的,轉載需宣告
        if angle < -45:
            angle = -90 - angle
        texts = bar(gray, angle)
    return texts

def bar(image, angle):
    gray = image
    #西瓜6寫的,轉載需宣告
    bar = rotate_bound(gray, 0 - angle)
    roi = cv2.cvtColor(bar, cv2.COLOR_BGR2RGB)
    texts = pyzbar.decode(roi)
    return texts


def barcode_angle(image):
    gray = image
    #西瓜6寫的,轉載需宣告
    ret, binary = cv2.threshold(gray, 220, 255, cv2.THRESH_BINARY_INV)
    kernel = np.ones((8, 8), np.uint8)
    dilation = cv2.dilate(binary, kernel, iterations=1)
    erosion = cv2.erode(dilation, kernel, iterations=1)
    erosion = cv2.erode(erosion, kernel, iterations=1)
    erosion = cv2.erode(erosion, kernel, iterations=1)
    
    contours, hierarchy = cv2.findContours(
        erosion, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    if len(contours) == 0:
        rect = [0, 0, 0]
    else:
        rect = cv2.minAreaRect(contours[0])
    return rect[2]

def rotate_bound(image, angle):
    (h, w) = image.shape[:2]
    (cX, cY) = (w // 2, h // 2)

    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    #西瓜6寫的,轉載需宣告
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))

    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY

    return cv2.warpAffine(image, M, (nW, nH))

image=cv2.imread("/Users/phoenix/Downloads/barcode_455.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
texts = barcode(gray)
print(texts)
if texts==[]:
    print("未識別成功")
else:
    for text in texts:
        tt = text.data.decode("utf-8")
    print("識別成功")
    print(tt)

條碼是模糊的是否會影響識別?

會的,處理方法就是傳統的調對比度,銳化。。。。
不過這個只能解決部分部分,至於有的條碼,微信可以掃,支付寶可以掃,但是我們識別不了,這個也不能怪庫不好,這部分該放棄就放棄吧。

結束語

如果你想用python來解決影象裡的條碼識別問題,這篇文章肯定是可以幫到你的。有不懂的,可以評論出來,我每天都會看,看到也就會回覆。所以麻煩關注,點贊加評論咯。
西瓜6的啦啦啦