推薦閱讀python
42個pycharm使用技巧,瞬間從黑鐵變王者git
Google C++項目編程風格指南 (中文版) 分享github
概述算法
在平常生活中,常常會看到條形碼的應用,好比超市買東西的生活,圖書館借書的時候。。。編程
那麼這些東西是如何作到準確檢測出條形碼的位置呢?ide
這就是今天要介紹的內容了函數
這篇博文的目標是演示使用計算機視覺和圖像處理技術實現條形碼的檢測。學習
經過本篇文章的學習,咱們能學到的內容包括:測試
一、圖像處理中經常使用的一些操做流程,包括濾波、閾值化處理、膨脹、腐蝕和輪廓查找等ui
二、更重要的一點,但願經過這個案例,可以幫助你們創建分析問題和處理問題的思路
須要注意的是,這個算法並不適用於全部的條形碼,可是它應該能給你一個基本的直覺,告訴你應該應用什麼類型的技術。
條形碼的檢測
對於下面這個例子,咱們將檢測下圖中的條形碼:
目標:找到條形碼的位置,而去除掉干擾的因素
思路:
利用條形碼的自身特色,通常都是矩形形狀,並且條碼的條帶是黑色的,矩形區域是白色的
讓咱們繼續寫一些代碼。打開一個新文件,將其命名爲 detect_barcode.py,如何開始寫代碼:
# 導入必要的包/庫import numpy as npimport argparseimport imutilsimport cv2
# 構造參數解析並分析參數ap = argparse.ArgumentParser()ap.add_argument("-i","--image", required = True, help = "path to the image file")args = vars(ap.parse_args())
咱們首先要作的是導入咱們須要的包。咱們將使用numpy進行數字處理,argparse用於解析命令行參數,cv2進行opencv綁定。
而後咱們將設置命令行參數。咱們這裏只須要一個開關,即 --image,它是咱們圖像的路徑,其中包含咱們想要檢測的條形碼。
如今,讓我進行實際的圖像處理吧 導入圖片並轉化爲灰度圖
image = cv2.imread(args["image"])gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 計算圖片x和y方向的Scharr梯度大小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)
# 用x方向的梯度減去y方向的梯度gradient = cv2.subtract(gradX,gradY)gradient = cv2.convertScaleAbs(gradient)
首先咱們先讀入圖片並將其轉換爲灰度圖;
而後咱們使用Scharr操做符(這裏制定ksize=1)去構造圖片在水平和垂直方向上的梯度幅值表示。
這裏,咱們用Scharr算子的x方向梯度減去y方向的梯度。經過這個相減操做,咱們就只剩下了高水平梯度和低垂直梯度的圖像區域。
咱們上述原始圖像的梯度表示以下圖所示
請注意梯度操做是如何檢測出圖片的條形碼區域的。接下來的步驟是如何過濾掉圖片中的噪聲,重點關注條形碼區域。
# 對圖片進行模糊和閾值化操做blurred = cv2.blur(gradient,(9,9))(_,thresh) = cv2.threshold(blurred, 255, 255, cv2.THRESH_BINARY)
咱們作的第一件事是使用一個卷積核大小爲9x9的均值濾波做用於梯度圖片。對圖片進行這個操做將有助於平滑圖片中的高頻噪聲。
而後我將模糊化後的圖片進行閾值化,在梯度圖片中,全部的像素點的灰度值低於255的將設爲0(黑色),其他設爲255(白色)。
模糊和閾值化處理後的輸出結果以下:
然而,正如你所看到的上圖閾值化圖片,在條形碼的垂直方向上存在這間隙。爲了縮小這些間隙,並使得咱們的算法更加容易的檢測出條形碼的「斑點」狀區域,咱們須要執行一些基礎的形態學操做:
# 構造一個閉合核並應用於閾值圖片kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
咱們經過使用函數cv2.getStructuringElement構造一個矩形核。這個核的寬度大於高度,所以容許咱們縮小條形碼垂直條帶之間的間隙。
固然,如今圖片中非條形碼的區域存在着不少斑點,這將會干擾輪廓的檢測。
如今,咱們繼續嘗試移除這些小的斑點
# 執行一系列的腐蝕和膨脹操做closed = cv2.erode(closed, None, iterations = 4)closed = cv2.dilate(closed, None, iterations = 4)
咱們如今要作的是進行4次腐蝕操做,而後再進行4次膨脹操做。腐蝕操做將會「腐蝕」掉圖片中的白色像素點,所以將會清除這些小的斑點,而膨脹操做將會「擴張」剩餘的白色像素,並使白色區域變長。
若是在腐蝕過程當中去除了小的斑點,則在膨脹的過程當中不會再次出現。
在一系列的腐蝕和膨脹操做以後,這些小斑點已經被成功的移除了,只剩下條形碼的區域。
最後尋找一下圖片中條形碼的區域的輪廓。
# 找到閾值化後圖片中的輪廓,而後進行根據區域進行排序,僅保留最大區域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)
幸運的是,opencv中提供了相應的接口,能夠很容易地找到圖像中的最大輪廓,若是咱們正確地完成了圖像處理步驟,它應該會對應於條形碼區域。
而後,咱們肯定最大輪廓的最小的邊界框,並最後顯示檢測到的條形碼。
正如咱們下圖所示,咱們已經成功的檢測到條形碼
代碼連接:https://github.com/DWCTOD/AI_study/tree/master/%E5%90%88%E6%A0%BC%E7%9A%84CV%E5%B7%A5%E7%A8%8B%E5%B8%88/%E5%AE%9E%E6%88%98%E7%AF%87/opencv/%EF%BC%88%E4%BA%94%EF%BC%89%E7%94%A8python%E5%92%8Copencv%E6%A3%80%E6%B5%8B%E5%9B%BE%E5%83%8F%E4%B8%AD%E7%9A%84%E6%9D%A1%E5%BD%A2%E7%A0%81
使用方法:python3 detect_barcode.py --image images/barcode_01.jpg
另外還提供了其餘的測試圖片
英文原文連接:https://www.pyimagesearch.com/2014/11/24/detecting-barcodes-images-python-opencv/
總結
值得去思考的點
一、爲啥要轉變成灰度圖
二、如何去除干擾因素,特別是條形碼下面的材料說明的區域是採用什麼辦法去除的,小的斑點是如何去除的