opencv 二維碼 openmv識別二維碼原理



文章插圖
opencv 二維碼 openmv識別二維碼原理

文章插圖
計算機視覺,我們前期文章分享了很多關于類似這方面的文章,包括人臉識別三部曲,目標檢測,目標追蹤等,本期文章,我們介紹一下如何使用opencv來進行條形碼的檢測,畢竟超市里面的物品都是有價格條形碼,如何進行opencv條形碼的檢測,便成了無人超市需要重點關注并需要解決的問題
opencv條形碼的檢測
opencv條形碼的檢測
import numpy as npimport cv2image = cv2.imread("11.jpg")gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)首先我們導入需要進行檢測的圖片,并把RGB顏色空間的圖片轉換成灰度照片
代碼截圖
ddepth =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)gradient = cv2.subtract(gradX, gradY)gradient = cv2.convertScaleAbs(gradient)blurred = cv2.blur(gradient, (9, 9))(_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)然后,我們使用cv.sobel算子進行圖片的X Y 軸的邊緣檢測,并使用cv2.subtract(gradX, gradY)計算圖片的梯度,以Sobel算子計算x,y方向上的梯度,之后在x方向上減去y方向上的梯度,通過這個減法,我們留下具有高水平梯度和低垂直梯度的圖像區域,然后cv2.convertScaleAbs返回圖片的unit8格式,參考圖片如下 。
高水平梯度和低垂直梯度的圖像區域
函數原型:dst=cv2.Sobel(src,ddepth,dx,dy[,dst[,ksize[,scale[,delta[,borderType]]]]])函數參數:
1. src – 需要處理的圖像
2. ddepth – 圖像的深度,-1表示采用的是與原圖像相同的深度 。目標圖像的深度必須大于等于原圖像的深度
3. dx – 對x軸方向求導的階數,一般為0、1、2,其中0表示這個方向上沒有求導
4. dy – 對y軸方向求導的階數,一般為0、1、2,其中0表示這個方向上沒有求導
5. dst – 目標圖像
6. ksize – Sobel算子的大小,必須為1、3、5、7
7. scale – 縮放導數的比例常數,默認情況下沒有伸縮系數
8. delta – 可選增量, 將會加到最終的dst中,同樣,默認情況下沒有額外的值加到dst中
9. borderType – 圖像邊界的模式 。這個參數默認值為cv2.BORDER_DEFAUL
在經過處理后,需要用convertScaleAbs()函數將其轉回原來的uint8形式,否則將無法顯示圖像,而只是一副灰色的窗口 。
函數原型:dst=cv2.convertScaleAbs(src[,dst[,alpha[,beta]]]) 其中可選參數alpha是伸縮系數,beta是加到結果上的一個值,結果返回uint8類型的圖片#absX=cv2.convertScaleAbs(x)#轉回uint8#absY=cv2.convertScaleAbs(y)
代碼截圖
在圖像的讀取中,會存在一些噪噪聲點,如一些白噪聲,因此我們需要進行去噪操作
opencv4種去噪操作
1. cv2.blur(均值濾波) 2.cv2.boxfilter(方框濾波)3. cv2.Guassiannblur(進行高斯濾波)4. cv2.medianBlur(進行中值濾波)1.cv2.blur(img, (3, 3)) 進行均值濾波參數說明:img表示輸入的圖片, (3, 3) 表示進行均值濾波的方框大小2. cv2.boxfilter(img, -1, (3, 3), normalize=True) 表示進行方框濾波,參數說明當normalize=True時,與均值濾波結果相同, normalize=False,表示對加和后的結果不進行平均操作,大于255的使用255表示3. cv2.Guassianblur(img, (3, 3), 1) 表示進行高斯濾波,參數說明: 1表示σ, x表示與當前值得距離,計算出的G(x)表示權重值4. cv2.medianBlur(img, 3) #中值濾波,相當于將9個值進行排序,取中值作為當前值參數說明:img表示當前的圖片,3表示當前的方框尺寸
閾值處理(cv2.threshold) 后圖片
opencv: 閾值處理(cv2.threshold)
cv2.threshold (src, thresh, maxval, type)src:源圖片,必須是單通道thresh:閾值,取值范圍0~255maxval:填充色,取值范圍0~255type:閾值類型,具體見下表
閾值類型
圖片形態學
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)closed = cv2.erode(closed, None, iterations = 4)closed = cv2.dilate(closed, None, iterations = 4)
代碼截圖
通過以上操作,我們已經檢測到了條形碼的大致位置,然后使用內核函數獲取圖片外形的形態學,并分別執行4次形態學腐蝕與膨脹,獲取更精確的圖片形狀位置
kernel = cv2.getStructuringElement這個函數的第一個參數表示內核的形狀,有三種形狀可以選擇矩形:MORPH_RECT;交叉形:MORPH_CROSS;橢圓形:MORPH_ELLIPSE;第二和第三個參數分別是內核的尺寸以及錨點的位置 。一般在調用erode以及dilate函數之前,先定義一個Mat類型的變量來獲得
getStructuringElement函數的返回值: 對于錨點的位置,有默認值Point(-1,-1),表示錨點位于中心點 。element形狀唯一依賴錨點位置,其他情況下,錨點只是影響了形態學運算結果的偏移 。
cv2.morphologyEx(src, op, kernel) 進行各類形態學的變化參數說明:src傳入的圖片op進行變化的方式kernel表示方框的大小2.op = cv2.MORPH_OPEN 進行開運算,指的是先進行腐蝕操作,再進行膨脹操作3. op = cv2.MORPH_CLOSE 進行閉運算, 指的是先進行膨脹操作,再進行腐蝕操作開運算:表示的是先進行腐蝕,再進行膨脹操作閉運算:表示先進行膨脹操作,再進行腐蝕操作
cv2.morphologyEx后圖片
形態學圖片轉換完成后,進行圖片的腐蝕與膨脹,這里主要是獲取更精確的外形 。
腐蝕與膨脹屬于形態學操作,所謂的形態學,就是改變物體的形狀,形象理解一些:腐蝕=變瘦 膨脹=變胖,主要是采用 cv2.erode() 和 cv2.dilate(),需要注意一點的是,腐蝕和膨脹主要針對二值化圖像的白色部分
腐蝕與膨脹后圖片
圖片外輪廓的繪制
cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = cnts[0]c = sorted(cnts, key = cv2.contourArea, reverse = True)[0]rect = cv2.minAreaRect(c)box = cv2.boxPoints(rect)box = np.int0(box)cv2.drawContours(image, [box], -1, (0, 255, 0), 3)cv2.imshow("Image", image)cv2.waitKey(0)
代碼截圖
我們通過以上的步驟,已經成功鎖定圖片條形碼的位置,然后使用cv2.findContours函數找到圖片的外形,并畫出圖片的外形 。
(_, cnts, _) = cv2.findContours(參數一: 二值化圖像closed.copy(),參數二:輪廓類型# cv2.RETR_EXTERNAL,#表示只檢測外輪廓# cv2.RETR_CCOMP,#建立兩個等級的輪廓,上一層是邊界# cv2.RETR_LIST,#檢測的輪廓不建立等級關系# cv2.RETR_TREE,#建立一個等級樹結構的輪廓# cv2.CHAIN_APPROX_NONE,#存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1參數三:處理近似方法# cv2.CHAIN_APPROX_SIMPLE,#例如一個矩形輪廓只需4個點來保存輪廓信息# cv2.CHAIN_APPROX_TC89_L1,# cv2.CHAIN_APPROX_TC89_KCOS)然后對找到的所有輪廓點進行重新排序
sorted(iterable, key=None, reverse=False)參數說明:iterable -- 可迭代對象 。key -- 主要是用來進行比較的元素,只有一個參數,具體的函數的參數就是取自于可迭代對象中,指定可迭代對象中的一個元素來進行排序 。reverse -- 排序規則,reverse = True 降序 , reverse = False 升序(默認) 。返回值返回重新排序的列表 。排序完成后的list傳遞給cv2.minAreaRect(Points)函數
其中points是點集,數據類型為ndarray,array((x1,y1),(x2,y2),….,(xn,yn))
而minAreaRect就是求出在上述點集下的最小面積矩形
rect[0]返回矩形的中心點,(x,y),實際上為y行x列的像素點
利用cv2.boxPoints(rect)可以返回矩形四個點的值,其中cv2.boxPoints(rect)[0]為point[0],cv2.boxPoints(rect)[1]為point[1].rect[1]返回矩形的長和寬rect[2]返回矩形的旋轉角度有了box的外形4個圖形點,便可以使用cv2.drawContours函數把4個點連接起來,形成一個矩形輪廓,最后顯示圖片
【opencv 二維碼 openmv識別二維碼原理】opencv條形碼的檢測