OpenCVで画像の輪郭を取得する方法 cv2.findContours

findcontour OpenCV

OpenCVを用いて輪郭を取得する方法を紹介します。

学べること
  • 画像の輪郭を取得する方法
  • 取得した輪郭を矩形(長方形)として取得する方法

ゴールイメージはこのようになります。

それでは実装方法を見ていきましょう。

OpenCVで輪郭を取得する

画像の輪郭は次の手順で取得していきます。

輪郭取得の手順
  1. 画像を読み込んでグレースケールにする: cv2.cvtColor
  2. 画像を2値化する: cv2.threshold
  3. 画像の輪郭を取得する: cv2.findContours
  4. 輪郭を描画して確認: cv2.drawContours

1〜3までで輪郭を取得し、4で輪郭が正しく取得されているかを確認しています。

輪郭取得のソースコード

先ほどの手順にしたがって画像の輪郭を取得してみます。

import cv2
import matplotlib.pyplot as plt

# 画像の読み込み
img_path = '輪郭を取得したい画像のPathを記入' # 例:'./sample.png'
img_clr = cv2.imread(img_path)

# グレースケールへ変更
img_clr = cv2.cvtColor(img_clr[:450], cv2.COLOR_BGR2RGB)
img = cv2.cvtColor(img_clr, cv2.COLOR_BGR2GRAY)

# 二値化
# 注:グレースケール画像である必要があります。
ret, img_bin = cv2.threshold(img,220,255,0)

# 輪郭を取得
cnts, _ = cv2.findContours(img_bin, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

# 輪郭を描画
img_cnt = cv2.drawContours(np.zeros_like(img), cnts, -1, 255,3)

どんな画像が取得できているかを表示して確認してみます。

オリジナル画像(img_clr)
2値化した画像(img_bin)
輪郭画像(img_cnt)

入力画像から、2値化した白黒画像が作成され、輪郭が抽出されているのが分かります。
ちなみに、画像を並べて表示する方法についてはこちらの記事で紹介してます。

以降では輪郭取得に利用した関数について、使い方を個別に見ていきます。

画像を2値化する: cv2.threshold

グレースケールの画像を入力して、2値化した白黒画像を作成するのに使用します。

  • 画像を閾値を元に2値化する関数: cv2.threshold
ret, img_bin = cv2.threshold(img,thd,max,type)
### 入力
# img: 入力画像。グレースケール画像である必要がある。
# thd: 閾値。この値を基準に2値化する。
# type: 2値化の方法。最もシンプルな方法はcv2.THRESH_BINARYです。
### 出力
# img_bin:2値化された画像。
# ret: 大津の二値化を用いる場合に利用する。詳しくは下記リンク参照。

2値化の方法(type)について
大津の2値化について

画像の輪郭を取得する: cv2.findContours

2値化した画像を入力して、輪郭をPythonのListとして取得します。

  • 画像の輪郭を取得する関数: cv2.findContours
cnts, _ = cv2.findContours(img, retval, mode)
### 入力
# img: 入力画像。
# retval: 輪郭の取得方法。記事ではcv2.RETR_TREEを使用。
# mode: 輪郭の近似方法。基本はcv2.CHAIN_APPROX_SIMPLEを使用。
### 出力
# cnts: 輪郭。検出した全ての輪郭がlistとして取得されます。

輪郭を描画して確認: cv2.drawContours

取得した輪郭(PythonのList)を画像として描画するのに使用します。

cv2.thresholdの使い方
  • 輪郭を描画する方法: v2.drawContours
draw_img = cv2.drawContours(img, cnts, index, clr, thickness)
### 入力
# img: 輪郭を描画する画像
# cnts: 描画する輪郭
# index: 描画する輪郭のインデックス。全て描画する場合は−1を指定。
### 出力
# draw_img: 輪郭を描画した画像

終わりに

今回は輪郭を取得する方法を紹介してきました。
次回は輪郭を用いた応用として、小さい輪郭を除外する方法、外接矩形の取得方法、輪郭を近似する方法(凸包など)を紹介していきたいと思います。

参考リンク

領域(輪郭)の特徴 — OpenCV-Python Tutorials 1 documentation

コメント

タイトルとURLをコピーしました