Tech Sketch Bucket of Technical Chips by TIS Inc.

OpenCVからLabeling.hを使ってラベリング

Pocket

ラベリングって?

ラベリングとは画像の中で連結している画素の固まりをその集合単位で抽出するものです。
具体的な例でいうと以下のような画像があるものとします。

入力画像

図1:入力画像

これに対してラベリングを実施することで、ひとつの画素の固まりに対して同じ色(ラベル)を割り当てたものが以下の画像です。

ラベリングされた画像

図2:ラベリングされた画像

このようにラベリングによってひと固まりになっているものが抽出され、その単位で他の処理を実行することができます。

また、ラベリングに関しては英語ですが以下のWikipediaの項目が参考になります。
Connected-component labeling(Wikipedia)

OpenCVでラベリング

OpenCVでラベリングを試みたところ、OpenCVには標準でラベリングをするクラスが用意されていません。
【OpenCV】輪郭処理(cvFindContours)を使ったラベリング処理 があるようですが、本記事ではライブラリを利用する方向で検討しました。

ざっくり調べてみたところ、OpenCVからラベリングが出来そうなものとして以下のものがあるようです。

上記のうち、cvBloblibとcvBlobは、Windows上のVC++から利用するにはビルドなどが難しそうだったので、ヘッダファイルだけで利用可能でライセンス上利用しやすそうなlabeling.hを利用してみました。


Labeling.hをつかう。

利用環境

というわけで以下の環境下でLabeling.hを利用してみました。

  • Microsoft Visual C++ 2010 Express
  • OpenCV 2.4.2

Labeling.hの入手

labeling.h からLabeling.hをダウンロードします。

サンプル

OpenCVを用いて画像ファイルを読み込んで、グレイスケール化、二値化、ラベリング、その結果を画面表示をするサンプルを用意しました。

ラベリング処理への入力

ラベリング処理への入力はLabeling.hの仕様上 0(黒)となるところは背景、その他はラベリング対象となります。
黒色部分をラベリングしたい場合は二値化の際に反転するフラグ(CV_THRESH_BINARY_INV )を設定しておく必要が有ります。

ラベリング処理の実行

サンプル中のLabelingBS#Execのところで、二値化された入力画像に対してラベリングされた出力を得ることが出来ます。(下図)
result.png

図3:入力画像と出力画像のイメージ図

Labeling.hで直接OpenCVのデータを取り扱うために以下のようにしています。

labeling処理への入力は二値化された1チャンネルのcv::Matのdataを渡します。
出力先はLabeling.hの仕様上shortである必要があるため、上記のように初期化したcv::Matのdataをキャストして渡します。

出力をcv::Matとして取り扱うことで、cv::compareなどを利用して特定のラベリングをされた部分の抽出が可能になるなど、OpenCVでラベリング結果を簡単に利用することが出来ます。

公式に書いてあるRegionInfoBSを使ってない。

サンプル中ではRegionInfoBSを利用していませんが、OpenCVと直接連携させなかったので割愛します。
Labeling.hのドキュメントどおりに動作すると思います。

ラベリングできました

というわけで、比較的簡単にOpenCVからLabeling.hを利用することが出来ました。

今回の記事ではラベリングする前段階の二値化手順などが適当なのでグラデーションしているものを入力画像に利用すると変な感じにラベリングされてしまう問題がありますが、目的に沿うように処理した上でLabeling.hに渡すことで強力に利用することが出来ると思います。

labeled_noname.png

図4:左:入力画像 右:出力画像

参考

Labeling.hの配布場所&ドキュメント

エンジニア採用中!私たちと一緒に働いてみませんか?