OpenCV で輪郭を見つける
このチュートリアルでは、Python で OpenCV の findContours()
関数を使用して画像に存在する輪郭を見つける方法について説明します。
Python で OpenCV の findContours()
関数を使用して画像内の輪郭を検索する
等高線は、オブジェクトの境界に沿ってポイントを結合することによって形成される曲線です。画像には複数のオブジェクトが存在し、画像の輪郭を見つけると、輪郭が画像に存在するオブジェクトの境界を強調するため、オブジェクトの形状に関する情報を取得できます。
オブジェクトの形状がわかれば、画像にどのオブジェクトが存在するかを簡単に推測できます。輪郭は、形状を分析し、オブジェクトを検出および認識するために広く使用されています。
OpenCV の findContours()
関数を使用して、画像に存在する輪郭を見つけることができます。精度を高めるには、バイナリイメージを使用して輪郭を見つける必要があります。
指定された画像がバイナリでない場合は、バイナリに変換できます。たとえば、カラー画像の場合、OpenCV の cvtColor()
関数を使用して画像をグレースケールに変換する必要があります。
OpenCV の threshold()
関数内のグレースケール画像を使用して、バイナリ画像を見つけることができます。その後、findContours()
関数とバイナリイメージを使用して輪郭を見つけることができます。
輪郭を表示する場合は、drawContours()
関数を使用して描画を作成し、輪郭を描画する必要があります。輪郭をよりよく視覚化するために、図面は指定された画像と同じサイズにする必要があります。
numpy
ライブラリの zeros()関数を使用して、指定された画像と同じサイズの黒色の描画を作成できます。
たとえば、imread()
関数を使用して画像を読み取り、それをバイナリスケールに変換してから、輪郭を見つけて表示してみましょう。以下のコードを参照してください。
import cv2
import numpy as np
image = cv2.imread("cat.jpg")
cv2.imshow("Original Image", image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("Gray Image", gray)
_, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
cv2.imshow("Binary image", binary)
contours, hierarchy = cv2.findContours(
binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
drawing = np.zeros((gray.shape[0], gray.shape[1], 3), dtype=np.uint8)
CountersImg = cv2.drawContours(drawing, contours, -1, (255, 255, 0), 3)
cv2.imshow("Contours", CountersImg)
cv2.waitKey(0)
出力:
findContours()
関数は 2つの出力引数を返します。最初の出力引数には、リスト内の輪郭の位置ポイントと座標が含まれています。2 番目の出力引数には、等高線の階層が含まれています。
findContours()
関数の最初の入力は、バイナリまたはグレースケール画像です。2 番目の入力引数は、等高線の階層を定義するために使用される取得モードです。
取得モード内で、すべての輪郭を取得する cv2.RETR_LIST
、外部カウンターのみを取得する cv2.RETR_EXTERNAL
、2 レベル階層の輪郭を取得する cv2.RETR_COMP
、cv2 などのさまざまな値を渡すことができます。RETR_TREE
は、完全な階層の輪郭を取得します。findContours()
関数の 3 番目の入力引数は、境界点を格納するために使用される近似メソッドです。
cv2.CHAIN_APPROX_NONE
メソッドはすべての境界点を格納しますが、すべての境界点が必要ない場合もあります。cv2.CHAIN_APPROX_SIMPLE
メソッドを使用して、始点と終点の等高線を保存できます。
findContours()
関数のオフセットに従って各輪郭をシフトするオフセットを定義することもできます。OpenCV の drawContours()
関数を使用して、指定された画像の上に輪郭を表示することもできます。
drawContours()
関数の最初の引数は、輪郭を描画する画像です。2 番目の引数は等高線で、3 番目の引数は等高線インデックスです。
3 番目の引数は等高線の色であり、RGB トリプレットとして定義できます。4 番目の引数は、整数として定義できる輪郭の太さです。
たとえば、与えられた画像の上に輪郭を表示しましょう。以下のコードを参照してください。
import cv2
import numpy as np
image = cv2.imread("cat.jpg")
cv2.imshow("Original Image", image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("Gray Image", gray)
_, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
cv2.imshow("Binary image", binary)
contours, hierarchy = cv2.findContours(
binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
drawing = np.zeros((gray.shape[0], gray.shape[1], 3), dtype=np.uint8)
CountersImg = cv2.drawContours(drawing, contours, -1, (255, 255, 0), 3)
cv2.imshow("Contours", CountersImg)
ImgWithCounter = cv2.drawContours(image, contours, -1, (255, 255, 0), 3)
cv2.imshow("Image with counters", ImgWithCounter)
cv2.waitKey(0)
出力: