基於Python_Opencv識別圖像輪廓

要求:用矩形或者圓形框住圖片中的雲朵(不要求全部框出)

cloud

輪廓檢測

Opencv-Python接口中使用cv2.findContours()函數來查找檢測物體的輪廓。

import cv2

img = cv2.imread('cloud.jpg')
# 灰度圖像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化
ret, binary = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)
img1, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 以圓形框出雲朵
# for i in range(len(contours)):
#   (x, y), radius = cv2.minEnclosingCircle(contours[i])
#   center = (int(x), int(y))
#   radius = int(radius)
#   img = cv2.circle(img, center, radius, (0, 255, 0), 2)

#以雲朵邊界輪廓框出雲朵
cv2.drawContours(img, contours, -1, (0, 0, 255), 3)

cv2.imshow("img", img)
cv2.waitKey(0)

result

需要注意的是cv2.findContours()函數接受的參數爲二值圖,即黑白的(不是灰度圖),所以讀取的圖像要先轉成灰度的,再轉成二值圖。

cv2.findContours()函數

函數的原型爲:

cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])  

返回兩個值:contours,hierarchy。注:opencv3會返回三個值,分別是img, countours, hierarchy

參數說明

第一個參數是尋找輪廓的圖像
第二個參數表示輪廓的檢索模式,有四種:
1. cv2.RETR_EXTERNAL表示只檢測外輪廓
2. cv2.RETR_LIST檢測的輪廓不建立等級關係
3. cv2.RETR_CCOMP建立兩個等級的輪廓,上面的一層爲外邊界,裏面的一層爲內孔的邊界信息。如果內孔內還有一個連通物體,這個物體的邊界也在頂層。
4. cv2.RETR_TREE建立一個等級樹結構的輪廓。
第三個參數method爲輪廓的近似辦法
cv2.CHAIN_APPROX_NONE存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1,
max(abs(x1x2),abs(y2y1))==1
cv2.CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點座標,例如一個矩形輪廓只需4個點來保存輪廓信息
cv2.CHAIN_APPROX_TC89_L1CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

返回值

cv2.findContours()函數返回兩個值,一個是輪廓本身,還有一個是每條輪廓對應的屬性。

contour返回值

cv2.findContours()函數首先返回一個list,list中每個元素都是圖像中的一個輪廓,用numpy中的ndarray表示。這個概念非常重要。在下面drawContours中會看見。可以打印觀察contours的數據類型。

print (type(contours))  
print (type(contours[0]))  
print (len(contours))  
hierarchy返回值

該函數還可返回一個可選的hiararchy結果,這是一個ndarray,其中的元素個數和輪廓個數相同,每個輪廓contours[i]對應4個hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分別表示後一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號,如果沒有對應項,則該值爲負數。

result


輪廓的繪製

OpenCV中通過cv2.drawContours在圖像上繪製輪廓。

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])  
  1. 第一個參數是指明在哪幅圖像上繪製輪廓;
  2. 第二個參數是輪廓本身,在Python中是一個list;
  3. 第三個參數指定繪製輪廓list中的哪條輪廓,如果是-1,則繪製其中的所有輪廓。
  4. 後面的參數很簡單。其中thickness表明輪廓線的寬度,如果是-1(cv2.FILLED),則爲填充模式。
    resut

OpenCV中通過cv2.minEnclosingCircle()可以幫我們找到一個對象的外接圓。它是所有能夠包括對象的圓中面積最小的一個。

(x,y),radius = cv2.minEnclosingCircle(contours[i])
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)

result
2018.8.11

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章