【Python・OpenCV】輪郭を描画する(cv2.drawContours)

※当サイトではアフィリエイト広告を利用しています

Python プログラミング 画像処理

【Python・OpenCV】輪郭を描画する(cv2.drawContours)

2024-08-29

はじめに

cv2.findContoures関数で検出した輪郭データに基づいて、その輪郭を画像の上に描画して形状や位置を確認したという場面は多くあると思います。その様な場面で、簡単に輪郭の描画ができるcv2.drawContours関数を紹介します。

cv2.line関数を使って、地道に輪郭を描画するというやり方(下記リンク)もありますが、for文など 使った繰り返し処理はPythonでは得意な処理ではないため輪郭の数が多い場合はcv2.findContoures関数を使う方法が効率的と言えます。

(広告) OpenCV関連書籍をAmazonで探す

cv2.drawContours関数

cv2.drawContours関数は、cv2.findContoures関数で検出した輪郭データを簡単に描画することができます。

cv2.drawContours関数の引数と戻り値は次の通りです。

cv2.drawContours(入力動画, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])

引数

名称説明
入力画像(必須)輪郭を描画する対象の画像。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_44 連結
cv2.LINE_88 連結(デフォルト)
cv2.LINE_AAアンチエイリアス処理された線

ポイント

  1. 特定の輪郭のみを描画
    • 引数contourIdxを使用して、特定の輪郭のみを描画できます。
    • 例えば、0を指定することで最初の輪郭のみ描画します。
  2. 輪郭の塗りつぶし
    • 引数thicknessに-1を指定すると、輪郭内部を塗りつぶすことができます。

戻り値

入力画像に輪郭が描画された画像データ(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個になりましたが、筆者の環境でもストレスなく描画処理を終えることができました。

おわりに

cv2.drawContours関数は、cv2.findContours関数で検出した輪郭を画像上に効率的に視覚化するためのツールです。
引数によって、描画する輪郭、色、太さなどを自由に設定できます。さらに、輪郭の階層情報を利用することで、より複雑な形状の描画も可能です。

また、cv2.drawContours関数以外にも、cv2.line関数、cv2.circle関数、cv2.rectangle関数など、様々な図形を描画する関数があります。
下の記事で紹介していますので、お時間がありましたら、ぜひ参考にしてください。

ご質問や取り上げて欲しい内容などがありましたら、コメントをお願いします。
最後までご覧いただきありがとうございました。

■(広告)OpenCVの参考書としてどうぞ!■

参考リンク

-Python, プログラミング, 画像処理
-