

[Azure Kinect DK] Quickstart: Build an Azure Kinect body tracking application (C#版)
ソリューション開発部 中川です。
前回の[Azure Kinect DK] Quickstart: Build your first Azure Kinect application (C#版) に続いて、Body Trackingアプリケーションのクイックスタートを実装してみたいと思います。
公式ドキュメントとして公開されているQuickstart: Build an Azure Kinect body tracking applicationについて、日本語訳が追加されていますが、まだC#コードは反映されていませんので、今回もC#コードに変更したものを紹介します。
今回はAzure Kinect Body Trackingアプリのプロジェクト作成を行い、 Azure Kinect との接続、Azure KinectカメラからBody Trackingの骨格情報を取得するところがゴールです。
Quickstart: Build an Azure Kinect body tracking application
前提条件
まず、前回の[Azure Kinect DK] Quickstart: Build your first Azure Kinect application (C#版) を完了していることを前提とします。Body Tracking SDK を設定するを参照して、Body Tracking SDKのセットアップを完了してください。
Visual Studio プロジェクトの準備
Visual Studioからコンソールアプリの新規プロジェクトを作成してください。
「 ツール 」 ⇒ 「 Nugetパッケージマネージャー 」 ⇒ 「 パッケージマネージャーコンソール 」 を開いてください。
Azure Kinect Sensor SDKの追加
PM> Install-Package Microsoft.Azure.Kinect.Sensor
Azure Kinect BodyTracking SDKの追加
PM> Install-Package Microsoft.Azure.Kinect.BodyTracking
ヘッダー
using Microsoft.Azure.Kinect.Sensor;
using Microsoft.Azure.Kinect.BodyTracking;
デバイスを開いてカメラを起動する
Azure KinectデバイスのOpenからStartCameraまでは、Sensor SDKの時と同じです。
BodyTrackingを有効にするためには、Configurationにいくつか注意が必要です。
最良の結果を得るには、深度モードを
クイック スタート:体をトラッキングする Azure Kinect アプリケーションの作成DepthMode.NFOV_Unbinned
またはDepthMode.WFOV_2x2Binned
に設定します。 深度モードがDepthMode.Off
またはDepthMode.PassiveIR
に設定されている場合、体のトラッカーは実行されません。
以下のコードでは、Kinectが1台接続されている前提で、デバイスを開いてカメラを起動するところまで記述しています。
//接続されている機器の数をチェック
if (Device.GetInstalledCount() == 0)
{
Console.WriteLine("No k4a devices attached!");
Console.ReadKey();
return;
}
//■デバイスを開いてカメラを起動する
Device device = null;
// Open the first plugged in Kinect device
try
{
//1台目に接続
device = Device.Open(0);
}
catch (AzureKinectOpenDeviceException ex)
{
Console.WriteLine("Failed to open k4a device!!");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace.ToString());
Console.ReadKey();
return;
}
// Start camera. Make sure depth camera is enabled.
var deviceConfig = new DeviceConfiguration();
deviceConfig.DepthMode = DepthMode.NFOV_Unbinned;
deviceConfig.ColorResolution = ColorResolution.Off;
try
{
device.StartCameras(deviceConfig);
}
catch (AzureKinectStartCamerasException ex)
{
Console.WriteLine("Failed to open k4a device!!");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace.ToString());
device.Dispose();
Console.ReadKey();
return;
}
トラッカーを作成する
トラッキングデータを取得するためのトラッカーを作成します。
使用後に開放し忘れないようusingで使用するのがよいと思います。
また、BodyTrackingの必須動作環境にNvidia GTX 1070以上の GPUが掲載されていますが、GPUがないPCの場合はCPUモードで起動することで動作させることができます。
(動作はしますが非常に重いのでおススメしません。)
//■トラッカーを作成する
var calibration = device.GetCalibration(deviceConfig.DepthMode, deviceConfig.ColorResolution);
var trackerConfig = new TrackerConfiguration();
trackerConfig.ProcessingMode = TrackerProcessingMode.Gpu; //GPUがない場合はCpuを指定
trackerConfig.SensorOrientation = SensorOrientation.Default;
using(var tracker = Tracker.Create(calibration, trackerConfig))
{
//ここにトラッキングデータ処理を記述
}
Azure Kinect デバイスからキャプチャを取得する
// Capture a depth frame
using (Capture sensorCapture = device.GetCapture())
{
//ここにキャプチャを使った処理を記述
}
キャプチャをエンキューして結果をポップする
トラッカーでは、Azure Kinect DK キャプチャをより効率的に非同期で処理するために、入力キューと出力キューを内部で保持します。 次の手順では、
クイック スタート:体をトラッキングする Azure Kinect アプリケーションの作成Tracker.EnqueueCapture()
関数を使用して、新しいキャプチャを入力キューに追加します。 出力キューから結果をポップするには、Tracker.PopResult()
関数を使用します。 タイムアウト値はアプリケーションによって異なり、キューの待機時間を制御します。
EnqueueCaptureした後はCaptureは不要になるので、忘れずに開放されるようにしましょう。
// Capture a depth frame
using (Capture sensorCapture = device.GetCapture())
{
// Queue latest frame from the sensor.
tracker.EnqueueCapture(sensorCapture);
}
// Try getting latest tracker frame.
using (Frame frame = tracker.PopResult(TimeSpan.Zero, throwOnTimeout: false))
{
if (frame != null)
{
//ここにPopした結果の処理を記述
}
}
体のトラッキング結果データにアクセスする
Popしたデータは、Frameインスタンスとして取得できます。Frameには骨格データや2Dのインデックスマップなどが格納されています。
これらのデータは複数人がTrackingできた場合は、人数分のデータが格納されます。
以下のコードでは、一人目の骨格データから、Headジョイントの位置情報を取得します。
// Try getting latest tracker frame.
using (Frame frame = tracker.PopResult(TimeSpan.Zero, throwOnTimeout: false))
{
if (frame != null)
{
Console.WriteLine("NumberOfBodies : " + frame.NumberOfBodies);
if(frame.NumberOfBodies > 0)
{
var skeleton = frame.GetBodySkeleton(0); //最初のスケルトンを取得
var headJoint = skeleton.GetJoint(JointId.Head); //HeadのJointを取得
Console.WriteLine(" Head : x=" + headJoint.Position.X + ",y=" + headJoint.Position.Y + ",z=" + headJoint.Position.Z);
}
}
}
骨格データ
Azure Kinectで取得できる骨格データについてはAzure Kinect body tracking jointsを参照してください。
各ジョイントはSkeleton.GetJoint()で取得できます。引数のJointIdはenum JointIdで定義されています。
クリーンアップ
device.StopCameras();
device.Dispose();
Full Code
クイックスタートでは取得したBodyTrackingデータの処理は何も記述されていません。
これだけだと寂しいので、BodyTrackingデータからHeadジョイントの3次元座標を取得して、コンソールに出力する処理を追加します。
1回のPop処理ごとにReadKey()でwaitさせて、Escキーで終了、それ以外のキーで次のEnqueue & Popを行うようにします。
以下が、すべてのコードです。
using System;
using Microsoft.Azure.Kinect.Sensor;
using Microsoft.Azure.Kinect.BodyTracking;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start My First Body Tracking App!");
//接続されている機器の数をチェック
if (Device.GetInstalledCount() == 0)
{
Console.WriteLine("No k4a devices attached!");
Console.ReadKey();
return;
}
//■デバイスを開いてカメラを起動する
Device device = null;
// Open the first plugged in Kinect device
try
{
//1台目に接続
device = Device.Open(0);
}
catch (AzureKinectOpenDeviceException ex)
{
Console.WriteLine("Failed to open k4a device!!");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace.ToString());
Console.ReadKey();
return;
}
// Start camera. Make sure depth camera is enabled.
var deviceConfig = new DeviceConfiguration();
deviceConfig.DepthMode = DepthMode.NFOV_Unbinned;
deviceConfig.ColorResolution = ColorResolution.Off;
try
{
device.StartCameras(deviceConfig);
}
catch (AzureKinectStartCamerasException ex)
{
Console.WriteLine("Failed to open k4a device!!");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace.ToString());
device.Dispose();
Console.ReadKey();
return;
}
//■トラッカーを作成する
var calibration = device.GetCalibration(deviceConfig.DepthMode, deviceConfig.ColorResolution);
var trackerConfig = new TrackerConfiguration();
trackerConfig.ProcessingMode = TrackerProcessingMode.Gpu; //GPUがない場合はCpuを指定
trackerConfig.SensorOrientation = SensorOrientation.Default;
using(var tracker = Tracker.Create(calibration, trackerConfig))
{
var wantExit = false;
while (!wantExit)
{
//■Azure Kinect デバイスからキャプチャを取得する
// Capture a depth frame
using (Capture sensorCapture = device.GetCapture())
{
// Queue latest frame from the sensor.
tracker.EnqueueCapture(sensorCapture);
}
// Try getting latest tracker frame.
using (Frame frame = tracker.PopResult(TimeSpan.Zero, throwOnTimeout: false))
{
if (frame != null)
{
Console.WriteLine("NumberOfBodies : " + frame.NumberOfBodies);
if(frame.NumberOfBodies > 0)
{
var skeleton = frame.GetBodySkeleton(0); //最初のスケルトンを取得
var headJoint = skeleton.GetJoint(JointId.Head); //HeadのJointを取得
Console.WriteLine(" Head : x=" + headJoint.Position.X + ",y=" + headJoint.Position.Y + ",z=" + headJoint.Position.Z);
}
}
}
//キー押下で続行。Escキーで終了
Console.WriteLine("Press Esc to Exit. Any other key to continue.");
var key = Console.ReadKey();
if (key.Key.Equals(ConsoleKey.Escape)) wantExit = true;
}
}
device.StopCameras();
device.Dispose();
}
}
}
実行すると、↓のような結果が得られます。
頭の位置をいろいろ動かして、数値が変化することを確認してみてください。


Next Step
これでAzure Kinect Body Trackingアプリの基本中の基本を実装できることができました。次のステップとしておススメなのは、公式のGitHubに公開されているサンプルを読み込むことです。
C++のサンプルがほとんどですが、「Azure-Kinect-Samples/body-tracking-samples/csharp_3d_viewer/」にC#のサンプルがあります。
今後もAzure Kinect DKを用いたアプリ開発のTIPSを紹介していく予定です。