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 」から取得できます。