黄昏より暗きもの、血の流れより赤きもの

黄昏より暗きもの、血の流れより赤きもの

自分の好きな事を好きなように書いて行きます。

【画像処理(OpenCV)】(K-Means Image Segmentation):データマイニングにも使われる「K-Means」法を使って画像を領域分割してみた【クラスタリング】

はじめに:画像の領域分割について

画像の領域分割とは、画像をある規則により複数の領域に分割することです。簡単に言えばPhotoshopで言う「マスク(アルファチャンネル)」や「選択範囲」です。例えばPhotoshopの「アルファチャンネル」などを使い、各種ツールを使って画像から対象物を抜き取ったりすることがあると思います。抜き取った際画像を対象物のマスクと背景のマスクに分割している訳です。

さてPhotoshopの場合「自動選択ツール」「色域指定」などマスクを作成する機能がありますが、こうした機能の一般的な呼び方が画像の領域分割と言う訳です。こういうツールを作るのは大変難しく、大学時代に研究で挑戦してみたのですが上手く行かずでした(笑)。

画像の領域分割の主な手法

ここからは画像の領域分割の主な手法として、領域成長法と機械学習クラスタリングに依る方法の2つあります。以下この2つに分けて説明していきます。

領域成長法:核となるピクセルと同じ特徴を持つピクセルを集めて行き、画像を複数の領域に分ける方法[例:Watershed(cvwatershed)など]

機械学習クラスタリング:画像の画素値の分布(ヒストグラム)や、数学的なアルゴリズムを使って画像を複数の領域に分割する方法

今回使う手法はクラスタリングアルゴリズムの1つである「K-Means法」です。この方法は画像処理やデーターマイニングなど幅広く使われるアルゴリズムなため、上記の人全てに読んでもらえる記事が書きやすいと思い採用しました。以下K-Means法について簡単に説明していきます。

K-Means法について

以下K-Meansアルゴリズムの数学的な説明について触れます。k-means法 - 機械学習の「朱鷺の杜Wiki」さんに依れば、クラスタの重心を計算し、重心との距離がちかい要素を集めて行くアルゴリズムと言えます。


次の目的関数を最小化する分割最適化クラスタリングの代表的手法。


f:id:program_study:20141109171251p:plain

ただし、データ集合 X は、ベクトルで表現されたデータ x の集合。 クラスタ Xi は、データ集合の網羅的で互いに素な部分集合。x¯i は Xi中の重心(セントロイドともいう)。||⋅|| はユークリッドノルム。



1.初期化:データ集合をランダムに k個のクラスタ分割し,初期クラスタを得る
2.各クラスタについてセントロイドf:id:program_study:20141109171321p:plainを計算
3.全てのデータ x∈X を,各クラスタのセントロイド xi との距離 ∥x−xi∥を最小にするクラスタ Xi へ割り当てる
4.前の反復とクラスタに変化がないか反復数が maxIter を超えたら終了しクラスタ {Xi} を出力.そうでなければ,ステップ2に戻る
(k-means法 - 機械学習の「朱鷺の杜Wiki」)

具体的にどのような流れでクラスタリングされているかを知りたい方は、「クラスタリングの定番アルゴリズム「K-means法」をビジュアライズしてみた - てっく煮ブログ」を読んでみると言いかもしれません。Flashのアニメーションでどのようにクラスタが変化しているか見る事ができます。

実験

まずブログ公開上の都合でK=5とし、2つの画像の様子を見てみましょう。

画像1

f:id:program_study:20141109164310j:plainf:id:program_study:20141109164316j:plainf:id:program_study:20141109164320j:plainf:id:program_study:20141109164455j:plainf:id:program_study:20141109164342j:plainf:id:program_study:20141109164336j:plain

画像2

f:id:program_study:20141109164610j:plainf:id:program_study:20141109164612j:plainf:id:program_study:20141109164614j:plainf:id:program_study:20141109164617j:plainf:id:program_study:20141109164620j:plainf:id:program_study:20141109164637j:plain

画像処理の場合「画像から指を指す方向を認識したい」と言った目的があり、その目的達成のためのアルゴリズム、パラメーターの選定をする流れとなります。なので実験の指針のようなものを立てながらやるのもコツです。

今回特に目的を定めていませんでしたが、敢えて1枚目に被写体と背景の色が別々の画像を採用しました。これは黄色や赤の回りに色を集めやすいと予想したからで、なんとか黄色と赤に画像の領域を分割することができました。

2枚目はわざと色んな色がバラバラで判別の難しいと思われる画像を選びました。あわよくば真ん中のボーカロイドのキャラクターを抜き出せればと思ってしまいそうですが、照明などの影響もあり複数ののクラスタに分割されてしまっています。照明などの影響を除去するための前処理が必要と考えられます。

ソースコード

ソースコード「k-meansクラスタリングによる画像分割,減色:OpenCV.jp」を書き換えたものです。

K-Meansを実行後、画像はK個のクラスタに分割されます。この分割の様子を分かりやすくするために、分割後のクラスタを別の画像に保存するよう改良しました。ここで、クラスタとして選択されてない部分は黒く塗りつぶすよう設定しました。

MAX_CLUSTERSで分割するクラスタKの数を、DEBUG_MODEが0のときは減色処理された画像を、1の場合はクラスタ毎の画像が所定のフォルダーに保存されます。入力する画像、出力する画像のパスなどは各自で入力の方をお願い致します。

以上で説明の方を終了します。最後までお読み頂きありがとうございました。