Python/OpenCVで画像内オブジェクトの輪郭抽出をする

  • このエントリーをはてなブックマークに追加

OpenCVは様々な画像処理が手軽に出来るようになるライブラリです。ここではPythonで扱うOpenCVコードで、画像内のオブジェクトの輪郭を抽出する方法を紹介します。

こんにちは。wat(@watlablog)です。ここではOpenCVを使って画像内物体の輪郭を抽出する方法を学びます

画像内オブジェクトの輪郭抽出技術の用途

まず始めに言葉の定義を行います。ここで扱う画像内オブジェクトの輪郭とは、以下の画像で示す赤線部になります。

画像内オブジェクトの輪郭の例

画像処理の分野は非常に幅広く用途を語ること自体がナンセンスかも知れませんが、以下に輪郭抽出を行ってから次に行う処理の代表格を3例紹介します。

①面積を求める

輪郭とは閉じた線を意味するので、一度輪郭を抽出してしまえば輪郭を抽出したオブジェクトの面積を求めることが出来ます。

工場で製品のある面から見た面積を全数検査することでサイズに関する品質保証をしたり、定点観測しているオブジェクトの成長を自動的に定量評価する等、プログラム的に面積を求めることで様々な科学技術処理を自動化することができます。

②周長を求める

①と同様に、大きさを観察する特徴量としては周長(Arc Length)もあります。面積は2値化して1になっているピクセルの総和を求めれば簡単に計算出来ますが、周長はそう簡単には行きません。

しかし、輪郭を一度抽出してしまえば周長の計算も容易となります。

③重心を求める

輪郭を抽出するということは、輪郭の画像内座標を得ているということになります。座標情報があればそのオブジェクトの中心を簡単に求めることが出来ます。

画像内で任意のオブジェクトの座標を求めることが出来れば、動画(複数枚の画像と同義)内の物体トラッキング(軌跡を追うこと)が可能になります。

数え上げればきりがありませんが(アイデア次第)、画像処理でプログラム的に輪郭を抽出できるということは様々なソリューションに繋がっていると言えます。

Python/OpenCVで画像内オブジェクトの輪郭を抽出するコード

Advertisements

サンプル画像

今回使用するサンプル画像はこちらです。

輪郭抽出のサンプル画像はWATLABブログのロゴ

当WATLABブログのロゴマークに対し、「Python/OpenCVで任意色を透過させたpng画像に変換」で紹介した記事を使って背景を透過したものを使います。

背景は別途黒っぽい色を使っていますが、これはOpenCVを始めとした画像処理ライブラリでは白色をオブジェクトと認識する特徴を持つためです。

そのため画像を読み込んだ後は以下の画像に示すようグレースケール化をし、さらに二値化を行います。

グレースケール化と二値化の例

二値化については「Python/OpenCVで画像の二値化をする方法」で詳細を書いていますので、是非参考にして下さい。

全ての輪郭を抽出するコードの例

以下が画像を読み込み、グレースケール化を行った後に二値化、そして輪郭を抽出するための全コードとなります。二値化の部分は閾値を60としていますが、これは画像により異なることに注意して下さい。

ここではcv2.findContoursが輪郭を抽出するためのメソッドです。

第二引数にcv2.RETR_LISTを使っていますが、この引数は全輪郭を探査するために使います。

以下が実行結果です。

cv2.RETR_LIST

cv2.drawContours(img, contours, i, (0, 255, 0), 5)として、iを色々な数値に変更してみると以下の結果を得ます。

このメソッドは輪郭を描画するものですが、iの値により1つ1つの輪郭を分けて描画することも可能です。後は色(B,G,R)や太さ(ここでは5)をお好みで。

一番外側の輪郭のみを抽出するコードの例

上記コードのcv2.findContoursの第二引数をcv2.RETR_EXTERNALに変更することで一番外側の輪郭のみを抽出することが可能です。

以下が実行結果です。先ほどのコードでは最後の輪郭を指定しなければいけませんでしたが、今回は全輪郭(-1)を指定するだけでただ1つの輪郭が抽出されました。

cv2.RETR_EXTERNAL

用途によってはこの方が手軽だったりするかも知れません。

ちなみに、hierarchyはその名の通り、階層構造を格納した変数です。今回はオブジェクトが1つでしたが、いくつものオブジェクトの輪郭を抽出した場合は階層情報(1つの輪郭に対して子輪郭、孫輪郭…)を利用して計算することも可能ですね。

まとめ

本記事では画像処理の基礎である「オブジェクトの輪郭抽出」をやってみました。

毎回思う事ですが、OpenCVを使えばあっと言う間に使いやすい形式で目的が達成されることを確認しました。

輪郭抽出は様々な画像内オブジェクトの特徴量算出等に使われる手法でもあるので、今後はこの手法を用いた物体トラッキング等にもチャレンジしてみたいですね。

汎用的な「輪郭抽出」を覚えてみました!Twitterからは別途面白そうなライブラリの紹介もあったので、後でやってみたいと思います!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメント

コメントを残す

*