はじめに
cv2.findContoures関数で検出した輪郭データに基づいて、その輪郭を画像の上に描画して形状や位置を確認したという場面は多くあると思います。その様な場面で、簡単に輪郭の描画ができるcv2.drawContours関数を紹介します。
cv2.line関数を使って、地道に輪郭を描画するというやり方(下記リンク)もありますが、for文など 使った繰り返し処理はPythonでは得意な処理ではないため輪郭の数が多い場合はcv2.findContoures関数を使う方法が効率的と言えます。
cv2.drawContours関数
cv2.drawContours関数は、cv2.findContoures関数で検出した輪郭データを簡単に描画することができます。
cv2.drawContours関数の引数と戻り値は次の通りです。
引数
| 名称 | 説明 |
|---|---|
| 入力画像(必須) | 輪郭を描画する対象の画像。numpy.ndarrayオブジェクト。 |
| contours(必須) | 描画する輪郭のリスト。cv2.findContours関数で得られた値。 |
| contourIdx(必須) | 描画する輪郭のインデックス(-1などの負の値を指定すると全ての輪郭を描画) |
| color(必須) | 輪郭の色(BGR形式のタプルまたは整数値) |
| thickness(オプション) | 輪郭線の太さ。ピクセル単位、-1を指定すると輪郭を塗りつぶし。(デフォルト:1) |
| lineType(オプション) | 線の種類。LineTypesで定義される値を設定します。(デフォルト:cv.2LINE_8) |
| hierarchy(オプション) | 輪郭の階層情報。cv2.findContours関数で得られた値。(デフォルト:None) |
| maxLevel(オプション) | 描画する最大階層レベル |
| offset(オプション) | 輪郭座標のオフセット(デフォルト:(0, 0)) |
引数のlineTypeはLineTypesに示す3種類のいずれかとなります。デフォルトはcv2.LINE_8です。
| 線の種類 | 説明 |
|---|---|
| cv2.LINE_4 | 4 連結 |
| cv2.LINE_8 | 8 連結(デフォルト) |
| cv2.LINE_AA | アンチエイリアス処理された線 |
戻り値
入力画像に輪郭が描画された画像データ(numpy.ndarrayオブジェクト)が返されます。
使い方
以下にサンプルコードを示します。
import cv2
import numpy as np
# 画像読み込み
image = cv2.imread("image.jpg")
# グレースケールに変換
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 二値化
_, binary = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)
# 輪郭を検出
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 輪郭を描画
result = cv2.drawContours(image, contours, -1, (0, 255, 0), 1)
# 結果の表示
cv2.imshow('codevace: cv2.drawContours', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 入力画像と同じサイズの空の画像を作成
result = np.zeros(image.shape, image.dtype)
# 黒い背景に輪郭のみを描画
result = cv2.drawContours(result, contours, -1, (0, 255, 0), 1)
# 結果の表示
cv2.imshow('codevace: cv2.drawContours', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 入力画像と同じサイズの空の画像を作成
result = np.zeros(image.shape, image.dtype)
# 黒い背景に輪郭のみを塗りつぶして描画
result = cv2.drawContours(result, contours, -1, (0, 255, 0), -1)
# 結果の表示
cv2.imshow('codevace: cv2.drawContours', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
このコードでは、まず画像をグレースケールに変換し、二値化を行います。その後、cv2.findContours関数で輪郭を検出し、cv2.drawContours関数を使用して全ての輪郭を緑色(0, 255, 0)で描画します。
続いて、黒い背景に輪郭のみを緑色(0, 255, 0)で描画します。
さらに、黒い背景に輪郭のみを緑色(0, 255, 0)で塗りつぶして描画します。
入力画像は下記を使用しました。
結果は次の通りです。
細かな輪郭まで検出できていることが確認できます。
検出された輪郭数は17305個になりましたが、筆者の環境でもストレスなく描画処理を終えることができました。

-1024x754.png)
-1024x754.png)
おわりに
cv2.drawContours関数は、cv2.findContours関数で検出した輪郭を画像上に効率的に視覚化するためのツールです。
引数によって、描画する輪郭、色、太さなどを自由に設定できます。さらに、輪郭の階層情報を利用することで、より複雑な形状の描画も可能です。
また、cv2.drawContours関数以外にも、cv2.line関数、cv2.circle関数、cv2.rectangle関数など、様々な図形を描画する関数があります。
下の記事で紹介していますので、お時間がありましたら、ぜひ参考にしてください。
ご質問や取り上げて欲しい内容などがありましたら、コメントをお願いします。
最後までご覧いただきありがとうございました。
■(広告)OpenCVの参考書としてどうぞ!■




