今天,我實現了一個很有趣的demo,它可以在視頻里找到并解析二維碼,然后把解析的內容實時在屏幕上顯示出來。
然后我們直入主題,首先你得確保你裝了
opencv,python,zbar
等環境。然后這個教程對于學過opencv的人可能更好理解,但是沒學過也無妨,到時候也可以直接用。
比如我的電腦上的環境是opencv2.4.x,python2.7,和最新的zbar,在Ubuntu 12.12的系統下運行的
假設你的opencv已經安裝好了,那么我們就可以安裝zbar
你可以先更新一下
sudo apt-get update
然后在輸入
sudo apt-get install python-zbar
如果環境裝好了,我們就可以接著下一步操作了。
首先讓我們來實現找到在圖片里面找到二維碼的功能
先新建一個python文件叫做;
simple_barcode_detection.py
代碼如下,這定義了一個函數,實現從一副圖片里面找出二維碼的位置
我們要檢測的二維碼的圖片
import numpy as np import cv2 def detect(image): # 把圖像從RGB裝換成灰度圖 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 使用Scharr操作(指定使用ksize = -1)構造灰度圖在水平和豎直方向上的梯度幅值表示。 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) #經過上面的操作后看起來是這樣
# 對上述的梯度圖采用用9x9的核進行平均模糊,這是有利于降噪的
#然后進行二值化處理,要么是255(白)要么是0(黑)
blurred = cv2.blur(gradient, (9, 9)) (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
#模糊與二值化處理后,看起來是這個樣子,
#上面的操作后發現有一些條形碼的豎杠之間存在一些縫隙,并使我們的算法能檢測到斑點區域,我們進行一些基本的形態學操作 #我們首先使用cv2.getStructuringElement構造一個長方形內核。這個內核的寬度大于長度,因此我們可以消除條形碼中垂直條之間的縫隙。 # 這里進行形態學操作,將上一步得到的內核應用到我們的二值圖中,以此來消除豎杠間的縫隙。 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7)) closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) #上述操作后看起來是這個樣子
#我們發現還是存在一些小斑點,這時我們可以使用opencv里面的腐蝕和膨脹來處理他們,來去除白色的斑點
closed = cv2.erode(closed, None, iterations = 4) closed = cv2.dilate(closed, None, iterations = 4) #這時候的效果看起來是這樣的
# 接下來我們來找輪廓 (cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #如果沒找到則返回為空 if len(cnts) == 0: return None #找到了就通過面積來排序,并計算旋轉角 # 給最大的輪廓找到邊框 c = sorted(cnts, key = cv2.contourArea, reverse = True)[0] rect = cv2.minAreaRect(c) #box(里面是ndarry數組,包含了4個頂點的位置) box = np.int0(cv2.cv.BoxPoints(rect)) # 返回box return box
最終結果
?好了,上面的解釋里面有中文,可能python解釋的時候會通不過,我下面直接給出代碼
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
完成了上述的工作,我們就完成了二維碼和條形碼的定位,接下去實現視頻里面二維碼的解析
你可以新建一個python文件,barcode_vid.py
解析二維碼我們需要用zbar這個模塊和PIL,PIL在python里面裝好了
我們先導入模塊
# 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循環 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: #這下面的3步得到掃描區域,掃描區域要比檢測出來的位置要大 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] #把區域里的二維碼傳換成RGB,并把它轉換成pil里面的圖像,因為zbar得調用pil里面的圖像,而不能用opencv的圖像 roi=cv2.cvtColor(roi,cv2.COLOR_BGR2RGB) pil= Image.fromarray(frame).convert('L') width, height = pil.size raw = pil.tostring() #把圖像裝換成數據 zarimage = zbar.Image(width, height, 'Y800', raw) #掃描器進行掃描 scanner.scan(zarimage) #得到結果 for symbol in zarimage: # 對結果進行一些有用的處理 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) # 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不能上傳視頻,我下面傳一下圖片
下面還是上源碼
# 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()
總結
以上所述是小編給大家介紹的使用python寫的opencv實時監測和解析二維碼和條形碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
