Python+Opencv实现实时的条形码检测
目錄
- 一、場景需求簡介
- 二、算法實(shí)現(xiàn)步驟
- 三、圖片中條形碼檢測代碼實(shí)現(xiàn)
- 四、圖片中條形碼檢測效果展示與分析
- 五、視頻中條形碼檢測代碼實(shí)現(xiàn)
- 六、視頻中條形碼檢測效果展示與分析
- 七、思維擴(kuò)展
- 參考資料
- 注意事項(xiàng)
一、場景需求簡介
??在現(xiàn)實(shí)場景中,我們經(jīng)常會(huì)遇到條形碼,它的主要作用是用來標(biāo)識物體,使得每一個(gè)物體都有唯一的一個(gè)編號,這樣可以極大的提高查找效率等,比較常用的應(yīng)用場景是超市和圖書館等,售貨員通過掃描這些條形碼就可以很快的知道這個(gè)商品的價(jià)格,極大的提高了用戶的購物體驗(yàn)。具體的示例如下所示:
二、算法實(shí)現(xiàn)步驟
- 步驟1-讀取圖片并將其轉(zhuǎn)化為灰度圖片,便于后面的處理;
- 步驟2-計(jì)算圖像中x和y方向的Scharr梯度幅值,并利用x方向的梯度值減去y方向的梯度值,對結(jié)果取絕對值操作;
- 步驟3-執(zhí)行高斯模糊并將圖片轉(zhuǎn)化為二值圖片,這樣可以抑制掉大量的噪聲,初略檢測出條形碼所在的區(qū)域;
- 步驟4-構(gòu)建一個(gè)掩碼并將其應(yīng)用在二值圖片中,這樣可以使得二維碼區(qū)域更加完整;
- 步驟5-執(zhí)行多次膨脹和腐蝕操作,這樣可以去除一些空洞和噪聲;
- 步驟6-檢測出圖片中的最大輪廓,這個(gè)輪廓其實(shí)就是我們的目標(biāo);
- 步驟7-計(jì)算該輪廓的最小外界矩形作為最終的輸出結(jié)果,由于該輪廓是一個(gè)不規(guī)則圖像,因而需要執(zhí)行該操作。
三、圖片中條形碼檢測代碼實(shí)現(xiàn)
# coding=utf-8 # 導(dǎo)入python包 import numpy as np import argparse import imutils import cv2# 構(gòu)建并解析參數(shù) ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required = True, help = "path to the image file") args = vars(ap.parse_args())# 讀取圖片并將其轉(zhuǎn)化為灰度圖片 image = cv2.imread(args["image"]) image1 = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 計(jì)算圖像中x和y方向的Scharr梯度幅值表示 ddepth = cv2.cv.CV_32F if imutils.is_cv2() else cv2.CV_32F gradX = cv2.Sobel(gray, ddepth=ddepth, dx=1, dy=0, ksize=-1) gradY = cv2.Sobel(gray, ddepth=ddepth, dx=0, dy=1, ksize=-1)# x方向的梯度減去y方向的梯度 gradient = cv2.subtract(gradX, gradY) # 獲取處理后的絕對值 gradient = cv2.convertScaleAbs(gradient) cv2.imwrite("gradient.png", gradient)# 對處理后的結(jié)果進(jìn)行模糊操作 blurred = cv2.blur(gradient, (9, 9)) # 將其轉(zhuǎn)化為二值圖片 (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY) cv2.imwrite("thresh.png", thresh)# 構(gòu)建一個(gè)掩碼并將其應(yīng)用在二值圖片中 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7)) closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) cv2.imwrite("closed1.png", closed)# 執(zhí)行多次膨脹和腐蝕操作 closed = cv2.erode(closed, None, iterations = 4) closed = cv2.dilate(closed, None, iterations = 4) cv2.imwrite("closed2.png", closed)# 在二值圖像中尋找輪廓, 然后根據(jù)他們的區(qū)域大小對該輪廓進(jìn)行排序,保留最大的一個(gè)輪廓 cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) c = sorted(cnts, key = cv2.contourArea, reverse = True)[0]# 計(jì)算最大的輪廓的最小外接矩形 rect = cv2.minAreaRect(c) box = cv2.cv.BoxPoints(rect) if imutils.is_cv2() else cv2.boxPoints(rect) box = np.int0(box)# 繪制并顯示結(jié)果 cv2.drawContours(image1, [box], -1, (0, 255, 0), 3) result = np.hstack([image, image1]) cv2.imwrite("detect1.png", result) cv2.imshow("Image", result) cv2.waitKey(0)四、圖片中條形碼檢測效果展示與分析
??上圖展示了該算法在圖片中的檢測結(jié)果和中間結(jié)果。第1行第1列表示原始的輸入圖片,對應(yīng)到代碼中的image,該圖片中含有一個(gè)條形碼;第1行第2列表示梯度差的絕對值的效果,對應(yīng)于代碼中的gradient,通過這個(gè)操作,我們可以發(fā)現(xiàn)含有條形碼的區(qū)域比較明顯;第2行第1列表示的是二值化后的結(jié)果,對應(yīng)于代碼中的thresh,通過二值化操作可以去除大量的噪聲,將二維碼的大致位置檢測出來;第2行第2列表示的是應(yīng)用掩模之后的效果圖,對應(yīng)于代碼中的closed,我們可以發(fā)現(xiàn)應(yīng)用了掩模之后的結(jié)果中調(diào)補(bǔ)了條形碼中的大部分空洞;第3行第1列表示的是經(jīng)過膨脹和腐蝕操作之后的結(jié)果,對應(yīng)于代碼中的closed,我們可以發(fā)現(xiàn)多次膨脹和腐蝕操作可以去除掉大量的空洞和噪聲;第3行第2列表示算法最終的檢測結(jié)果,對應(yīng)于代碼中的image1,我們可以發(fā)現(xiàn)該算法準(zhǔn)確的檢測出圖片中的條形碼。
五、視頻中條形碼檢測代碼實(shí)現(xiàn)
# coding=utf-8 # 導(dǎo)入python包 from imutils.video import VideoStream import numpy as np import imutils import argparse import time import cv2# 定義簡單的圖片檢測函數(shù),這個(gè)思路就是單張圖片的檢測思路 def detect(image):gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)ddepth = cv2.cv.CV_32F if imutils.is_cv2() else cv2.CV_32FgradX = cv2.Sobel(gray, ddepth=ddepth, dx=1, dy=0, ksize=-1)gradY = cv2.Sobel(gray, ddepth=ddepth, dx=0, dy=1, ksize=-1)gradient = cv2.subtract(gradX, gradY)gradient = cv2.convertScaleAbs(gradient)blurred = cv2.blur(gradient, (9, 9))(_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)closed = cv2.erode(closed, None, iterations=4)closed = cv2.dilate(closed, None, iterations=4)cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)if len(cnts) == 0:return Nonec = sorted(cnts, key=cv2.contourArea, reverse=True)[0]rect = cv2.minAreaRect(c)box = cv2.cv.BoxPoints(rect) if imutils.is_cv2() else cv2.boxPoints(rect)box = np.int0(box)return box# 構(gòu)建并解析參數(shù) ap = argparse.ArgumentParser() ap.add_argument("-v", "--video", help="path to the (optional) video file") args = vars(ap.parse_args())# 如果視頻不存在則進(jìn)行視頻捕獲 if not args.get("video", False):vs = VideoStream(src=0).start()time.sleep(2.0) # 否則裝載視頻 else:vs = cv2.VideoCapture(args["video"])# 循環(huán)處理每一幀 while True:# 獲取當(dāng)前幀frame = vs.read()frame = frame[1] if args.get("video", False) else frame# 判斷是否達(dá)到視頻的最后一幀if frame is None:break# 進(jìn)行單張圖片檢測box = detect(frame)# 如果發(fā)現(xiàn)了條形碼則繪制結(jié)果if box is not None:cv2.drawContours(frame, [box], -1, (0, 255, 0), 2)# 顯示當(dāng)前幀的結(jié)果cv2.imshow("Frame", frame)key = cv2.waitKey(1) & 0xFF# 當(dāng)用戶按下q鍵時(shí)退出整個(gè)循環(huán)if key == ord("q"):break# 停止視頻捕獲 if not args.get("video", False):vs.stop() # 否則釋放內(nèi)存 else:vs.release()# 關(guān)閉所有的窗口 cv2.destroyAllWindows()六、視頻中條形碼檢測效果展示與分析
??上圖中展示了該算法在視頻上面的檢測結(jié)果,該算法在圖片中的條形碼檢測的基礎(chǔ)上,增加了一些視頻控制的代碼,整個(gè)代碼默認(rèn)會(huì)讀取視頻,當(dāng)用戶沒有設(shè)置讀取的視頻時(shí),該代碼會(huì)調(diào)用電腦上面的攝像頭進(jìn)行視頻捕獲,并實(shí)時(shí)的檢測當(dāng)前幀中是否包含條形碼,如果包含則會(huì)顯示該條形碼,否則不顯示任何東西,整個(gè)捕獲過程會(huì)一直執(zhí)行下去,直到用戶按下鍵盤上面的q鍵為止。通過觀察上圖我們可以發(fā)現(xiàn)該代碼可以實(shí)時(shí)、準(zhǔn)確的檢測到視頻中包含的二維碼。
七、思維擴(kuò)展
??本文僅僅實(shí)現(xiàn)了一個(gè)簡單的圖像條形碼檢測算法,如果你想實(shí)現(xiàn)一個(gè)更強(qiáng)大的條形碼檢測算法,你需要考慮到圖像的方向,嘗試著去應(yīng)用機(jī)器學(xué)習(xí)技術(shù),如haar級聯(lián)或hog+linear svm來“掃描”圖像的條形碼區(qū)域。
??本文實(shí)現(xiàn)的基于視頻的條形碼檢測算法是在兩個(gè)假設(shè)的基礎(chǔ)上設(shè)計(jì)的。第一個(gè)假設(shè)是我們有一個(gè)靜態(tài)攝像頭,它以90度角“向下看”條形碼。這將確保條碼圖像的梯度區(qū)域被我們設(shè)計(jì)的簡單條碼探測器探測到。第二個(gè)假設(shè)是,我們的視頻有條形碼的“特寫”,這意味著我們將智能手機(jī)直接放在條形碼的上方,而不是將條形碼放在遠(yuǎn)離鏡頭的地方。我們把條形碼移離相機(jī)越遠(yuǎn),我們簡單的條形碼檢測器就越不成功。如果你想要設(shè)計(jì)一個(gè)更好的條形碼檢測器,可以去參考博客1和博客2的實(shí)現(xiàn)細(xì)節(jié)。
參考資料
[1] 參考鏈接
注意事項(xiàng)
[1] 該博客是本人原創(chuàng)博客,如果您對該博客感興趣,想要轉(zhuǎn)載該博客,請與我聯(lián)系(qq郵箱:1575262785@qq.com),我會(huì)在第一時(shí)間回復(fù)大家,謝謝大家的關(guān)注.
[2] 由于個(gè)人能力有限,該博客可能存在很多的問題,希望大家能夠提出改進(jìn)意見。
[3] 如果您在閱讀本博客時(shí)遇到不理解的地方,希望您可以聯(lián)系我,我會(huì)及時(shí)的回復(fù)您,和您交流想法和意見,謝謝。
[4] 本文測試的圖片可以通過該鏈接進(jìn)行下載。網(wǎng)盤鏈接- 提取碼:mfa9 。
[5] 本人業(yè)余時(shí)間承接各種本科畢設(shè)設(shè)計(jì)和各種小項(xiàng)目,包括圖像處理(數(shù)據(jù)挖掘、機(jī)器學(xué)習(xí)、深度學(xué)習(xí)等)、matlab仿真、python算法及仿真等,有需要的請加QQ:1575262785詳聊!!!
總結(jié)
以上是生活随笔為你收集整理的Python+Opencv实现实时的条形码检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c盘清理工具哪个好(2022最新版)
- 下一篇: 基于python的HOG+SVM目标检测