python識別復(fù)雜背景下的二維碼

關(guān)于二維碼生成與識別,網(wǎng)上有很多資料,生成是比較容易的python相關(guān)的庫也很多养匈,但是識別才是技術(shù)難度比較高的,這里指的是復(fù)雜背景下的二維碼快速識別都伪;所謂復(fù)雜背景就是說二維碼占畫幅比例很小呕乎、存在扭曲、變形陨晶、模糊猬仁,比如隨手拍的照片上二維碼,這種情況下往往很隨意的角度先誉,給二維碼識別帶來不小困難湿刽。這兩天查了不少資料也對比了很多開源實(shí)現(xiàn),但沒有找到可以媲美微信掃一掃識別效果的方案褐耳,不得不說這種成熟的商用產(chǎn)品即便是一個很小的細(xì)分功能也是下了不少功夫的诈闺。

我也研究了下,這里給出我自己的初步方案漱病。

基于yolov5網(wǎng)絡(luò)的二維碼定位 ===> 二維碼提取 ===> 二維碼矯正===> 二維碼圖像增強(qiáng) ===> pyzbar識別

我面對的場景是像下面這樣的圖片:


貨運(yùn)單.png

這種圖片如果直接用zbar識別的話买雾,不僅耗時(shí)較長而且識別率極低;但是如果直接形態(tài)學(xué)處理干擾又太多杨帽,因此這里先用目標(biāo)檢測網(wǎng)絡(luò)yolov5做定位漓穿。

  • yolo的訓(xùn)練這里就不再贅述了,訓(xùn)練數(shù)據(jù)是從網(wǎng)絡(luò)上找的各種二維碼圖片

識別效果很好幾乎100%注盈,需要訓(xùn)練數(shù)據(jù)或者訓(xùn)練好的代碼及模型的私信聯(lián)系我晃危。以下著重介紹定位后的預(yù)處理。定位并提取后的二維碼如下:


定位并提取后的二維碼
  • 盡管已經(jīng)提取了二維碼老客,但直接用pyzbar識別效果非常差僚饭,識別率不到10%,因此考慮對這些圖像進(jìn)行矯正胧砰。

以下面這張?zhí)崛『蟮亩S碼為例:


image.png

首先將圖像放縮到統(tǒng)一大小鳍鸵,然后識別二維碼邊界,最后進(jìn)行仿射變換矯正圖像尉间,代碼如下:

import cv2
import imutils
from skimage import measure
import numpy as np



image = cv2.imread('image.png')

image = cv2.resize(image, (600, 600))
height, width = image.shape[:2]
#size = (int(width * 0.25), int(height * 0.25))
#shrink = cv2.resize(image, size, interpolation=cv2.INTER_AREA)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imwrite('gray.jpg',gray)

ret2, image_binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
ret, binary = cv2.threshold(gray, ret2 * 0.85, 255, cv2.THRESH_BINARY)

#ret, binary = cv2.threshold(gray, 135, 255, cv2.THRESH_BINARY)
cv2.imwrite('binary.jpg',binary)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (80, 80))
iOpen = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
iClose = cv2.morphologyEx(iOpen, cv2.MORPH_CLOSE, kernel)
cv2.imwrite('iClose.jpg',iClose)
# cv2.imwrite('tempcolse.jpg',iClose)

img = 255 - iClose

cv2.imwrite('img.jpg',img)



def Get_cnt(edged):
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[1] if imutils.is_cv3() else cnts[0]
    docCnt = None
    if len(cnts) > 0:
        cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
        for c in cnts:
            peri = cv2.arcLength(c, True)
            approx = cv2.approxPolyDP(c, 0.02 * peri, True)
            if len(approx) == 4:
                docCnt = approx
                break
    return docCnt


def order_points(pts):
    rect = np.zeros((4, 2), dtype="float32")
    s = pts.sum(axis=1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]

    diff = np.diff(pts, axis=1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect

def four_point_transform(simage, pts,gap=50):
    # print(pts)
    rect = order_points(pts)

    (tl, tr, br, bl) = rect
    tl[0] = tl[0]-gap
    tl[1] = tl[1]-gap

    tr[0] = tr[0]+gap
    tr[1] = tr[1]-gap


    br[0] = br[0]+gap
    br[1] = br[1]+gap

    bl[0] = bl[0]-gap
    bl[1] = bl[1]+gap

    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))  
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))

    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))

    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")

    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    warped = cv2.copyMakeBorder(warped,50,50,50,50, cv2.BORDER_CONSTANT,value=[255,255,255])
    return warped



#69,64   555,551
#sx,sy = _black_edges(img)
#print(sx,sy)

ss = Get_cnt(img)
print(ss)

warped = four_point_transform(image,ss.reshape(4, 2),gap=35)#這個gap閾值控制下仿射變換的余量偿乖,避免有些二維碼變換后識別不出來

cv2.imwrite('warped.jpg',warped)

warped.jpg
  • 接下來击罪,就是對二維碼做增強(qiáng)然后調(diào)用pyzbar做識別:
import pyzbar.pyzbar as pyzbar
from PIL import Image,ImageEnhance
from pyzbar.pyzbar import ZBarSymbol
import qreader





image2 = 'warped.jpg'

img = Image.open(image2)
#img = img.resize((600,600),Image.ANTIALIAS)
img = ImageEnhance.Brightness(img).enhance(2.0)#增加亮度
#
#img = ImageEnhance.Sharpness(img).enhance(1.5)#銳利化
#
#img = ImageEnhance.Contrast(img).enhance(2.0)#增加對比度
#
img = img.convert('L')#灰度化
img.save('cc.png')


barcodes = pyzbar.decode(img)

print(barcodes)
for barcode in barcodes:
    barcodeData = barcode.data.decode("utf-8")
    print(barcodeData)
cc.png

識別結(jié)果如下:
[Decoded(data=b'WMWHSE6:2000041942,', type='QRCODE', rect=Rect(left=73, top=73, width=459, height=453), polygon=[Point(x=73, y=82), Point(x=78, y=526), Point(x=532, y=517), Point(x=521, y=73)])]
WMWHSE6:2000041942,

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市贪薪,隨后出現(xiàn)的幾起案子媳禁,更是在濱河造成了極大的恐慌,老刑警劉巖画切,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件竣稽,死亡現(xiàn)場離奇詭異,居然都是意外死亡霍弹,警方通過查閱死者的電腦和手機(jī)毫别,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來庞萍,“玉大人拧烦,你說我怎么就攤上這事《奂疲” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵齐佳,是天一觀的道長私恬。 經(jīng)常有香客問我,道長炼吴,這世上最難降的妖魔是什么本鸣? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮硅蹦,結(jié)果婚禮上荣德,老公的妹妹穿的比我還像新娘。我一直安慰自己童芹,他們只是感情好涮瞻,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著假褪,像睡著了一般署咽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上生音,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天宁否,我揣著相機(jī)與錄音,去河邊找鬼缀遍。 笑死慕匠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的域醇。 我是一名探鬼主播台谊,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼蓉媳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了青伤?” 一聲冷哼從身側(cè)響起督怜,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤饲趋,失蹤者是張志新(化名)和其女友劉穎荒吏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耸棒,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丰歌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年姨蟋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片立帖。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡眼溶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晓勇,到底是詐尸還是另有隱情堂飞,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布绑咱,位于F島的核電站绰筛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏描融。R本人自食惡果不足惜铝噩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窿克。 院中可真熱鬧骏庸,春花似錦、人聲如沸年叮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谋右。三九已至硬猫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間改执,已是汗流浹背啸蜜。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辈挂,地道東北人衬横。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像终蒂,于是被迫代替她去往敵國和親蜂林。 傳聞我的和親對象是個殘疾皇子遥诉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容