kinectと最近傍法で物体認識
復習
- 前回のkinectセンサーから任意の範囲の深度マップ抽出を拡張し、最近傍法(NN法、或いはk近傍法)を利用した物体認識を行う。
- NN法は、初歩的な機械学習法の一つ。
- 以前のRでニューラルネットワークを用いた手書き数字認識と違い、前処理を行わず、その場でメモリーの中から一番近似したデータを選ぶ
- その場で高速に学習(?)できるが、大量のデータを扱う際は前処理を行い効率化する必要がある気がする。
設計概要
- GUIのレイアウトは前回とほぼ変わらず以下のよう。
- 変更点は、ボタン1を学習モードに割り当て、ボタン2をテストモードに割り当てた所くらい。
- メインウィンドウのフィールドに、選択範囲内での深度マップを格納する1次元配列を用意。
- (imageFrame.Image.Bitsを取得したdepthData配列も、表示する色を格納したcolorFrameも余計なデータが入ってるので新しく作った)
- rec、testのそれぞれのボタンを押す際に、イメージのストリームをとめてわかりやすくする。
NN法の設計(id:nowokayさんの基本のNearestNeighbors法(NN法)でパターン認識を参考)
- まずは、データを格納するクラスを作った。
public class Data { public int index;//privateにしてゲッターセッターを追加する方が良い public double[] data; public Data(int _index, double[] _data) { data = _data; index = _index; } }
-
- doubleの配列のデータ、そして、その名前のインデックス(メインウィンドウで、命名した順に割り振られる)
- NN法の考え方はシンプルで、テスト用に送られてきたデータをメモリ内のデータと比較し、一番近似した物を選ぶ。
public class NearestNeighbor{ ArrayList dataArray = new ArrayList(); MainWindow mw; public NearestNeighbor(MainWindow _mw) { mw = _mw;//main windowのアドレス取得 } public void learn(int _index, double[] _data) { dataArray.Add(new Data(_index,_data)); } public int trial(double[] _data) { int index = 0; double min = Double.MaxValue;//とりあえず可能な最大値 for(int i = 0; i<dataArray.Count; i++){ double[] tmp = ((Data)dataArray[i]).data; double sumDiff = 0; for(int j=0; j<tmp.Length; j++) { sumDiff += Math.Pow(tmp[j] - _data[j],2);//それぞれの点における二条誤差を足しあわせる } if(min > sumDiff)//最小の誤差のインデックスを記憶 { min = sumDiff; index = ((Data)dataArray[i]).index; } } return index; } }
名前登録パネル
- 名前の登録のために以下のパネルを追加
- コンボボックスに、すでに登録された名前リスト、あるいは新規名前登録の選択肢を与える。
- 新規登録が選択されたときのみ、下部のテキストボックスをenableにする。
- また、学習の手間を省くため、コンボボックスの初期メニュー選択は、送られてきた深度マップが最も近い名前の物を表示するようにする。
text-to-speech
- あとは、人に見せるとき、学習した名前をテキストボックスに表示するのでは地味なので、覚えた名前をコンピュータに読ませるようにした。
- referenceにSystem.speechを追加し、コードに以下を追加
using System.Speech.Synthesis
- 初期化
SpeechSynthesizer synth = new SpeechSynthesizer(); synth.Volume = 100; // ボリューム設定:0〜100 synth.Rate = -5; // 読むスピード設定:-10〜10
- 読ませる
synth.Speak("what do you want me to say?");
デモ
- ムヒをkinectの前に置いて、認識範囲指定、そして、「Rec」をクリック
- で、次回から「test」で認識するようになる。
- text-to-speechで読むと同時に、画面左下のtext boxにも認識した名前を表示。
- 次にかぼちゃを認識
- 鍋を認識。
- 初めはかぼちゃと勘違いしていたが、すぐに学習
- やかん
- やかん2
- NN法は、メモリの中から一番近い物を選ぶため、違う物を同じやかんと命名することも可
- コーヒーカップ
- 鳥の置物
- お茶葉箱
改善点
- 認識したい物体の大きさに応じて、データを拡大縮小できるように
- カメラからの距離で物体を学習するのではなく、物体の厚みなどを計算し、設置距離が大きく変わっても認識できるように
- RANSACアルゴリズムなどを用いて、設置平面を求め消去する*1
心理学との関連
- 発達心理学の分野の実験で分かっていることは、2歳以下の子供は、物の名前学習をするに当たって、shape biasを主に使っている。(Jones and Smith, 2002)*2
- 似た形の物は同じ名前を持っているという思いこみを、色よりも大きさよりも何よりも最も利用する。
- それ以上の子供は、更に、function biasという、同じ機能を持った物体に名前を汎化させる傾向を持つ。(Nelson, Russsel, Duke, and Jones, 2000)*3
- それは少し難しいのでもう少し勉強したら挑戦。
- Grabner, Gall, Goolの"What Makes a Chair a Chair?" (2011)とか面白そうなことしてる。
参考書
*1:参考:RANSACを調べてみました
*2:Jones, S. S., & Smith, L. B. (2002). How children know the relevant properties for generalizing object names. Developmental Science 5(2), 219-232.
*3:Nelson, D. G. K., Russell, R., Duke, N., & Jones, K. (2000). Two-Year-Olds Will Name Artifacts by Their Functions. Child Development, 71(5), 1271-1288.