Hatena::ブログ(Diary)

明日とロボット このページをアンテナに追加 RSSフィード

2011-07-01

kinectセンサーから任意の範囲の深度マップ抽出

深度マップ

f:id:astrobot:20110701225046j:image

  • kinectセンサーがサポートする850〜4000の範囲で深度の検出を行う。
  • それ以外は白で表示しない。
  • 基本的の深度データの操作の方法は、Working with Depth Dataより。

implementation

  • 深度を検出する関数
    • byte[] 配列で深さを表現し、1ピクセルに2バイトを使うため、それぞれに対応するビットシフトオペレーターを、タイプに応じて使う必要がある。
    • Depthタイプを使う場合
      • 2つめのみを8ビット左に
Distance (0,0) = (int)(Bits[0] | Bits[1] << 8 );
    • DepthAndPlayerIndexタイプを使う場合
      • 1つめを3ビット右に(プレイヤーインデックスをスキップ)、2つめを5ビット左に
Distance (0,0) =(int)(Bits[0] >> 3 | Bits[1] << 5);
    • 今回の例は、PlayerIndexは使わないため以下
private int GetDistance(byte firstFrame, byte secondFrame)
{
    int distance = (int)(firstFrame | secondFrame << 8);
    return distance;
}

深度マップのカラー設定

  • 範囲の設定には2つのスライダーを使用。
  • スライダーの関数の例
private void slider2_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (slider2.Value <= slider1.Value) //minがmaxを越えないためのチェック
        slider2.Value = slider1.Value + 10;
    maxRange = slider2.Value;

}
  • スライダーで指定した最大深度max、最小深度minの差から範囲を決定し、色の濃さを決定

255 * (distance - min)/(max - min)

  • それ以外の場所は白で表示
private byte[] GenerateColoredBytes(ImageFrame imageFrame)
{
    int height = imageFrame.Image.Height;
    int width = imageFrame.Image.Width;

    //Depth data for each pixel
    Byte[] depthData = imageFrame.Image.Bits;

    //colorFrame contains color information for all pixels in image
    //Height x Width x 4 (Red, Green, Blue, empty byte)
    Byte[] colorFrame = new byte[imageFrame.Image.Height * imageFrame.Image.Width * 4];

    //hardcoded locations to Blue, Green, Red (BGR) index positions   
    const int BlueIndex = 0;
    const int GreenIndex = 1;
    const int RedIndex = 2;

    var depthIndex = 0;
    double range = maxRange - minRange;
    for (var y = 0; y < height; y++)
    {
        var heightOffset = y * width;


        for (var x = 0; x < width; x++)
        {
            var index = ((width - x - 1) + heightOffset) * 4;

            var distance = GetDistance(depthData[depthIndex], depthData[depthIndex + 1]);

            if (distance <= minRange || distance >= maxRange)
            {
                colorFrame[index + BlueIndex] = 255;
                colorFrame[index + GreenIndex] = 255;
                colorFrame[index + RedIndex] = 255;
            }
            else
            {
                byte tmp = (byte)(255 * (distance - minRange) / range);
                colorFrame[index + BlueIndex] = tmp;
                colorFrame[index + GreenIndex] = tmp;
                colorFrame[index + RedIndex] = 10;
            }


            //jump two bytes at a time
            depthIndex += 2;
        }
    }

    return colorFrame;
}

例:

  • 手前の椅子に範囲を

f:id:astrobot:20110701225047j:image

  • 後ろのツボに範囲を

f:id:astrobot:20110701225048j:image

  • 背景のカーテンに範囲を

f:id:astrobot:20110701225049j:image

データのcsv出力

using Microsoft.Win32;
  • 上記のライブラリーを参照し、その時点での深度マップをcsvで出力し保存

f:id:astrobot:20110701225050j:image

続き

Kinect関連記事

774774 2011/11/09 23:07 Kinect for Windows SDK 入門1-3まで一通りやりましたがここでつまずいてしまいました。
sliderの値や色の濃淡が反映されません。

astrobotastrobot 2011/11/10 14:58 スライダーの値が反映されないとのことですが、それぞれのスライダーの関数内でminRange、maxRangeの値を設定するようにしていますか?
一応例を追記しておきます。

wefwef 2015/07/15 13:28 はじめまして。最近kinectをいじりはじめ、lkinectで物の認識をしたくて、探していたところこの次の記事を見つけました。
しかし、1−3までの設定を行い、ここまできたところ、深度の変更を受け付けてくれませんでした。どこが原因かスライダー関数などなくし、極力簡単にして検証しても解決できなかったので、コメントに記載させていただきました。できれば、この記事と次の記事のソースコードをお教えしていただけないでしょうか?

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

リンク元