使用python寫的opencv實(shí)時(shí)監(jiān)測(cè)和解析二維碼和條形碼
今天,我實(shí)現(xiàn)了一個(gè)很有趣的demo,它可以在視頻里找到并解析二維碼,然后把解析的內(nèi)容實(shí)時(shí)在屏幕上顯示出來。
然后我們直入主題,首先你得確保你裝了opencv,python,zbar等環(huán)境。然后這個(gè)教程對(duì)于學(xué)過opencv的人可能更好理解,但是沒學(xué)過也無妨,到時(shí)候也可以直接用。
比如我的電腦上的環(huán)境是opencv2.4.x,python2.7,和最新的zbar,在Ubuntu 12.12的系統(tǒng)下運(yùn)行的
假設(shè)你的opencv已經(jīng)安裝好了,那么我們就可以安裝zbar
你可以先更新一下
sudo apt-get update
然后在輸入
sudo apt-get install python-zbar
如果環(huán)境裝好了,我們就可以接著下一步操作了。
首先讓我們來實(shí)現(xiàn)找到在圖片里面找到二維碼的功能
先新建一個(gè)python文件叫做;simple_barcode_detection.py
代碼如下,這定義了一個(gè)函數(shù),實(shí)現(xiàn)從一副圖片里面找出二維碼的位置
我們要檢測(cè)的二維碼的圖片

import numpy as np import cv2 def detect(image): # 把圖像從RGB裝換成灰度圖 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 使用Scharr操作(指定使用ksize = -1)構(gòu)造灰度圖在水平和豎直方向上的梯度幅值表示。 gradX = cv2.Sobel(gray, ddepth = cv2.cv.CV_32F, dx = 1, dy = 0, ksize = -1) gradY = cv2.Sobel(gray, ddepth = cv2.cv.CV_32F, dx = 0, dy = 1, ksize = -1) #Scharr操作后,從x的梯度減去y的梯度 gradient = cv2.subtract(gradX, gradY) gradient = cv2.convertScaleAbs(gradient) #經(jīng)過上面的操作后看起來是這樣

# 對(duì)上述的梯度圖采用用9x9的核進(jìn)行平均模糊,這是有利于降噪的
#然后進(jìn)行二值化處理,要么是255(白)要么是0(黑)
blurred = cv2.blur(gradient, (9, 9)) (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
#模糊與二值化處理后,看起來是這個(gè)樣子,

#上面的操作后發(fā)現(xiàn)有一些條形碼的豎杠之間存在一些縫隙,并使我們的算法能檢測(cè)到斑點(diǎn)區(qū)域,我們進(jìn)行一些基本的形態(tài)學(xué)操作 #我們首先使用cv2.getStructuringElement構(gòu)造一個(gè)長方形內(nèi)核。這個(gè)內(nèi)核的寬度大于長度,因此我們可以消除條形碼中垂直條之間的縫隙。 # 這里進(jìn)行形態(tài)學(xué)操作,將上一步得到的內(nèi)核應(yīng)用到我們的二值圖中,以此來消除豎杠間的縫隙。 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7)) closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) #上述操作后看起來是這個(gè)樣子

#我們發(fā)現(xiàn)還是存在一些小斑點(diǎn),這時(shí)我們可以使用opencv里面的腐蝕和膨脹來處理他們,來去除白色的斑點(diǎn)
closed = cv2.erode(closed, None, iterations = 4) closed = cv2.dilate(closed, None, iterations = 4) #這時(shí)候的效果看起來是這樣的

# 接下來我們來找輪廓 (cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #如果沒找到則返回為空 if len(cnts) == 0: return None #找到了就通過面積來排序,并計(jì)算旋轉(zhuǎn)角 # 給最大的輪廓找到邊框 c = sorted(cnts, key = cv2.contourArea, reverse = True)[0] rect = cv2.minAreaRect(c) #box(里面是ndarry數(shù)組,包含了4個(gè)頂點(diǎn)的位置) box = np.int0(cv2.cv.BoxPoints(rect)) # 返回box return box
最終結(jié)果

好了,上面的解釋里面有中文,可能python解釋的時(shí)候會(huì)通不過,我下面直接給出代碼
import numpy as np import cv2 def detect(image): # convert the image to grayscale gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # compute the Scharr gradient magnitude representation of the images # in both the x and y direction gradX = cv2.Sobel(gray, ddepth = cv2.cv.CV_32F, dx = 1, dy = 0, ksize = -1) gradY = cv2.Sobel(gray, ddepth = cv2.cv.CV_32F, dx = 0, dy = 1, ksize = -1) # subtract the y-gradient from the x-gradient gradient = cv2.subtract(gradX, gradY) gradient = cv2.convertScaleAbs(gradient) # blur and threshold the image blurred = cv2.blur(gradient, (9, 9)) (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY) # construct a closing kernel and apply it to the thresholded image kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7)) closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) # perform a series of erosions and dilations closed = cv2.erode(closed, None, iterations = 4) closed = cv2.dilate(closed, None, iterations = 4) # find the contours in the thresholded image (cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # if no contours were found, return None if len(cnts) == 0: return None # otherwise, sort the contours by area and compute the rotated # bounding box of the largest contour c = sorted(cnts, key = cv2.contourArea, reverse = True)[0] rect = cv2.minAreaRect(c) box = np.int0(cv2.cv.BoxPoints(rect)) # return the bounding box of the barcode return box
完成了上述的工作,我們就完成了二維碼和條形碼的定位,接下去實(shí)現(xiàn)視頻里面二維碼的解析
你可以新建一個(gè)python文件,barcode_vid.py
解析二維碼我們需要用zbar這個(gè)模塊和PIL,PIL在python里面裝好了
我們先導(dǎo)入模塊
# import the necessary packages import simple_barcode_detection import cv2 import numpy as np import zbar from PIL import Image
#接下去是創(chuàng)建一個(gè)掃描器,他可以解析二維碼的內(nèi)容
# create a reader
scanner = zbar.ImageScanner()
# configure the reader
scanner.parse_config('enable')
#設(shè)置屏幕顯示字體
font=cv2.FONT_HERSHEY_SIMPLEX
#啟用攝像頭
camera=cv2.VideoCapture(0)
#接下去是一個(gè)大的while循環(huán)
while True:
#得到當(dāng)前的幀
# grab the current frame
(grabbed, frame) = camera.read()
#檢測(cè)視頻是否到底了,如果檢測(cè)視頻文件里面的二維碼或條形碼用這個(gè),如果開啟攝像頭就無所謂了
# check to see if we have reached the end of the
# video
if not grabbed:
break
調(diào)用剛才我們建的那個(gè)函數(shù)來查找二維碼返回二維碼的位置
# detect the barcode in the image
box = simple_barcode_detection.detect(frame)
if box != None:
#這下面的3步得到掃描區(qū)域,掃描區(qū)域要比檢測(cè)出來的位置要大
min=np.min(box,axis=0)
max=np.max(box,axis=0)
roi=frame[min[1]-10:max[1]+10,min[0]-10:max[0]+10]
#把區(qū)域里的二維碼傳換成RGB,并把它轉(zhuǎn)換成pil里面的圖像,因?yàn)閦bar得調(diào)用pil里面的圖像,而不能用opencv的圖像
roi=cv2.cvtColor(roi,cv2.COLOR_BGR2RGB)
pil= Image.fromarray(frame).convert('L')
width, height = pil.size
raw = pil.tostring()
#把圖像裝換成數(shù)據(jù)
zarimage = zbar.Image(width, height, 'Y800', raw)
#掃描器進(jìn)行掃描
scanner.scan(zarimage)
#得到結(jié)果
for symbol in zarimage:
# 對(duì)結(jié)果進(jìn)行一些有用的處理
print 'decoded', symbol.type, 'symbol', '"%s"' %symbol.data
cv2.drawContours(frame, [box], -1, (0, 255, 0), 2)
#把解析的內(nèi)容放到視頻上
cv2.putText(frame,symbol.data,(20,100),font,1,(0,255,0),4)
# show the frame and record if the user presses a key
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# if the 'q' key is pressed, stop the loop
if key == ord("q"):
break
# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()
CSDN不能上傳視頻,我下面?zhèn)饕幌聢D片

下面還是上源碼
# import the necessary packages
import simple_barcode_detection
import cv2
import numpy as np
import zbar
from PIL import Image
# create a reader
scanner = zbar.ImageScanner()
# configure the reader
scanner.parse_config('enable')
font=cv2.FONT_HERSHEY_SIMPLEX
camera=cv2.VideoCapture(0)
while True:
# grab the current frame
(grabbed, frame) = camera.read()
# check to see if we have reached the end of the
# video
if not grabbed:
break
# detect the barcode in the image
box = simple_barcode_detection.detect(frame)
if box != None:
min=np.min(box,axis=0)
max=np.max(box,axis=0)
roi=frame[min[1]-10:max[1]+10,min[0]-10:max[0]+10]
print roi.shape
roi=cv2.cvtColor(roi,cv2.COLOR_BGR2RGB)
pil= Image.fromarray(frame).convert('L')
width, height = pil.size
raw = pil.tostring()
# wrap image data
zarimage = zbar.Image(width, height, 'Y800', raw)
# scan the image for barcodes
scanner.scan(zarimage)
# extract results
for symbol in zarimage:
# do something useful with results
print 'decoded', symbol.type, 'symbol', '"%s"' %symbol.data
cv2.drawContours(frame, [box], -1, (0, 255, 0), 2)
cv2.putText(frame,symbol.data,(20,100),font,1,(0,255,0),4)
# if a barcode was found, draw a bounding box on the frame
# show the frame and record if the user presses a key
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# if the 'q' key is pressed, stop the loop
if key == ord("q"):
break
# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()
總結(jié)
以上所述是小編給大家介紹的使用python寫的opencv實(shí)時(shí)監(jiān)測(cè)和解析二維碼和條形碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
Python和Java的語法對(duì)比分析語法簡(jiǎn)潔上python的確完美勝出
Python是一種廣泛使用的解釋型、高級(jí)編程、通用型編程語言,由吉多·范羅蘇姆創(chuàng)造,第一版發(fā)布于1991年。這篇文章主要介紹了Python和Java的語法對(duì)比,語法簡(jiǎn)潔上python的確完美勝出 ,需要的朋友可以參考下2019-05-05
使用Python實(shí)現(xiàn)租車計(jì)費(fèi)系統(tǒng)的兩種方法
本文通過兩種方法給大家分享了使用Python實(shí)現(xiàn)租車計(jì)費(fèi)系統(tǒng),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09
Python編寫運(yùn)維進(jìn)程文件目錄操作實(shí)用腳本示例
這篇文章主要為大家介紹了Python編寫實(shí)用運(yùn)維進(jìn)程文件目錄的操作腳本示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Python使用asyncio包處理并發(fā)的實(shí)現(xiàn)代碼
這篇文章主要介紹了Python使用asyncio包處理并發(fā),asyncio包使用事件循環(huán)驅(qū)動(dòng)的協(xié)程實(shí)現(xiàn)并發(fā),本文通過實(shí)例代碼給大家介紹的非常詳細(xì)對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
python中*args與**kwarsg及閉包和裝飾器的用法
這篇文章主要介紹了python中*args與**kwarsg及閉包和裝飾器的用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
python利用pymysql和openpyxl實(shí)現(xiàn)操作MySQL數(shù)據(jù)庫并插入數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了如何使用Python連接MySQL數(shù)據(jù)庫,并從Excel文件中讀取數(shù)據(jù),將其插入到MySQL數(shù)據(jù)庫中,有需要的小伙伴可以參考一下2023-10-10
python基于C/S模式實(shí)現(xiàn)聊天室功能
這篇文章主要為大家詳細(xì)介紹了python基于C/S模式實(shí)現(xiàn)聊天室功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
python+django+sql學(xué)生信息管理后臺(tái)開發(fā)
這篇文章主要為大家詳細(xì)介紹了python+django+sql學(xué)生信息管理后臺(tái)開發(fā),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

