[Azure Kinect DK] Quickstart: Build an Azure Kinect body tracking application (C#版)

Azure Kinect DK,C#,Microsoft Azure,Microsoft Visual Studio,Mixed Reality

ソリューション開発部 中川です。

前回の[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にいくつか注意が必要です。

最良の結果を得るには、深度モードを DepthMode.NFOV_Unbinned または DepthMode.WFOV_2x2Binned に設定します。 深度モードが DepthMode.Off または DepthMode.PassiveIR に設定されている場合、体のトラッカーは実行されません。

クイック スタート:体をトラッキングする Azure Kinect アプリケーションの作成

以下のコードでは、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 キャプチャをより効率的に非同期で処理するために、入力キューと出力キューを内部で保持します。 次の手順では、Tracker.EnqueueCapture() 関数を使用して、新しいキャプチャを入力キューに追加します。 出力キューから結果をポップするには、Tracker.PopResult() 関数を使用します。 タイムアウト値はアプリケーションによって異なり、キューの待機時間を制御します。

クイック スタート:体をトラッキングする Azure Kinect アプリケーションの作成

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を紹介していく予定です。

  • Zabbix Enterprise Appliance
  • 低コスト・短納期で提供するまるごとおまかせZabbix