OpenCVのfindContours hierarchy(輪郭の階層情報)の解説
前回の記事はOpenCVでの直線検出と図形検出、図形数えるについて説明しました。今回はOpenCVのfindContours hierarchy(輪郭の階層情報)について解説したいと思います。
目次
1. OpenCVのfindContours hierarchy(輪郭の階層情報)
2. RETR_LIST
3. RETR_TREE
4. RETR_CCOMP
5. RETR_EXTERNAL
1. findContours hierarchy(輪郭の階層情報)
OpenCVのPython版のfindcontours関数はオブジェクトの輪郭を検出する関数です。時には物体が難しい場所に位置,ある形状の中に別の形状が観測されることもあります。画像中に含まれるすべてのオブジェクトを検出して、それぞれのオブジェクトにラベル番号を振り分けています。輪郭線の情報およびオブジェクトの階層構造情報を返します。この関数表現方法を 階層情報 と呼びます。
第一引数に入力画像、第二引数に抽出モード、第三引数に近似手法を取ります。
image, contours, hierarchy = cv2.findContours(入力画像, 抽出モード, 近似手法)
実験
環境:Google Colab (CPU)でfindContours hierarchyの関数を実験します。
先ず、入力画像を表示します。
import cv2 import numpy as np from IPython.display import Image img_file = "box_a.png" Image(img_file)
findContoursのhierarchy の関数を作成します。画像をロードして加工します。そして、輪郭の階層情報を出します。最後は輪郭を可視化します。
def findContours_summary(img, method, output): img_file = img img = cv2.imread(img_file) img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(img_gray, 127, 255,0) contours, hierarchy = cv2.findContours(thresh, method, cv2.CHAIN_APPROX_SIMPLE) print(method) print("Number of Contours found = " + str(len(contours))) print(hierarchy) item_no = 0 font = cv2.FONT_HERSHEY_DUPLEX # 図形の設定 img1 = img.copy() flattened_hierarchy = [y for x in hierarchy for y in x] for cnt, h in zip(contours, flattened_hierarchy): approx = cv2.approxPolyDP(cnt, 0.01*cv2.arcLength(cnt, True), True) cv2.drawContours(img, [approx], 0, (0), 2) x = approx.ravel()[0] y = approx.ravel()[1] if len(approx) == 4: item_no +=1 cv2.putText(img1, "{}.{}".format(item_no, h), (x, y), font, 0.4, (0)) # 結果の画像作成 global output_img output_img = output cv2.imwrite(output_img, img1) Image(output_img)
2. RETR_LIST
RETR_LISTの抽出モードは最も単純なものです。画像の中全ての輪郭を検出しますが,輪郭の包含関係は無視されます。つまり,全ての輪郭が同一階層に属することになります。
ここでは3番目と4番目の値が常に―1となり,NextとPreviousには対応するインデックスが格納されることになります。一行目は輪郭0を表しており,次の輪郭が輪郭1であるためNext = 1となっています.一方で,前の輪郭は無いのでPrevious = 0となります.上述したように,残りの二つの数値は-1となります.
findContours_summary(img_file, cv2.RETR_LIST, "output1.jpg") Image(output_img)
1
Number of Contours found = 4
[[[ 1 -1 -1 -1]
[ 2 0 -1 -1]
[ 3 1 -1 -1]
[-1 2 -1 -1]]]
3. RETR_TREE
RETR_LISTの抽出モードは全包含要素が、無視され最も外側の輪郭のみが返されます。このルールの下では,包含関係の最も外のモノのみが残り,その他の下の階層は無視されると言えます。画像中では最も外側の輪郭,すなわち階層レベルが0の輪郭は3個あります。
findContours_summary(img_file, cv2.RETR_TREE, "output2.jpg") Image(output_img)
Number of Contours found = 4
[[[-1 -1 1 -1]
[ 2 -1 -1 0]
[-1 1 3 0]
[-1 -1 -1 2]]]
4. RETR_CCOMP
RETR_LISTの抽出モードは全輪郭を検出し,2レベルの階層に分類します。物体の外側の輪郭は階層1,物体の内側の穴などの輪郭は階層2と分類されます。
findContours_summary(img_file, cv2.RETR_CCOMP, "output3.jpg") Image(output_img)
Number of Contours found = 4
[[[ 1 -1 -1 -1]
[-1 0 2 -1]
[ 3 -1 -1 1]
[-1 2 -1 1]]]
5. RETR_EXTERNAL
RETR_EXTERNALの抽出モードは全子要素が、無視され最も外側の輪郭のみが返されます。このルールの下では,階層の最も上のモノのみが残り,その下の輪郭は無視されると言えます。
画像中では最も外側の輪郭,すなわち階層レベルが0の輪郭は1個あります。
findContours_summary(img_file, cv2.RETR_EXTERNAL, "output4.jpg") Image(output_img)
Number of Contours found = 1
[[[-1 -1 -1 -1]]]