計算機視覺,我們前期文章分享了很多關於類似這方面的文章,包括人臉識別三部曲,目標檢測,目標追蹤等,本期文章,我們介紹一下如何使用opencv來進行條形碼的檢測,畢竟超市裏面的物品都是有價格條形碼,如何進行opencv條形碼的檢測,便成了無人超市需要重點關注並需要解決的問題
opencv條形碼的檢測
opencv條形碼的檢測
import numpy as np
import cv2
image = cv2.imread("11.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)首先我們導入需要進行檢測的圖片,並把RGB顏色空間的圖片轉換成灰度照片
代碼截圖
ddepth = cv2.CV_32F
gradX = 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~255
maxval:填充色,取值範圍0~255
type:閾值類型,具體見下表
閾值類型
圖片形態學
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條形碼的檢測
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/223281.html
微信掃一掃
支付寶掃一掃