當前位置:
首頁 > 知識 > 用 Python 和 OpenCV 檢測圖片上的條形碼

用 Python 和 OpenCV 檢測圖片上的條形碼

(點擊

上方公眾號

,可快速關注)





編譯:伯樂在線 - Halal,英文:Adrian Rosebrock   


http://blog.jobbole.com/80448/




更新:

這篇文章的介紹看起來有點「離題」,某些方面是因為在寫文章之前,我剛看完《南方公園黑色星期五》,所以我肯定在殭屍購物者、黑色星期五的混亂和《權利的遊戲》中得到一些靈感。




黑色星期五要來了。




瘋狂的消費者成群結隊,中西部的中年女性蜂擁而出,露出沒有牙齒的嗜血牙齦,直奔當地沃爾瑪75%折扣的最新一季的《權利的遊戲》。




感恩節之夜,他們將在沃爾瑪門外排起長隊,團結在一起,用他們的雙手和頭部,擊打緊鎖的大門,直到身體鮮血淋淋,就像《驚變28天》中的殭屍一樣,只不過不是為了肉身,他們渴望小小的消費寄託,他們的戰爭吶喊著折扣,銷售額將會上升到極點,他們雷鳴般的腳步造成整個大平原的地震。


當然,媒體也無濟於事,他們將危言聳聽每一個小場景。從凍傷的家庭在寒風中露營整晚,到瞞姍老太在大門打開後被蜂擁而入的低價搶購人群踩踏,就像侏羅紀公園中似雞龍的蹂躪。這所有的一切只是因為她想為9歲的孫女蒂米買到最新的光暈遊戲,而蒂米的父母,在去年的這個時候離世了,就在沃爾瑪,在這黑色星期五。



我不得不問,所有的這些混亂值得么?


見鬼,當然不。


我在這個黑色星期五時的購物都是在網上完成的,就像用一杯咖啡和少量泰諾(Tylenol)護理宿醉一樣。


但是如果你決定外出到現實世界勇敢地低價搶購,

你會想先下載本文附帶的源碼。


想像一下你會覺得多麼愚蠢,排隊,等待結賬,只是為了掃描一下最新一季的《權利的遊戲》上的條形碼,然後查明它便宜了 5 美元。


接下來,我將展示給你怎樣僅僅通過Python和Opencv,來檢測圖片中的條形碼。

用 Python 和 OpenCV 檢測圖片上的的條形碼


這篇博文的目的是應用計算機視覺和圖像處理技術,展示一個條形碼檢測的基本實現。我所實現的演算法本質上基於

StackOverflow 上的這個問題

,瀏覽代碼之後,我提供了一些對原始演算法的更新和改進。


首先需要留意的是,這個演算法並不是對所有條形碼有效,但會給你基本的關於應用什麼類型的技術的直覺。


假設我們要檢測下圖中的條形碼:



圖1:包含條形碼的示例圖片


現在讓我們開始寫點代碼,新建一個文件,命名為detect_barcode.py,打開並編碼:




1

# import the necessary packages


2

import

numpy

as

np


3

import

argparse


4

import

cv2


5


6

# construct the argument parse and parse the arguments


7

ap

=

argparse

.

ArgumentParser

()


8

ap

.

add_argument

(

"-i"

,

"--image"

,

required

=

True

,

help

=

"path to the image file"

)


9

args

=

vars

(

ap

.

parse_args

())




我們首先做的是導入所需的軟體包,我們將使用NumPy做數值計算,argparse用來解析命令行參數,cv2是OpenCV的綁定。


然後我們設置命令行參數,我們這裡需要一個簡單的選擇,–image是指包含條形碼的待檢測圖像文件的路徑。


現在開始真正的圖像處理:



11

# load the image and convert it to grayscale


12

image

=

cv2

.

imread

(

args

[

"image"

])


13

gray

=

cv2

.

cvtColor

(

image

,

cv2

.

COLOR_BGR2GRAY

)


14


15

# compute the Scharr gradient magnitude representation of the images


16

# in both the x and y direction


17

gradX

=

cv2

.

Sobel

(

gray

,

ddepth

=

cv2

.

cv

.

CV_32F

,

dx

=

1

,

dy

=

0

,

ksize

= -

1

)


18

gradY

=

cv2

.

Sobel

(

gray

,

ddepth

=

cv2

.

cv

.

CV_32F

,

dx

=

0

,

dy

=

1

,

ksize

= -

1

)


19


20

# subtract the y-gradient from the x-gradient


21

gradient

=

cv2

.

subtract

(

gradX

,

gradY

)


22

gradient

=

cv2

.

convertScaleAbs

(

gradient

)




12~13行:從磁碟載入圖像並轉換為灰度圖。


17~18行:使用Scharr操作(指定使用ksize = -1)構造灰度圖在水平和豎直方向上的梯度幅值表示。


21~22行:Scharr操作之後,我們從x-gradient中減去y-gradient,通過這一步減法操作,最終得到包含高水平梯度和低豎直梯度的圖像區域。


上面的gradient表示的原始圖像看起來是這樣的:



圖:2:條形碼圖像的梯度表示


注意條形碼區域是怎樣通過梯度操作檢測出來的。

下一步將通過去噪僅關注條形碼區域。



24

# blur and threshold the image


25

blurred

=

cv2

.

blur

(

gradient

,

(

9

,

9

))


26

(

_

,

thresh

)

=

cv2

.

threshold

(

blurred

,

225

,

255

,

cv2

.

THRESH_BINARY

)





25行:我們要做的第一件事是使用9*9的內核對梯度圖進行平均模糊,這將有助於平滑梯度表徵的圖形中的高頻雜訊。


26行:然後我們將模糊化後的圖形進行二值化,梯度圖中任何小於等於255的像素設為0(黑色),其餘設為255(白色)。


模糊並二值化後的輸出看起來是這個樣子:



圖3:二值化梯度圖以此獲得長方形條形碼區域的粗略近似


然而,如你所見,在上面的二值化圖像中,條形碼的豎杠之間存在縫隙,為了消除這些縫隙,並使我們的演算法更容易檢測到條形碼中的「斑點」狀區域,我們需要進行一些基本的形態學操作:



28

# construct a closing kernel and apply it to the thresholded image


29

kernel

=

cv2

.

getStructuringElement

(

cv2

.

MORPH_RECT

,

(

21

,

7

))


30

closed

=

cv2

.

morphologyEx

(

thresh

,

cv2

.

MORPH_CLOSE

,

kernel

)





29行:我們首先使用cv2.getStructuringElement構造一個長方形內核。這個內核的寬度大於長度,因此我們可以消除條形碼中垂直條之間的縫隙。


30行:這裡進行形態學操作,將上一步得到的內核應用到我們的二值圖中,以此來消除豎杠間的縫隙。


現在,你可以看到這些縫隙相比上面的二值化圖像基本已經消除:



圖4:使用形態學中的閉運算消除條形碼豎條之間的縫隙


當然,現在圖像中還有一些小斑點,不屬於真正條形碼的一部分,但是可能影響我們的輪廓檢測。


讓我們來消除這些小斑點:



32

# perform a series of erosions and dilations


33

closed

=

cv2

.

erode

(

closed

,

None

,

iterations

=

4

)


34

closed

=

cv2

.

dilate

(

closed

,

None

,

iterations

=

4

)





我們這裡所做的是首先進行4次腐蝕(erosion),然後進行4次膨脹(dilation)。腐蝕操作將會腐蝕圖像中白色像素,以此來消除小斑點,而膨脹操作將使剩餘的白色像素擴張並重新增長回去。


如果小斑點在腐蝕操作中被移除,那麼在膨脹操作中就不會再出現。


經過我們這一系列的腐蝕和膨脹操作,可以看到我們已經成功地移除小斑點並得到條形碼區域。



圖5:應用一系列的腐蝕和膨脹來移除不相關的小斑點


最後,讓我們找到圖像中條形碼的輪廓:



36

# find the contours in the thresholded image, then sort the contours


37

# by their area, keeping only the largest one


38

(

cnts

,

_

)

=

cv2

.

findContours

(

closed

.

copy

(),

cv2

.

RETR_EXTERNAL

,


39

cv2

.

CHAIN_APPROX_SIMPLE

)


40

c

=

sorted

(

cnts

,

key

=

cv2

.

contourArea

,

reverse

=

True

)[

0

]


41


42

# compute the rotated bounding box of the largest contour


43

rect

=

cv2

.

minAreaRect

(

c

)


44

box

=

np

.

int0

(

cv2

.

cv

.

BoxPoints

(

rect

))


45


46

# draw a bounding box arounded the detected barcode and display the


47

# image


48

cv2

.

drawContours

(

image

,

[

box

],

-

1

,

(

0

,

255

,

0

),

3

)


49

cv2

.

imshow

(

"Image"

,

image

)


50

cv2

.

waitKey

(

0

)



38~40行:幸運的是這一部分比較容易,我們簡單地找到圖像中的最大輪廓,如果我們正確完成了圖像處理步驟,這裡應該對應於條形碼區域。




43~44行:然後我們為最大輪廓確定最小邊框




48~50行:最後顯示檢測到的條形碼


正如你在下面的圖片中所見,我們已經成功檢測到了條形碼:



圖6:成功檢測到示例圖像中的條形碼


下一部分,我們將嘗試更多圖像。


成功的條形碼檢測


要跟隨這些結果,請使用文章下面的表單去下載本文的源碼以及隨帶的圖片。


一旦有了代碼和圖像,打開一個終端來執行下面的命令:



$

python

detect_barcode

.

py

--

image

images

/

barcode_02

.

jpg






圖7:使用OpenCV檢測圖像中的一個條形碼


檢測椰油瓶子上的條形碼沒有問題。


讓我們試下另外一張圖片:



$ python detect_barcode.py --image images/barcode_03.jpg







圖8:使用計算機視覺檢測圖像中的一個條形碼


我們同樣能夠在上面的圖片中找到條形碼。


關於食品的條形碼檢測已經足夠了,書本上的條形碼怎麼樣呢:



$

python

detect_barcode

.

py

--

image

images

/

barcode_04

.

jpg







圖9:使用Python和OpenCV檢測書本上的條形碼


沒問題,再次通過。


那包裹上的跟蹤碼呢?



$

python

detect_barcode

.

py

--

image

images

/

barcode_05

.

jpg







圖10:使用計算機視覺和圖像處理檢測包裹上的條形碼


我們的演算法再次成功檢測到條形碼。


最後,我們再嘗試一張圖片,這個是我最愛的義大利面醬—饒氏自制伏特加醬(Rao』s Homemade Vodka Sauce):



$

python

detect_barcode

.

py

--

image

images

/

barcode_06

.

jpg







圖11:使用Python和Opencv很容易檢測條形碼


我們的演算法又一次檢測到條形碼!


總結


這篇博文中,我們回顧了使用計算機視覺技術檢測圖像中條形碼的必要步驟,使用Python編程語言和OpenCV庫實現了我們的演算法。


演算法概要如下:




  1. 計算x方向和y方向上的Scharr梯度幅值表示



  2. 將x-gradient減去y-gradient來顯示條形碼區域



  3. 模糊並二值化圖像



  4. 對二值化圖像應用閉運算內核



  5. 進行系列的腐蝕、膨脹



  6. 找到圖像中的最大輪廓,大概便是條形碼


需要注意的是,該方法做了關於圖像梯度表示的假設,因此只對水平條形碼有效。


如果你想實現一個更加魯棒的條形碼檢測演算法,你需要考慮圖像的方向,或者更好的,應用機器學習技術如Haar級聯或者HOG + Linear SVM去掃描圖像條形碼區域。


源碼下載:

http://pan.baidu.com/s/1jGMfcBs




看完本文有收穫?請轉

發分享給更多人


關注「P

ython開發者」,提升Python技能


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發者 的精彩文章:

TAG:Python開發者 |