NtKinectを利用して OpenCV や Kinect V2 の基本的機能を使う DLL ファイルを作成し、 他の自作のプログラムや Unity から利用する方法は 「NtKinect: Kinect V2 を使うプログラムをDLL化してUnityから利用する」 で説明しました。
さて、Kinect V2 で顔認識、音声認識、ジェスチャー認識を行うプログラムは、 それぞれの機能に対応した 既存のDLL ファイルを実行時に必要とします。 このように「Kinect V2 の機能のうち既存のDLLファイルを必要とする機能を 自作のプログラムで利用した場合に、その自作プログラムを DLL 化して Unity をはじめとする 他のプログラムから利用する方法」について本稿で解説します。
本稿では、顔認識を行う DLL ファイルを作成する方法について解説します。
では実際に既存の DLL ファイルを必要とする Kinect V2 の例として、 顔認識を行う DLL ライブラリを作成してみましょう。
「構成プロパティ」 -> 「リンカー」 -> 全般 -> 入力
Kinect20.Face.lib
マゼンタ色の部分が今回追加した関数のプロトタイプ宣言です。
NtKinectDll.h |
|
顔認識を使うので、NtKinect.h を include する前にUSE_FACEマクロをdefineします。 このマクロをdefineした場合は Kinect20.Face.lib ライブラリをリンクする必要があるので注意して下さい。
int faceDirection(void *, float *data) 関数の定義を追加します。 この関数ではまず、 カメラで取得した画像を1/16に縮小してその上に関節を赤で描画して、 さらに認識できた顔領域に矩形を描画してからcv::imshow()で表示しています。 ウィンドウの内容を正しく表示させるためにはcv::waitKey(1)を呼び出す必要があります。 顔の向きは pitch, yaw, roll の3通りのfloat値で、それが最大で6人分なので、 data 領域はこの関数を呼び出す側で 「floatのバイト数 * 3 * 6 」バイト以上確保されている必要があります。 返り値は、向きを認識できた顔の個数です。
NtKinectDll.cpp |
|
[注意](2017/10/07 追記) Visual Studio 2017 Update 2 でのビルド時に「dllimport ...」というエラーが起きる場合は こちらを参考にして NtKinectDll.cpp 内で NTKINECTDLL_EXPORTS をdefineする ことで対処して下さい。
上記のzipファイルには必ずしも最新の NtKinect.h が含まれていない場合があるので、 こちらから最新版をダウンロードして 差し替えてお使い下さい。
生成したDLLファイルが正しく動作することを確認する簡単なプロジェクトを作成しましょう。
プロジェクトの stdafx.cpp や CheckDLL.cpp が置かれているフォルダに古いNtKinectDll.hが あるはずですが、その上に新しい NtKinectDll.h をコピーします。
プロジェクトの stdafx.cpp や CheckDLL.cpp が置かれているフォルダに 古いNtKinectDll.dll と NtKinectDll.lib があるはずですが、その上に新しい NtKinectDll.dll と NtKinectDll.lib をコピーします。
プロジェクトの stdafx.cpp や CheckDLL.cpp が置かれているフォルダに、 $(KINECTSDK20_DIR)Redist\Face\x64\ の下のファイルを全てコピーします。 標準の設定だと $(KINECTSDK20_DIR)は C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\ になっているはずです(「v2.0_バージョン番号」の部分はお使いのSDK のバージョンにより異なります)。
$(KINECTSDK20_DIR)Redist\Face\x64\NuiDatabase\ \Kinect20.Face.lib \Microsoft.Kinect.Face.lib \Microsoft.Kinect.Face.xml |
int faceDirection(void* ptr,float* data) の返り値は、向きが認識できた顔の個数です。 一人の顔の向きは pitch, yaw, row の3個のfloatで表されます。 最大で6人を同時認識することがあるので 6*3 個のfloatのための領域を配列で確保しています。
CheckDLL.cpp |
|
NtKinectDll.dll を Unityで利用します。
上部のメニューから「Game Object」-> 「3D Object」 -> 「Cube」
6個のCubeの位置を変更します。カメラはCubeを前から見るような位置にします(デフォルトのままでOKです)。
name | Position | Rotation | Scale | ||||||
---|---|---|---|---|---|---|---|---|---|
x | y | z | x | y | z | x | y | z | |
Cube0 | -5 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
Cube1 | -3 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
Cube2 | -1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
Cube3 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
Cube4 | 3 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
Cube5 | 5 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
Main Camera | 0 | 1 | -10 | 0 | 0 | 0 | 1 | 1 | 1 |
上部のメニューから「Assets」-> 「Create」 -> 「C# Script」 -> ファイル名は NtKinectBehaviour
C++ のポインタは C# では System.IntPtr として扱います。
NtKinectBehaviour.cs |
|
顔認識をしていても瞬間的に認識できなくなると立方体が激しく動いて見辛いので、 10回連続で認識に失敗するときだけ追跡失敗とする簡便なエラー処理を 行っています(変数counter)。 本来は faceTrackingId を受け取って顔毎に判断すべきですが、 説明のコードが複雑になるのを避けるために簡単な方法に留めています。
[注意] 骨格や顔の認識状態を表示するためにDLL内でOpenCVのウィンドウを生成しています。 後から生成されたこのウィンドウにフォーカスがあるときは (= Unityのウィンドウにフォーカスがない場合は) Unityの画面は変化しないので注意して下さい。 Unityのウィンドウの上部をクリックしてUnityのウィンドウにフォーカスが ある状態で動作を試して下さい。