使用Python和OpenCV检测图像中的条形码
生活随笔
收集整理的這篇文章主要介紹了
使用Python和OpenCV检测图像中的条形码
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
使用Python和OpenCV檢測圖像中的條形碼
- 1. 效果圖
- 2. 算法的步驟
- 3. 源碼
- 參考
這篇博客將介紹使用計(jì)算機(jī)視覺和圖像處理技術(shù)進(jìn)行條形碼檢測的必要步驟,并演示使用Python編程語言和OpenCV庫實(shí)現(xiàn)檢測算法及其檢測效果。
1. 效果圖
原圖
灰度圖 VS 梯度漸變圖
x梯度減y梯度,梯度漸變獲取定位條形碼大致區(qū)域;
高斯模糊圖 VS 閾值化圖
高斯模糊去掉高頻噪音的干擾;
閾值化圖使得圖像的黑白區(qū)域更加明顯。閾值的值的設(shè)置很重要。該方法應(yīng)用的是大于225的直接為255白色,不大于255的為0,黑色
閉合核圖 VS 腐蝕膨脹圖
閉合核作用:使得條形碼之間的細(xì)線差距更小;
腐蝕膨脹:去掉條形碼周圍的小斑點(diǎn)的干擾,要么消亡,要么生長成為條形碼區(qū)域;
最終效果圖:
2. 算法的步驟
該算法的步驟是:
- 計(jì)算x和y方向上的Scharr梯度幅度表示。
- 從x梯度中減去y梯度以顯示條形碼區(qū)域。
- 模糊和閾值圖像。
- 將封閉內(nèi)核應(yīng)用于閾值圖像。
- 執(zhí)行一系列的膨脹和腐蝕。
- 找到圖像中最大的輪廓,就是條形碼。
該算法并不適用于所有條形碼。注意,由于此方法對圖像的漸變表示進(jìn)行了假設(shè),因此僅適用于水平條形碼。
優(yōu)化:
如果要實(shí)施更強(qiáng)大的條形碼檢測算法,則需要考慮圖像的方向,或者更好的方法是應(yīng)用機(jī)器學(xué)習(xí)技術(shù)(例如Haar級聯(lián)或HOG +線性SVM)“掃描”圖像以進(jìn)行條形碼區(qū)域掃描。
3. 源碼
# USAGE
# python detect_barcode.py --image images/barcode_02.jpgimport argparseimport cv2
import imutils
# 導(dǎo)入必要的包
import numpy as np# 構(gòu)建命令行參數(shù)及解析
# --image 包含條形碼的輸入圖像路徑
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"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("origin", image)
cv2.waitKey(0)# 使用Scharr運(yùn)算符(指定ksize = -1)構(gòu)造水平和垂直方向上灰度圖像的梯度幅度表示。
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)# 用Scharr運(yùn)算符的x梯度中減去Scharr運(yùn)算符的y梯度,剩下的圖像區(qū)域具有較高的水平梯度和較低的垂直梯度。
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)
cv2.imshow("gray VS gradient", np.hstack([gray, gradient]))
cv2.waitKey(0)# 以上可得到條碼圖像的梯度表示
# 請注意,漸變操作是如何檢測圖像的條形碼區(qū)域的。下一步將濾除圖像中的噪點(diǎn),并僅關(guān)注條形碼區(qū)域。
# 高斯平滑以及閾值化圖像
# 使用9 x 9內(nèi)核將平均模糊應(yīng)用于漸變圖像,用以消除圖像梯度表示的高頻噪聲。
blurred = cv2.blur(gradient, (9, 9))
# 對模糊圖像進(jìn)行閾值處理。漸變圖像中任何不大于225的像素都將設(shè)為0(黑色)。否則,像素設(shè)置為255(白色)。
(_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
cv2.imshow("blurred VS thresh", np.hstack([blurred, thresh]))
cv2.waitKey(0)# 條形碼的豎線之間存在間隙。為了彌合這些差距,并使算法更容易檢測條形碼的“斑點(diǎn)”狀區(qū)域,我們需要執(zhí)行一些基本的形態(tài)學(xué)操作:
# 構(gòu)造一個閉合核并將其應(yīng)用于閾值圖像
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)# 執(zhí)行完成后,縫隙實(shí)際上更加封閉:
# 圖像中出現(xiàn)了小的斑點(diǎn),這些斑點(diǎn)不是實(shí)際條形碼的一部分,但可能會干擾輪廓檢測。
# 繼續(xù)嘗試刪除這些小斑點(diǎn):
# 執(zhí)行4次腐蝕迭代,然后進(jìn)行4次膨脹迭代。腐蝕將“侵蝕”圖像中的白色像素,從而消除小斑點(diǎn),而膨脹將“膨脹”剩余的白色像素并使白色區(qū)域重新生長。
eroded = cv2.erode(closed, None, iterations=4)
dilated = cv2.dilate(eroded, None, iterations=4)
cv2.imshow("closede VS eroded and dilated", np.hstack([closed, dilated]))
cv2.waitKey(0)# 只要在侵蝕過程中去除了小斑點(diǎn),它們就不會在擴(kuò)張過程中重新出現(xiàn)。
# 經(jīng)過一系列侵蝕和膨脹后,可以看到小斑點(diǎn)已被成功去除,并且剩下條形碼區(qū)域:# 在閾值化的圖像中尋找輪廓,輪廓面積排序,只保留最大的一個
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(image, [box], -1, (0, 255, 0), 3)
cv2.imshow("Image", image)
cv2.waitKey(0)
參考
- https://www.pyimagesearch.com/2014/11/24/detecting-barcodes-images-python-opencv/
總結(jié)
以上是生活随笔為你收集整理的使用Python和OpenCV检测图像中的条形码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “气变风凛冽”上一句是什么
- 下一篇: Open3D o3dtut怎么导入才不报