kinectとk近傍法で物体認識

復習

  • 前回、kinectと最近傍法で物体認識で、Kinectの深度データを使い物体認識を行った。
  • 今回、精度を上げるために、少しだけプログラムを書き換え、k-近傍法を使うことにする。
    • 今回はid:nowokay:20080328さんに習って、k=3にした。

implementation

  • 前回は、NearestNeighborクラスで、最小の誤差のデータを選んだが、今回は、最も近似した3つのデータの中で多数決を行い、答えを推測する。
  • 色々な方法はあるが、以下のフィールドを持つクラスを作って値を突っ込み、ソートすることにした。
    1. 観測地とデータの誤差
    2. 推測された名前index
public class IndexAndDifference: IComparable
{
    public int index;
    public double difference;
    public IndexAndDifference(int _index, double _difference)
    {
        index = _index;
        difference = _difference;
    }
    public int CompareTo(object obj)
    {
        IndexAndDifference Compare = (IndexAndDifference)obj;
        if (this.difference < Compare.difference)
            return -1;
        else if (this.difference > Compare.difference)
            return 1;
        else
            return 0;
    }
}
  • ソートの際に、オブジェクトの比較が行われるため、IComparableインターフェースを実装
    • CompareToをオーバーライドする。
  • 全ての格納されたデータに対してこのクラスオブジェクトをArrayListにいれた後、Listの関数のSort()でソート。
  • そして、最小3つを取り出し多数決を以下のように行った
if (sorted.Count < 3)//データが2つ以下なら多数決を取れないから
{
    index = ((IndexAndDifference)sorted[0]).index;
}
else if (((IndexAndDifference)sorted[1]).index == ((IndexAndDifference)sorted[2]).index)
{
    index = ((IndexAndDifference)sorted[1]).index;
}
else
{
    index = ((IndexAndDifference)sorted[0]).index;
}
return index;
  • こんな感じで、少しは精度上がったかな。
    • データの量に応じてkの数を増やすようにした方がいいのかも。

RANSAC法を利用してKinect深度データから平面除去

復習

  • kinectと最近傍法で物体認識、kinectとk近傍法で物体認識で作ったプログラムは、指定した範囲内の深度データからオブジェクト情報を学習した。
  • 問題点は、机などの関係のないデータも一緒に学習するため、例えば、テーブルに置かれた時計と、壁にかけられた同じ時計を違う物と見なす。
    • それを解決する一歩として、RANSAC(RANdom SAmple Consensus)アルゴリズムを用いて平面を除去する。

RANSACアルゴリズム

  • ノイズの多いサンプルから2次元ならば最もらしい直線の相関を見いだす。
  • 指定された回数の繰り返しで
    1. サンプルの中から適当な2点を選ぶ。
    2. その二点が結ぶ線上付近にある(誤差の許容量を指定)他の点の数を数える。
    3. その含まれる点の数が今までで最大ならば、最大の線の含む点のセットを更新
  • これによって、最もらしい線を求める。
  • 今回のように3次元の場合には、2点を3点にし、平面をランダムに選ぶことによって最もらしい平面を求めることができる。

implementation

  • とりあえず、C++のVector3fみたいなクラスを作る。
    • C#あまり知らないので似たような物は元々あるかも。
class Vector3F
{
    double X, Y, Z;
    public Vector3F(double _x, double _y, double _z)
    {
        X = _x;
        Y = _y;
        Z = _z;
    }
    public static Vector3F operator -(Vector3F left, Vector3F right)
    {
        return new Vector3F(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
    }
}
  • ポイント間の引き算が必要になるためoperator-をオーバーロードしておく。
  • 次にさっきのアルゴリズムに基づいてRANSACのクラスを作る。

デモ

  • 机の上のカボチャ

  • 机を除去

  • 壁の時計

  • 壁を除去

  • まぁまぁ良い感じでないのって感じ。