OpenCV中幾何形狀識(shí)別與測(cè)量
點(diǎn)擊上方“小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)
經(jīng)??吹接袑W(xué)習(xí)OpenCV不久的人提問(wèn),如何識(shí)別一些簡(jiǎn)單的幾何形狀與它們的顏色,其實(shí)通過(guò)OpenCV的輪廓發(fā)現(xiàn)與幾何分析相關(guān)的函數(shù),只需不到100行的代碼就可以很好的實(shí)現(xiàn)這些簡(jiǎn)單幾何形狀識(shí)別與對(duì)象測(cè)量相關(guān)操作。本文就會(huì)演示給大家如何通過(guò)OpenCV 輪廓發(fā)現(xiàn)與幾何分析相關(guān)函數(shù)實(shí)現(xiàn)如下功能:
幾何形狀識(shí)別(識(shí)別三角形、四邊形/矩形、多邊形、圓)
計(jì)算幾何形狀面積與周長(zhǎng)、中心位置
提取幾何形狀的顏色
在具體代碼實(shí)現(xiàn)與程序演示之前,我們先要搞清楚一些概念。
1. 輪廓(contours)
什么是輪廓,簡(jiǎn)單說(shuō)輪廓就是一些列點(diǎn)相連組成形狀、它們擁有同樣的顏色、輪廓發(fā)現(xiàn)在圖像的對(duì)象分析、對(duì)象檢測(cè)等方面是非常有用的工具,在OpenCV中使用輪廓發(fā)現(xiàn)相關(guān)函數(shù)時(shí)候要求輸入圖像是二值圖像,這樣便于輪廓提取、邊緣提取等操作。輪廓發(fā)現(xiàn)的函數(shù)與參數(shù)解釋如下:
findContours(image, mode, method, contours=None, hierarchy=None, offset=None)
- image輸入/輸出的二值圖像
- mode 返回輪廓的結(jié)構(gòu)、可以是List、Tree、External
- method 輪廓點(diǎn)的編碼方式,基本是基于鏈?zhǔn)骄幋a
- contours 返回的輪廓集合
- hieracrchy 返回的輪廓層次關(guān)系
- offset 點(diǎn)是否有位移
2. 多邊形逼近
多邊形逼近,是通過(guò)對(duì)輪廓外形無(wú)限逼近,刪除非關(guān)鍵點(diǎn)、得到輪廓的關(guān)鍵點(diǎn),不斷逼近輪廓真實(shí)形狀的方法,OpenCV中多邊形逼近的函數(shù)與參數(shù)解釋如下:
approxPolyDP(curve, epsilon, closed, approxCurve=None)
- curve 表示輸入的輪廓點(diǎn)集合
- epsilon 表示逼近曲率,越小表示相似逼近越厲害
- close 是否閉合
3. 幾何距計(jì)算
圖像幾何距是圖像的幾何特征,高階幾何距中心化之后具有特征不變性,可以產(chǎn)生Hu距輸出,用于形狀匹配等操作,這里我們通過(guò)計(jì)算一階幾何距得到指定輪廓的中心位置,計(jì)算幾何距的函數(shù)與參數(shù)解釋如下:
moments(array, binaryImage=None)
- array表示指定輸入輪廓
- binaryImage默認(rèn)為None
基于輪廓發(fā)現(xiàn)與多邊形逼近、幾何距實(shí)現(xiàn)幾何形狀識(shí)別與對(duì)象測(cè)量,測(cè)量時(shí)候還用到另外兩個(gè)相關(guān)API分別是計(jì)算輪廓的周長(zhǎng)與面積。具體用法在代碼中體現(xiàn)。整個(gè)代碼實(shí)現(xiàn)分為如下幾步完成:1.圖像二值化
# 二值化圖像
print("start to detect lines...\n")
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
cv.imshow("input image", frame)
2.輪廓發(fā)現(xiàn)
out_binary, contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for cnt in range(len(contours)):
? ?# 提取與繪制輪廓
? ?cv.drawContours(result, contours, cnt, (0, 255, 0), 2)
3.幾何形狀識(shí)別
# 輪廓逼近
epsilon = 0.01 * cv.arcLength(contours[cnt], True)
approx = cv.approxPolyDP(contours[cnt], epsilon, True)
# 分析幾何形狀
corners = len(approx)
shape_type = ""
if corners == 3:
? ?count = self.shapes['triangle']
? ?count = count+1
? ?self.shapes['triangle'] = count
? ?shape_type = "三角形"
if corners == 4:
? ?count = self.shapes['rectangle']
? ?count = count + 1
? ?self.shapes['rectangle'] = count
? ?shape_type = "矩形"
if corners >= 10:
? ?count = self.shapes['circles']
? ?count = count + 1
? ?self.shapes['circles'] = count
? ?shape_type = "圓形"
if 4 < corners < 10:
? ?count = self.shapes['polygons']
? ?count = count + 1
? ?self.shapes['polygons'] = count
? ?shape_type = "多邊形"
4.測(cè)量周長(zhǎng)、面積、計(jì)算中心
# 求解中心位置
mm = cv.moments(contours[cnt])
cx = int(mm['m10'] / mm['m00'])
cy = int(mm['m01'] / mm['m00'])
cv.circle(result, (cx, cy), 3, (0, 0, 255), -1)
# 計(jì)算面積與周長(zhǎng)
p = cv.arcLength(contours[cnt], True)
area = cv.contourArea(contours[cnt])
5.顏色提取
# 顏色分析
color = frame[cy][cx]
color_str = "(" + str(color[0]) + ", " + str(color[1]) + ", " + str(color[2]) + ")"
運(yùn)行顯示原圖如下:

分析結(jié)果:

控制臺(tái)輸出:

下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
交流群
歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱(chēng)+學(xué)校/公司+研究方向“,例如:”張三?+?上海交大?+?視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~

