實操教程|基于OpenCV的條形碼區(qū)域分割

極市導讀
?本文在Anaconda中采用Python 2.7 完成從圖像中提取出含有條形碼的區(qū)域。?>>加入極市CV技術交流群,走在計算機視覺的最前沿

我們將一起學習如何從圖像中提取出含有條形碼的區(qū)域。下面的代碼,我們將在Anaconda中采用Python 2.7 完成,當然OpenCV中的圖像處理庫也是必不可少的。
分割是識別圖像內一個或多個對象的位置的過程。我們要介紹的技術其實非常簡單,它利用了形態(tài)算子的擴張和侵蝕,以及諸如開運算,閉運算和黑帽算子的組合。
簡介
安裝Anaconda后,讓我們從Anaconda的提示符下使用以下命令轉到OpenCV安裝:conda install -c https://conda.anaconda.org/menpo opencv現在,讓我們從Anaconda啟動器啟動Spyder IDE。

Anaconda啟動器一旦運行了Spyder,建議驗證OpenCV安裝是否成功。在Python控制臺的右下角,我們進行以下測試:
import?cv2
代碼講解
我們已經創(chuàng)建了一個啟動GitHub存儲庫。小伙伴可以使用以下方法直接克隆它:
git?clone?--branch?step1
https://github.com/lucapiccinelli/BarcodesTutorial.git
現在,我們將要下載測試圖像,并對他們進行讀取和顯示。

import?cv2
import?matplotlib.pyplot?as?plt
im?=?cv2.imread(r’img\barcodes.jpg’,?cv2.IMREAD_GRAYSCALE)
plt.imshow(im,?cmap=’Greys_r’)
接下來,我們將對圖像進行二值化處理,這樣可以通過閾值的設定來提取出我們感興趣的部分。使用黑帽運算符,我們可以增加較暗的圖像元素。我們可以首先使用簡單的全局閾值安全地對圖像進行二值化處理。黑帽運算符使我們可以使用非常低的閾值,而不必過多地關注噪聲。
在應用blackhat時,我們使用的內核會更加重視垂直圖像元素。內核具有固定的大小,因此可以縮放圖像,這也可以提高性能(并支持某種輸入歸一化)。

黑帽+閾值處理它遵循其他形態(tài)運算符的采用,順序地將它們組合在一起以獲得條形碼位置中的連接組件。
#riscalatura?dell'immagine
scale?=?800.0?/?im.shape[1]
im?=?cv2.resize(im,?(int(im.shape[1]?*?scale),?int(im.shape[0]?*?scale)))
#blackhat
kernel?=?np.ones((1,?3),?np.uint8)
im?=?cv2.morphologyEx(im,?cv2.MORPH_BLACKHAT,?kernel,?anchor=(1,?0))
#sogliatura
thresh,?im?=?cv2.threshold(im,?10,?255,?cv2.THRESH_BINARY)
膨脹和閉合的這種組合在測試圖像上效果很好,但可能無法在其他圖像上達到相同的效果。這沒有關系,大家可以嘗試改變參數和運算符的組合,直到對結果滿意為止。

膨脹+閉運算最后的預處理步驟是應用具有很大內核的開運算符,以刪除太少而無法適合條形碼形狀的元素。
kernel = np.ones((21, 35), np.uint8)
im = cv2.morphologyEx(im, cv2.MORPH_OPEN, kernel, iterations=1)
這是我們希望得到的最終結果:

使用35x21內核打開現在,我們可以運行連接的組件的檢測算法,并檢索帶有坐標和尺寸的條形碼矩形。如大家在上一張圖像中所看到的那樣,最后的形態(tài)學步驟并未濾除全部的噪聲。但是,在這種情況下,將它們過濾掉非常簡單,以矩形區(qū)域值作為閾值就可以了。
#rilettura?dell'immagine,?stavolta?a?colori
im_out?=?cv2.imread(r'img\barcodes.jpg')
#estrazione?dei?componenti?connessi
contours,?hierarchy?=?cv2.findContours(im,?cv2.RETR_EXTERNAL,?cv2.CHAIN_APPROX_NONE)
unscale?=?1.0?/?scale
if?contours?!=?None:
????for?contour?in?contours:
????????
????????#?se?l'area?non?è?grande?a?sufficienza?la?salto?
????????if?cv2.contourArea(contour)?<=?2000:
????????????continue
????????
????????#estraggo?il?rettangolo?di?area?minima?(in?formato?(centro_x,?centro_y),?(width,?height),?angolo)
????????rect?=?cv2.minAreaRect(contour)
????????#l'effetto?della?riscalatura?iniziale?deve?essere?eliminato?dalle?coordinate?rilevate
????????rect?=?\
????????????((int(rect[0][0]?*?unscale),?int(rect[0][1]?*?unscale)),?\
?????????????(int(rect[1][0]?*?unscale),?int(rect[1][1]?*?unscale)),?\
?????????????rect[2])
????????
????????#disegno?il?tutto?sull'immagine?originale
????????box?=?np.int0(cv2.cv.BoxPoints(rect))
????????cv2.drawContours(im_out,?[box],?0,?(0,?255,?0),?thickness?=?2)
????????
plt.imshow(im_out)
#scrittura?dell'?immagine?finale
cv2.imwrite(r'img\out.png',?im_out)
最后,在上面的代碼中,我使用提取的矩形繪制它們,并將其覆蓋在原始圖像上。

最終結果,條形碼以綠色框突出顯示。
結論
提出的技術非常簡單有效,但存在一些缺點:
它對條形碼偏斜非常敏感;它可以很好地工作到大約45度,然后必須執(zhí)行第二遍,修改內核的方向。 它只能在固定尺寸范圍內找到條形碼。 盡管對矩形區(qū)域施加了過濾,但仍有可能無法清除某些非條形碼。第一個和第二個可能不是真正的問題,但是最后一個可能會花費大家大量時間來嘗試解碼非條形碼的內容。一個很好的解決方案是將條形碼特征(圖像梯度,傅立葉變換)輸入給神經網絡(或一些其他一些分類器),并在第二時刻過濾掉噪聲。下面給出完整的示例代碼。
import?cv2
import?matplotlib.pyplot?as?plt
import?numpy?as?np
im?=?cv2.imread(r'img\barcodes.jpg',?cv2.IMREAD_GRAYSCALE)
im_out?=?cv2.imread(r'img\barcodes.jpg')
#riscalatura?dell'immagine
scale?=?800.0?/?im.shape[1]
im?=?cv2.resize(im,?(int(im.shape[1]?*?scale),?int(im.shape[0]?*?scale)))
#blackhat
kernel?=?np.ones((1,?3),?np.uint8)
im?=?cv2.morphologyEx(im,?cv2.MORPH_BLACKHAT,?kernel,?anchor=(1,?0))
#sogliatura
thresh,?im?=?cv2.threshold(im,?10,?255,?cv2.THRESH_BINARY)
#operazioni??morfologiche
kernel?=?np.ones((1,?5),?np.uint8)
im?=?cv2.morphologyEx(im,?cv2.MORPH_DILATE,?kernel,?anchor=(2,?0),?iterations=2)?#dilatazione
im?=?cv2.morphologyEx(im,?cv2.MORPH_CLOSE,?kernel,?anchor=(2,?0),?iterations=2)??#chiusura
kernel?=?np.ones((21,?35),?np.uint8)
im?=?cv2.morphologyEx(im,?cv2.MORPH_OPEN,?kernel,?iterations=1)
#estrazione?dei?componenti?connessi
contours,?hierarchy?=?cv2.findContours(im,?cv2.RETR_EXTERNAL,?cv2.CHAIN_APPROX_NONE)
unscale?=?1.0?/?scale
if?contours?!=?None:
????for?contour?in?contours:
????????
????????#?se?l'area?non?è?grande?a?sufficienza?la?salto?
????????if?cv2.contourArea(contour)?<=?2000:
????????????continue
????????
????????#estraggo?il?rettangolo?di?area?minima?(in?formato?(centro_x,?centro_y),?(width,?height),?angolo)
????????rect?=?cv2.minAreaRect(contour)
????????#l'effetto?della?riscalatura?iniziale?deve?essere?eliminato?dalle?coordinate?rilevate
????????rect?=?\
????????????((int(rect[0][0]?*?unscale),?int(rect[0][1]?*?unscale)),?\
?????????????(int(rect[1][0]?*?unscale),?int(rect[1][1]?*?unscale)),?\
?????????????rect[2])
????????
????????
????????#disegno?il?tutto?sull'immagine?originale
????????box?=?np.int0(cv2.cv.BoxPoints(rect))
????????cv2.drawContours(im_out,?[box],?0,?(0,?255,?0),?thickness?=?2)
????????
plt.imshow(im_out)
#scrittura?dell'?immagine?finale
cv2.imwrite(r'img\out.png',?im_out)
如果覺得有用,就請分享到朋友圈吧!
公眾號后臺回復“數據集”獲取深度學習數據集分類下載~

#?CV技術社群邀請函?#

備注:姓名-學校/公司-研究方向-城市(如:小極-北大-目標檢測-深圳)
即可申請加入極市目標檢測/圖像分割/工業(yè)檢測/人臉/醫(yī)學影像/3D/SLAM/自動駕駛/超分辨率/姿態(tài)估計/ReID/GAN/圖像增強/OCR/視頻理解等技術交流群
每月大咖直播分享、真實項目需求對接、求職內推、算法競賽、干貨資訊匯總、與?10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發(fā)者互動交流~

