[Azure Kinect DK] Quickstart: Build your first Azure Kinect application (C#版)




ソリューション開発部 中川です。
Azure Kinect DK がいよいよ日本でも 2020年3月27日(金) に発売されました。
早速ソリューション開発部でも入手し、技術調査を始めています。
本体を入手したらまずはAzure Kinect DK documentationを読み込むところから始まります。クイックスタートとしてQuickstart: Build your first Azure Kinect applicationが用意されていますが、英語のみ、かつCのコードしか掲載されていません。
Azure Kinect Sensor SDK はC#対応に更新されている(一部の機能を除く)ので、今回は「 Quickstart: Build your first Azure Kinect application 」をC#コードでまとめてみます。
Azure Kinectアプリのプロジェクト作成を行い、 Azure Kinect との接続、Azure Kinectカメラからカラー画像を取得・保存するところがゴールです。
Quickstart: Build your first Azure Kinect application C#版
Azure Kinect DKを使い始めたい? このクイックスタートでデバイスを起動してみよう!
(本文ではAzureサブスクリプションを作成するよう促していますが、とりあえず起動するだけなら不要です。)
以下のFunctionをカバーしています:
- Microsoft.Azure.Kinect.Sensor.Device.GetInstalledCount()
- Microsoft.Azure.Kinect.Sensor.Device.Open()
- Microsoft.Azure.Kinect.Sensor.Device.StartCameras()
- Microsoft.Azure.Kinect.Sensor.Device.StopCameras()
前提条件
- Azure Kinect DK をセットアップしてください。
- Azure Kinect Sensor SDKをダウンロードしてインストールしてください。
Visual Studio プロジェクトの準備
Visual Studioからコンソールアプリの新規プロジェクトを作成してください。
「 ツール 」 ⇒ 「 Nugetパッケージマネージャー 」 ⇒ 「 パッケージマネージャーコンソール 」 を開いてください。
Azure Kinect Sensor SDKの追加
PM> Install-Package Microsoft.Azure.Kinect.Sensor -Version 1.4.0
System.Drauwingの追加 (Kinectから取得した画像処理のため)
PM> Install-Package System.Drawing.Common -Version 4.7.0
ヘッダー
using Microsoft.Azure.Kinect.Sensor;
Azure Kinect DK デバイスを見つける
複数の Azure Kinect DK デバイスを接続できます。まず最初に何台接続されているかを Microsoft.Azure.Kinect.Sensor.Device.GetInstalledCount() を使用して確認します。
このメソッドは特別なセットアップはなしですぐに動作します。
int count = Device.GetInstalledCount();
デバイスが接続されていることが確認出来たら、Microsoft.Azure.Kinect.Sensor.Device.Open() を使用して接続します。その際、接続する機器のIndexを指定できます。1台目に接続する場合は、0 を指定します。
//1台目に接続 Device device = Device.Open(0);
デバイスをOpen したあと、不要になったら忘れずに破棄するようにしましょう。
device.Dispose();
カメラを起動する
デバイスに接続したら、Microsoft.Azure.Kinect.Sensor.DeviceConfigurationオブジェクトでカメラ設定を定義する必要があります。カメラ設定にはさまざまなオプションがあるので、用途に合った設定を選びましょう。
//カメラを起動する device.StartCameras(new DeviceConfiguration { ColorFormat = ImageFormat.ColorBGRA32, //RGBカラーイメージ ColorResolution = ColorResolution.R720p, //解像度720p DepthMode = DepthMode.NFOV_Unbinned, //深度モード:NFOV Unbinned SynchronizedImagesOnly = true, //DepthイメージとColorイメージのシンクロされたイメージを取得 }); // ...Camera capture and application specific code would go here... // カメラを停止する device.StopCameras();
エラーハンドリング
注)この部分は原文の翻訳ではありません。
SDKを確認した限り用意されているExceptionは以下の通りです。
AzureKinectOpenDeviceException AzureKinectStartCamerasException AzureKinectStartImuException AzureKinectException
OpenDevice, StartCameras, StartImu はそれぞれの操作に対応しています。その他のErrorはAzureKinectExceptionで返されるのではないかと思われます。
まだ十分に確認できていませんが、Exceptionに含まれるDescriptionは「 K4A_FAILED
」としか書かれていないことも多く、うまくいかなかった時の原因の特定が難しい印象です。
この辺は今後の拡充に期待したいところです。
StartCameras() 後に適切にStopCameras() しないままエラーなどでプロセスが落ちてしまうと、Kinectカメラが起動したままになってしまい、他のプロセスからアクセスできなくなりUSBケーブルを抜き差しする必要があるので注意しましょう。
カメラからRGBイメージを取得する
注)この部分は原文の翻訳ではありません。
原文は「// …Camera capture and application specific code would go here…」と省略されており、カメラを起動して停止するだけのコードとなっています。
でもこれだけでは寂しいので、KinectからRGBイメージを取得してローカルディスクに保存するコードを追加します。
Kinect.ImageからBitMapへの変換はtks_yoshinagaさんの下記のブログ記事を参考にさせていただきました。
tks_yoshinagaさんの「 C#で始めるAzure Kinect開発 」シリーズはとても読みやすくわかりやすいのでおススメです。
コード
//カラー画像を取得して保存 var transform = device.GetCalibration().CreateTransformation(); var colorWidth = device.GetCalibration().ColorCameraCalibration.ResolutionWidth; var colorHeight = device.GetCalibration().ColorCameraCalibration.ResolutionHeight; Console.WriteLine("Get Capture."); using (var transformedDepth = new Image(ImageFormat.Depth16, colorWidth, colorHeight, colorWidth * sizeof(UInt16))) using (Capture capture = device.GetCapture()) { Console.WriteLine("Captured !!"); transform.DepthImageToColorCamera(capture, transformedDepth); unsafe { //カラー画像を取得 var colorImage = capture.Color; //画像のメモリのアドレスを取得 using (System.Buffers.MemoryHandle pin = colorImage.Memory.Pin()) { try { //Bitmap画像を作成 var colorBitmap = new System.Drawing.Bitmap( colorImage.WidthPixels, //カラー画像の横幅 colorImage.HeightPixels,//カラー画像の縦幅 colorImage.StrideBytes, //横一列のバイト数(width*4) System.Drawing.Imaging.PixelFormat.Format32bppArgb,//カラーフォーマット(RGBA) (IntPtr)pin.Pointer); //各ピクセルの色情報 //ファイルに保存 colorBitmap.Save(@"保存したいパス\" + System.DateTime.Now.ToString("yyyyMMddhhmmss") + ".png", System.Drawing.Imaging.ImageFormat.Png); } catch (Exception ex) { Console.WriteLine("Failed to Save Image!"); Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace.ToString()); } } } }
unsafeコードを使用するので、プロジェクトでアンセーフビルドを許可する設定を行います。プロジェクトプロパティの「ビルド」タブにて「アンセーフコードの許可(E)」にチェックを入れます。



FullCode
using System; using Microsoft.Azure.Kinect.Sensor; namespace SensorQuickStart { class Program { static void Main(string[] args) { //接続されている機器の数をチェック int count = Device.GetInstalledCount(); 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; } //カメラを起動 try { device.StartCameras(new DeviceConfiguration { ColorFormat = ImageFormat.ColorBGRA32, //RGBカラーイメージ ColorResolution = ColorResolution.R720p, //解像度720p DepthMode = DepthMode.NFOV_Unbinned, //深度モード:NFOV Unbinned SynchronizedImagesOnly = true, //DepthイメージとColorイメージのシンクロされたイメージを取得 }); } 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 transform = device.GetCalibration().CreateTransformation(); var colorWidth = device.GetCalibration().ColorCameraCalibration.ResolutionWidth; var colorHeight = device.GetCalibration().ColorCameraCalibration.ResolutionHeight; Console.WriteLine("Get Capture."); using (var transformedDepth = new Image(ImageFormat.Depth16, colorWidth, colorHeight, colorWidth * sizeof(UInt16))) using (Capture capture = device.GetCapture()) { Console.WriteLine("Captured !!"); transform.DepthImageToColorCamera(capture, transformedDepth); unsafe { //カラー画像を取得 var colorImage = capture.Color; //画像のメモリのアドレスを取得 using (System.Buffers.MemoryHandle pin = colorImage.Memory.Pin()) { try { //Bitmap画像を作成 var colorBitmap = new System.Drawing.Bitmap( colorImage.WidthPixels, //カラー画像の横幅 colorImage.HeightPixels,//カラー画像の縦幅 colorImage.StrideBytes, //横一列のバイト数(width*4) System.Drawing.Imaging.PixelFormat.Format32bppArgb,//カラーフォーマット(RGBA) (IntPtr)pin.Pointer); //各ピクセルの色情報 //ファイルに保存 colorBitmap.Save(@"保存したいパス\" + System.DateTime.Now.ToString("yyyyMMddhhmmss") + ".png", System.Drawing.Imaging.ImageFormat.Png); } catch (Exception ex) { Console.WriteLine("Failed to Save Image!"); Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace.ToString()); } } } } // Shut down the camera when finished with application logic device.StopCameras(); device.Dispose(); } } }
デフォルトの構成オプション「AnyCPU」では動作できないので、「x64」に切り替えて実行してください。指定したパスにpng画像ファイルが保存されます。
Next Step
これでAzure Kinectアプリの基本中の基本を実装できることができました。次のステップとしておススメなのは、公式のGitHubに公開されているサンプルを読み込むことです。
「 build2019/csharp 」の下にC#でのサンプルが用意されています。
次回は Azure Kinect Body Tracking SDK を使用して、「Quickstart: Build an Azure Kinect body tracking application」のC#版を投稿します。