PythonとOpenCVを使用して画像内の物体の輪郭を抽出する方法を紹介します。この記事では、OpenCVのfindContours
関数を用いて画像内に含まれる物体の輪郭を抽出する方法をサンプルコードとともに紹介します。また、ノイズ対策や輪郭の面積を取得する方法も解説します。
輪郭抽出の手順
以下の手順で輪郭抽出を行います。
- ターゲット画像読み込み
- グレースケールに変換
- 2値 (白黒)画像に変換
- OpenCVの
findContours
関数を用いて輪郭抽出 - 結果の描画・表示
輪郭抽出を行っているのは OpenCVのfindContours
関数です。cv2.findContours
関数の使いどころとしては、以下が挙げられます。
- 輪郭抽出
- 画像内の物体の数を数える
- 画像内の物体抽出 (物体検知用の学習データ作成に向けたのアノテーション)
ノイズ対策
輪郭抽出をするだけでは、細かいノイズ (の輪郭)が乗ってしまうのでその対策をします。使用する関数は、輪郭の面積を取得できる cv2.contourArea()
です。以下のコードを追加することで、指定したサイズ以上の輪郭のみ抽出できます。
contours = list(filter(lambda x:cv2.contourArea(x) > 1000, contours))
サンプルコード
以下のようなコードを今回作成しました。
import cv2
import matplotlib.pyplot as plt
# 分析対象画像のパス
trgtimg_path = 'test_images/sample1_for_contour.jpg'
# オリジナル画像の読み込み
img_bgr = cv2.imread(trgtimg_path)
# グレースケールに変換
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
# 2値化
gray_th = 160
ret, img_bin = cv2.threshold(img_gray, gray_th, 255, cv2.THRESH_BINARY)
# 輪郭抽出
contours, hierarchy = cv2.findContours(img_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# ノイズ対策
contours = list(filter(lambda x:cv2.contourArea(x) > 1000, contours))
# 領域の描画
result_img1 = cv2.drawContours(img_bgr.copy(), contours, -1, (0,255,0), 5)
cv2.imshow('result_img',result_img1)
cv2.waitKey(0)
# 個々の領域を囲む四角形をオリジナル画像に描画
for c in contours:
x,y,w,h = cv2.boundingRect(c)
result_img2 = cv2.rectangle(img_bgr, (x,y), (x+w,y+h), (255,0,0), 4)
この記事ではOpenCVを用いて画像内に含まれる物体の輪郭抽出をする方法をサンプルコードとともに紹介しました。うまく輪郭を抽出するためにノイズ対策も実施しています。画像処理を考えた際に必要になることが多いとと思いますので、活用できるようになることをお勧めします。