Kinect for Windows v2でプロ生ちゃんとベストショットを撮る方法

2014-07-17

先日の記事でも書きましたが、v2からは手の関節もトラッキングできるようになったため、「グー・チョキ・パー」も判別できるようになりました。

というわけで、FaceTracking機能と組み合わせて、「被写体が笑っている」かつ「どちらか一方の手がピースしている」時に写真を撮るサンプルを簡単に作成してみました。

またキャプチャした情報から被写体のみを抽出し、別の画像と合成してpngに出力してくれます。これをもう少し改良すれば、いつでもベストショットで写真が取れるようになるかも…?

FaceTrackingに関して

ボーンを取得・描画、それから被写体の抽出はほとんどサンプルと同様です。

今回はデフォルトのサンプルにはなかったFaceTrackingに関して説明します。

FaceTrackingの開始

FaceTrackingを開始するには、まずどの対象をトラッキングするかを設定する必要があります。そこで、BodyFrameからBodyを取得した際にTrackingIdというプロパティがありますので、それを用いてインスタンスを作成しています。

FaceTrackingの開始(VB)
1
2
3
4
5
6
7
Me.faceSource = New FaceFrameSource(Me.kinectSensor) With {
    .FaceFrameFeatures = FaceFrameFeatures.Happy,
    .TrackingId = body.TrackingId}
Me.faceReader = Me.faceSource.OpenReader
AddHandler Me.faceReader.FrameArrived, AddressOf OnFaceFrameArrived
AddHandler Me.faceSource.TrackingIdLost, AddressOf OnTrackingLost

FaceTrackingの開始(C#)
1
2
3
4
5
6
this.faceSource = new FaceFrameSource(this.kinectSensor) {
    FaceFrameFeatures = FaceFrameFeatures.Happy,
    TrackingId = body.TrackingId};
this.faceReader = this.faceSource.OpenReader();
this.faceReader.FrameArrived += OnFaceFrameArrived();
this.faceSource.TrackingIdLost += OnTrackingLost();

FaceFrameFeaturesには他にも以下のような項目があります。複数指定することも可能です。

Trackingデータの処理

無事にTrackingが成功すると、FrameArrivedイベントが発生します。(上記のコードでは、OnFaceFrameArrivedイベントハンドラが呼ばれています)この引数には結果が格納されています。

FaceFrameFeaturesの項目に関してはFacePropertiesプロパティで取得可能です。結果にはYes,Maybe,No,Unknownが返ってきます。

Trackingデータの処理(VB)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Private Sub OnFaceFrameArrived(sender As Object, e As FaceFrameArrivedEventArgs)
    Dim faceFrame = e.FrameReference.AcquireFrame

    If faceFrame IsNot Nothing Then
        Dim result = faceFrame.FaceFrameResult.FaceProperties(FaceProperty.Happy)
        If result = DetectionResult.Yes Or result = DetectionResult.Maybe Then
            CreateSnapShot()
        End If
    End If

End Sub

Trackingデータの処理(C#)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private void OnFaceFrameArrived(Object sender,FaceFrameArrivedEventArgs e)
{
    var faceFrame = e.FrameReference.AcquireFrame();

    if (faceFrame != null)
    {
        var result = faceFrame.FaceFrameResult.FaceProperties(FaceProperty.Happy);
        if (result == DetectionResult.Yes || result == DetectionResult.Maybe)
            CreateSnapShot();
    }
}

今回作成したプログラムは、条件が揃った際にスナップショットを作成しますが、その際一瞬にして同じような画像が大量に保存されてしまうことを防ぐため、この仕組みを用いて1トラッキングにつき1回までしか作成しないよう制限しています。(つまり「画面に写っている人が写真を撮ったら、その人が画面の外に出てもう一度中に入るなどをしてトラッキングを失わない限り、写真を撮らない」、ということを行っています)

Tracking対象を失ってしまった時の処理

画面外に移動した等の理由で対象を失ってしまった際には、TrackingIdLostイベントが発生します。(上記のコードでは、OnTrackingLostイベントハンドラが呼ばれています)

このイベントハンドラが取る引数eに、失ったTrackingId等が格納されているので、それを見て判別することが可能です。

対象を失ってしまった時の処理
1
2
3
4
5
6
7
8
Private Sub OnTrackingLost(sender As Object, e As TrackingIdLostEventArgs)
    Console.WriteLine(e.TrackingId)

    Me.faceReader = Nothing
    Me.faceSource = Nothing

End Sub

1
2
3
4
5
6
7
private void OnTrackingLost(Object sender,TrackingIdLostEventArgs e)
{
    Console.WriteLine(e.TrackingId);

    this.faceReader = null;
    this.faceSource = null;
}

注意事項

実はこれだけではプログラムは動かず、分析のためのデータベースが必要となります。(それがないと、Noという結果しか出ません)

そこで、ビルド後のアクションにNUIDatabaseを出力フォルダにコピーするコマンドが実行されるよう、設定する必要があります。

ビルド後のアクション
1
xcopy "C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\Microsoft.Kinect.Face\2.0\Redist\CommonConfiguration\x64\NuiDatabase" "NuiDatabase" /e /y /i /r

サンプル

動作画面のサンプルを以下に掲載します。(一人暮らしで家が狭いため、障害物も多く全身が入りきっていません)

右手でピースをした時に反応している

右手でピースをした時に反応している

パーでは何も反応しない

パーでは何も反応しない

笑うとHappyとして認識される

笑うとHappyとして認識される

笑いながらピースで記念撮影

笑いながらピースで記念撮影

このような画像が保存されます

このような画像が保存されます

コード

以下のページで公開しています。基本的にボーンの作成等はサンプルと同様ですので、そちらを見たほうがよいでしょう。

GitHub – KinectCameraSample

また今回背景の画像は プログラミング生放送勉強会よりプロ生ちゃんを使用させていただきました。(許可は頂いております)

可愛い女の子とベストショットで写真を撮ることができるなんて、まるで夢のようですね!

このエントリーをはてなブックマークに追加
« Kinect for Windows v2.0 オープンベータ版で遊んでみました スマートニュース株式会社でインターンしてきました »