Members‎ > ‎Wataru-Fujimura‎ > ‎Kinect Tips‎ > ‎

骨格情報の取得

Windowsフォームアプリケーションでの骨格情報取得方法です。
今回は骨格の位置に円を描画します。
(作成日:2012/02/28)

1.プロジェクトを作る
2.参照設定を追加
3.アプリケーションのデザイン

実画像取得の時と同じようにしてください。



4.pictureBoxのpaintイベントを作る

pictureBoxのプロパティに雷のようなアイコンがあるのでクリック。



一番下までスクロールして[paint]の欄をダブルクリック。



するとソースコード上に自動でイベントが生成されます。


この部分で、骨格の位置を表す円を描画します。



5.プログラム

以下のコードのように入力してください

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

// ビットマップを生成するため
using System.Drawing.Imaging;

// Kinectのセンサクラス
// Microsoft.Kinectを参照に追加
using Microsoft.Kinect;

// メモリ管理の最適化のため
// System.Runtime.Serializationを参照に追加
using System.Runtime.InteropServices;

namespace formgetskeleton
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// kinectのセンサクラス
        /// </summary>
        KinectSensor kinect;

        /// <summary>
        /// kinectから取得したRGBデータ
        /// (byte型配列)
        /// </summary>
        byte[] imageData;

        /// <summary>
        /// 実画像
        /// (ビットマップ形式)
        /// </summary>
        Bitmap ImageBitmap;

        /// <summary>
        /// 骨格情報
        /// </summary>
        Skeleton[] skeletonData;

        public Form1()
        {
            InitializeComponent();
            // ピットマップの初期化
            ImageBitmap = new Bitmap(640, 480);

            // kinectの初期化
            kinect = KinectSensor.KinectSensors[0];

            // カラー画像の取得を開始する
            kinect.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(ColorImageReady);
            kinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);

            // スケルトントラッキングを開始する
            kinect.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(SkeletonFrameReady);
            kinect.SkeletonStream.Enable();

            // Kinectを起動する
            kinect.Start();
        }

        /// <summary>
        /// 生成されたpaintイベント
        /// </summary>
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            // skeletonDataがnullでない場合
            if (skeletonData != null)
            {
                foreach (var user in skeletonData)
                {
                    if (user.TrackingState == SkeletonTrackingState.Tracked)
                    {
                        foreach (Joint join in user.Joints)
                        {
                            // カラー画像のサイズにに合わせて骨格情報をXY座標に変換する
                            ColorImagePoint point = kinect.MapSkeletonPointToColor(join.Position, kinect.ColorStream.Format);

                            // 骨格情報を円で表示
                            // 円の中央を骨格の位置にするため、縦横の半分のサイズを引いておく
                            e.Graphics.FillEllipse(System.Drawing.Brushes.Red, point.X - 10, point.Y - 10, 20, 20);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// カラー画像の取得
        /// </summary>
        void ColorImageReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            // kinectからカラーイメージを取得
            ColorImageFrame image = e.OpenColorImageFrame();

            // imageがnullだった場合処理しない
            if (image != null)
            {
                // imageData配列の初期化
                imageData = new byte[image.PixelDataLength];

                // imageのピクセルデータをpixelDataへコピーする
                image.CopyPixelDataTo(imageData);

                // imageDataからビットマップへ変換する
                ImageBitmap = toBitmap(imageData, ImageBitmap.Width, ImageBitmap.Height);

                // ピクチャーボックスへ反映
                pictureBox1.Image = ImageBitmap;

            }
        }

        /// <summary>
        /// 骨格情報を取得する
        /// </summary>
        void SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            SkeletonFrame skeleton = e.OpenSkeletonFrame();

            if (skeleton != null)
            {
                skeletonData = new Skeleton[skeleton.SkeletonArrayLength];
                skeleton.CopySkeletonDataTo(skeletonData);
            }
        }

        /// 取得データをビットマップデータに変換
        /// </summary>
        /// <param name="pixels">kinectで取得したbyte[]配列</param>
        /// <param name="width">横サイズ</param>
        /// <param name="height">縦サイズ</param>
        /// <returns></returns>
        public static Bitmap toBitmap(byte[] pixels, int width, int height)
        {
            // pixelsに何も入っていない場合nullを返す
            if (pixels == null)
                return null;

            // ビットマップの初期化
            var bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);

            // システムメモリへロック
            var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);

            // メモリデータのコピー
            Marshal.Copy(pixels, 0, data.Scan0, pixels.Length);

            // システムメモリのロック解除
            bitmap.UnlockBits(data);

            return bitmap;
        }
    }
}





実行結果

このような感じで表示されるはずです(頭の位置は表示されていません)。
ユーザー認識は6人までできますが、骨格情報が取得できるのは2人までのようです。





画像のサイズに合ったXY座標変換は、深度画像のサイズに合わせても行うことができます。

座標変換

// カラー画像のサイズにに合わせて骨格情報をXY座標に変換する
ColorImagePoint point = kinect.MapSkeletonPointToColor(join.Position, kinect.ColorStream.Format);

                  ↓  ↓

// 深度画像のサイズにに合わせて骨格情報をXY座標に変換する
DepthImagePoint point = kinect.MapSkeletonPointToDepth(join.Position, kinect.DepthStream.Format);


また、3次元座標が直接ほしい場合は「 join.Position 」から取得できます。


ċ
formgetskeleton.zip
(46k)
Wataru Fujimura,
Feb 28, 2012, 4:46 AM
Comments