1. 程式人生 > >Python OpenCV 輪廓特徵1

Python OpenCV 輪廓特徵1

                           Python  OpenCV  輪廓特徵1

 

什麼是輪廓

     輪廓可以簡單認為成連續的點(連著邊界)連在一起的曲線,具有相同的顏色或者灰度。輪廓在形狀分析物體的檢測和識別中很有用。

  

學習計算輪廓特徵,如面積、周長、最小外接矩形等。圖片等可到原始碼處下載。


目標

  • 計算物體的周長、面積、質心、最小外接矩形等
  • OpenCV函式:cv2.contourArea(), cv2.arcLength(), cv2.approxPolyDP() 等

教程

在計算輪廓特徵之前,我們先用上一節的程式碼把輪廓找到:

img = cv2.imread('handwriting.jpg', 0)
_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
image, contours, hierarchy = cv2.findContours(thresh, 3, 2)

# 以數字3的輪廓為例
cnt = contours[0]

為了便於繪製,我們創建出兩幅彩色圖,並把輪廓畫在第一幅圖上:

img_color1 = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
img_color2 = np.copy(img_color1)
cv2.drawContours(img_color1, [cnt], 0, (0, 0, 255), 2)

 

輪廓面積

area = cv2.contourArea(cnt)  # 4386.5

注意輪廓特徵計算的結果並不等同於畫素點的個數,而是根據幾何方法算出來的,所以有小數。

如果統計二值圖中畫素點個數,應儘量避免迴圈,可以使用cv2.countNonZero()

,更加高效

 

輪廓周長

perimeter = cv2.arcLength(cnt, True)  # 585.7

引數2表示輪廓是否封閉,顯然我們的輪廓是封閉的,所以是True。

影象矩

矩可以理解為影象的各類幾何特徵,詳情請參考:[Image Moments]

M = cv2.moments(cnt)

M中包含了很多輪廓的特徵資訊,比如M['m00']表示輪廓面積,與前面cv2.contourArea()計算結果是一樣的。質心也可以用算:

cx, cy = M['m10'] / M['m00'], M['m01'] / M['m00']  # (205, 281)

 

外接矩形

形狀的外接矩形有兩種,如下圖,綠色的叫外接矩形,表示不考慮旋轉並且能包含整個輪廓的矩形。藍色的叫最小外接矩,考慮了旋轉:

x, y, w, h = cv2.boundingRect(cnt)  # 外接矩形
cv2.rectangle(img_color1, (x, y), (x + w, y + h), (0, 255, 0), 2)
rect = cv2.minAreaRect(cnt)  # 最小外接矩形
box = np.int0(cv2.boxPoints(rect))  # 矩形的四個角點取整
cv2.drawContours(img_color1, [box], 0, (255, 0, 0), 2)

其中np.int0(x)是把x取整的操作,比如377.93就會變成377,也可以用x.astype(np.int)

 

最小外接圓

外接圓跟外接矩形一樣,找到一個能包圍物體的最小圓:

(x, y), radius = cv2.minEnclosingCircle(cnt)
(x, y, radius) = np.int0((x, y, radius))  # 圓心和半徑取整
cv2.circle(img_color2, (x, y), radius, (0, 0, 255), 2)

 

擬合橢圓

我們可以用得到的輪廓擬合出一個橢圓:

ellipse = cv2.fitEllipse(cnt)
cv2.ellipse(img_color2, ellipse, (255, 255, 0), 2)

 

形狀匹配

cv2.matchShapes()可以檢測兩個形狀之間的相似度,返回值越小,越相似。先讀入下面這張圖片:

img = cv2.imread('shapes.jpg', 0)
_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
image, contours, hierarchy = cv2.findContours(thresh, 3, 2)
img_color = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)  # 用於繪製的彩色圖

圖中有3條輪廓,我們用A/B/C表示:

cnt_a, cnt_b, cnt_c = contours[0], contours[1], contours[2]
print(cv2.matchShapes(cnt_b, cnt_b, 1, 0.0))  # 0.0
print(cv2.matchShapes(cnt_b, cnt_c, 1, 0.0))  # 2.17e-05
print(cv2.matchShapes(cnt_b, cnt_a, 1, 0.0))  # 0.418

可以看到BC相似程度比AB高很多,並且圖形的旋轉或縮放並沒有影響。其中,引數3是匹配方法,詳情可參考:ShapeMatchModes,引數4是OpenCV的預留引數,暫時沒有實現,可以不用理會。

形狀匹配是通過影象的Hu矩來實現的(cv2.HuMoments()),大家如果感興趣,可以參考:Hu-Moments

 

小結

常用的輪廓特徵:

  • cv2.contourArea()算面積,cv2.arcLength()算周長,cv2.boundingRect()算外接矩
  • cv2.minAreaRect()算最小外接矩,cv2.minEnclosingCircle()算最小外接圓
  • cv2.matchShapes()進行形狀匹配

 

原文參考:https://www.jianshu.com/p/6a71aceb8da6

希望對你有幫助。