pythonとか

python3+opencvで何か色々やります

findContours,hierarchy

OpenCVの輪郭検出機能にfindContoursがある
これを使うと返り値にコンターと階層構造が取得できる

試しに以下のような画像を用意して

f:id:wave_cisk:20160903115603p:plain:w400

次のコードを実行する

import cv2

img = cv2.imread("./test.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, contours, hierarchy = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE )

findContoursの第二引数にRETR_TREEを指定することで階層構造を保持した輪郭が検出される

ここでcontoursとhierarchyの中身を確認


print("contours=",len(contours),  "hierarchy=",len(hierarchy) )

結果は、
contours= 7 hierarchy= 1
この場合は7本の輪郭を検出した
元画像に閉曲線は3つしか描いてないが、黒線の外側境界と内側境界で2つづつ検出されている

drawContoursを使って色分けしてみる

cv2.drawContours(img, contours[0], -1,(255,  0,  0),3)
cv2.drawContours(img, contours[1], -1,(  0,255,  0),3)
cv2.drawContours(img, contours[2], -1,(  0,  0,255),3)
cv2.drawContours(img, contours[3], -1,(255,255,  0),3)
cv2.drawContours(img, contours[4], -1,(  0,255,255),3)
cv2.drawContours(img, contours[5], -1,(255,  0,255),3)
cv2.drawContours(img, contours[6], -1,(  0,  0,  0),3)

cv2.imshow("img", img)

結果
f:id:wave_cisk:20160903134915p:plain:w400
外側の青線が0番目のコンターで、番号が大きいのが内側


hierarchyの中身をリスト表示

print(hierarchy)
[[[-1 -1  1 -1]
  [-1 -1  2  0]
  [-1 -1  3  1]
  [-1 -1  4  2]
  [-1 -1  5  3]
  [-1 -1  6  4]
  [-1 -1 -1  5]]]

数字の意味は
[next, previous, fist_child, parent]のコンターの番号を返す
この場合階層内に閉曲線が一つなのでnext,previousは-1
0番目のコンターは親を持たないので-1、子のコンター番号は1

コンターの面積

for i in range(0, len(contours)): 
    print(cv2.contourArea(contours[i]))
741105.0
188691.0
179718.0
59741.0
54736.0
22727.0
19664.0


地図の等高線で色分けとかしたいので
子のコンターの面積差で判定して境界線残して塗りつぶし

for i in range(2, len(contours)):
    
    area1 = cv2.contourArea(contours[i])
    area2 = cv2.contourArea(contours[int(hierarchy[0][i][2:3])])
    
    if( area1 - area2 > 10000 ) or ( area1 - area2 == 0 ):              
        cv2.fillConvexPoly(img, contours[i], (255,255-i*40,255-i*40))
    else:
        cv2.fillConvexPoly(img, contours[i], (0,0,0))

f:id:wave_cisk:20160903155733p:plain:w400