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