OpenCVを用いて輪郭を取得する方法を紹介します。
ゴールイメージはこのようになります。
それでは実装方法を見ていきましょう。
OpenCVで輪郭を取得する
画像の輪郭は次の手順で取得していきます。
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)
どんな画像が取得できているかを表示して確認してみます。
入力画像から、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: 大津の二値化を用いる場合に利用する。詳しくは下記リンク参照。
画像の輪郭を取得する: 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)を画像として描画するのに使用します。
終わりに
今回は輪郭を取得する方法を紹介してきました。
次回は輪郭を用いた応用として、小さい輪郭を除外する方法、外接矩形の取得方法、輪郭を近似する方法(凸包など)を紹介していきたいと思います。
参考リンク
領域(輪郭)の特徴 — OpenCV-Python Tutorials 1 documentation
コメント