書籍転載:KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版(5)
Kinect WPF ControlsでWPFアプリでもジェスチャーを活用しよう
― Chapter 4 応用機能 4.3 ―
WPFアプリにKinectを操作するための機能を実装する場合にはKinect WPF Controlsが便利だ。その機能概要を紹介する。
第1回~前回では、UnityでKinectを活用する方法を解説しました。今回は、UnityではなくWPFアプリでKinectを活用したい方に向けて、Kinect WPF Controlsの概要と基本的な活用方法を解説します。
書籍転載について
本コーナーは、秀和システム発行の書籍『KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。
『KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版』の詳細や購入は秀和システムのサイトや目次ページをご覧ください。プログラムのダウンロードも、秀和システムのサイトから行えます。
ご注意
本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。
■
4.3 Kinect WPF Controlsを使う
Kinect WPF Controlsを使うと、WPFアプリケーションへ簡単にKinectで操作できる機能を持たせることができます。Kinect操作の対象となるエリアを限定できるので、細かい設定操作はマウスに任せるなど柔軟なKinectアプリケーションが開発できます。
4.3.1 ハンドポインターとジェスチャー
Kinect WPF Controlsには下のようなポインターが付属しています。
ポインターの形の通り、手の動きでこのポインターを操作することになります。Kinectを使うときは画面から離れていることが多く、またKinectで認識される手の位置はマウスよりも精度がかなり落ちますからマウスポインターよりかなり大きなもの(80×80ピクセル程度)となっています。
エンゲージング
誰のどの手(右手または左手)をハンドポンターに結合(エンゲージ)させるかを設定する操作です。標準では手のひらを前に向けて体の前に置くジェスチャーでエンゲージングが行われますが、手を上げるなど他のジェスチャーでエンゲージしたければKinectRegion.SetOnePersonManualEngagementメソッドを用います。
http://www.microsoftvirtualacademy.com/training-courses/programming-kinect-for-windows-v2-jump-start
ターゲティング
開いた手を動かしてハンドポインターを目的の位置まで動かすことを言います。手をどれだけ動かせばよいかはハンドポインターが動ける範囲とPHIZ(Physical Interaction Zone)によって決まります。PHIZはMicrosoftの用語ですが、大まかにはその場から動かず、また関節に負担をかけることなく右手または左手が動かせる範囲を言います。
http://www.microsoftvirtualacademy.com/training-courses/programming-kinect-for-windows-v2-jump-start
4.3 Kinect WPF Controlsを使う
プレス
手のひらを前に突き出すことでハンドポインターが乗っているボタンやタイルをクリックすることを言います。プレスとなる付近まで手のひらを出すとハンドポインターの色が徐々に変わるので意図しないプレスを防ぐことができます。プレスをするときは手を動かすことになりますので、ハンドポインターの位置はどうしても少しはぶれてしまいます。Microsoftではプレスするボタンやタイルは208×208以上のサイズにすることを推奨しています。
グリップ/アングリップ
ハンドポインターが乗っているオブジェクトを、手を握る(グリップ)ことでつかんで動かすジェスチャーです。手を握ったまま動かし、手を開いて(アングリップ)解放します。ScrollViewerの子を動かすことでパンしたり、ドラッグアンドドロップを行ったりすることができます。握った手を前後に動かすことで拡大縮小を行うことも考えられます。
4.3.2 実行結果
このプログラムを実行すると下のような簡単な図形とプレイヤーのシルエットが表示されます。左のグレーのボタンにターゲッティングしてプレスを行うと”Press Me!”という文字列が“Pressed!”に変わり、右の緑の正方形はグリップ・アングリップで自由に動かすことができます。また、何も見えない白い部分をグリップ・アングリップすれば左右のパンを行うことができます。
4.3.3 プロジェクトの設定
Kinect WPF Controlsを利用するためには以下の設定が必要になります。
C#
プロジェクトの「参照設定」を右クリックし、「参照の追加」をクリックします。参照マネージャーから「Microsoft.Kinect.Wpf.Controls」を追加します。
4.3.4 解説
ボタンをプレスできるようにするだけならば、XAMLの中にKinectRegionというコントロールを置き、その子にボタンを配置するだけです。
usingディレクティブ
追加で使用する名前空間を指定します。
using Microsoft.Kinect;
using Microsoft.Kinect.Wpf.Controls;
|
<Window x:Class="KinectV2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Kinect for Windows SDK v2" SizeToContent="WidthAndHeight"
Loaded="Window_Loaded" Closing="Window_Closing"
xmlns:k="http://schemas.microsoft.com/kinect/2014"
xmlns:kinectV2="clr-namespace:KinectV2">
<StackPanel Orientation="Vertical">
<k:KinectUserViewer HorizontalAlignment="Left" Width="80" Height="60" />
<k:KinectRegion Name="kinectRegion" Width="800" Height="600">
<ScrollViewer HorizontalScrollBarVisibility="Visible">
<Canvas Width="1600">
<kinectV2:DragDropDecorator Canvas.Left="400" Canvas.Top="0">
<Rectangle Width="300" Height="300" Fill="Green" />
</kinectV2:DragDropDecorator>
<Button Name="btn" Click="Button_Click" FontSize="20"
Content="Press Me!" Width="300"
Height="300"></Button>
</Canvas>
</ScrollViewer>
</k:KinectRegion>
</StackPanel>
</Window>
|
KinectUserViewerはユーザーのシルエットを表示できるコントロールです。KinectRegionがハンドポインターの動く範囲で、その中にあるコントロールがKinect操作の対象となります。この2つをStackPanelで縦に並べてあります。DragDropDecoratorはCanvasの中に配置されるカスタムコントロールで、子のRectangleをグリップ・アングリップでドラッグアンドドロップできるようにする機能を持ちます。
DragDropDecorator, DragDropDecoratorControllerクラス
public class DragDropDecorator : Decorator, IKinectControl
{
public bool IsManipulatable
{
get
{
return true;
}
}
public bool IsPressable
{
get
{
return false;
}
}
public IKinectController CreateController( IInputModel inputModel, KinectRegion kinectRegion)
{
return new DragDropDecoratorController( inputModel, kinectRegion );
}
}
class DragDropDecoratorController:IKinectManipulatableController
{
private ManipulatableModel _inputModel;
private KinectRegion _kinectRegion;
private DragDropDecorator _dragDropDecorator;
bool _disposed = false ;
//コンストラクタ
public DragDropDecoratorController( IInputModel inputModel, KinectRegion kinectRegion)
{
_inputModel = inputModel as ManipulatableModel;
_kinectRegion = kinectRegion;
_dragDropDecorator = inputModel.Element as DragDropDecorator;
_inputModel.ManipulationUpdated += inputModel_ManipulationUpdated;
}
//DragDropDecoratorのCanvas.Top,Canvas.Leftプロパティを更新
void inputModel_ManipulationUpdated( object sender, Microsoft.Kinect.Input.KinectManipulationUpdatedEventArgs e )
{
//DragDropDecoratorの親はCanvas
Canvas canvas = _dragDropDecorator.Parent as Canvas;
if (canvas!=null) {
double y = Canvas.GetTop( _dragDropDecorator );
double x = Canvas.GetLeft( _dragDropDecorator );
if ( double.IsNaN( x ) || double.IsNaN( y ) )
return;
PointF delta = e.Delta.Translation;
//deltaは-1.0..1.0の相対値で表されているので
//KinectRegionに合わせて拡大
var Dy = delta.Y*_kinectRegion.ActualHeight;
var Dx = delta.X*_kinectRegion.ActualWidth;
Canvas.SetTop( _dragDropDecorator, y+Dy );
Canvas.SetLeft( _dragDropDecorator, x+Dx );
}
}
FrameworkElement IKinectController.Element
{
get
{
return _inputModel.Element as FrameworkElement;
}
}
ManipulatableModel IKinectManipulatableController.ManipulatableInputModel
{
get
{
return _inputModel;
}
}
void System.IDisposable.Dispose()
{
if ( !_disposed ) {
_kinectRegion = null;
_inputModel = null;
_dragDropDecorator = null;
_inputModel.ManipulationUpdated -= inputModel_ManipulationUpdated;
_disposed = true;
}
}
}
|
DragDropDecoratorクラスはIKinectControlを継承してIsManipulatableをtrueに設定し、CreateControllerメソッドがIKinectManipulatableControllerを継承したクラス(DragDropDecoratorController)のインスタンスを返すようにします。
DragDropDecoratorControllerのinputModel変数のManipulationUpdatedイベントでコントロールが動くようにイベントハンドラを書いています。なお、プレスできるカスタムコントロールを作るにはIsPressableの方をtrueにしてIKinectPressableContorollerを継承したコントローラクラスを作ってやればOKです。
初期化
KinectUserViewerがKinectRegionを見つけられるよう、MainWindowにkinectRegionを割り付けます。kinectRegionにKinectSensorを設定します。
void InitializeKinectControls()
{
KinectRegion.SetKinectRegion( this, kinectRegion );
this.kinectRegion.KinectSensor = KinectSensor.GetDefault();
}
|
■
次回からは、「Chapter 8 Kinectで学ぶ数学」を全て転載します。お楽しみに。
※以下では、本稿の前後を合わせて5回分(第3回~第7回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
3. Kinectの座標とUnityの座標を合わせる
UnityでKinectを使う際にポイントとなる、Kinectの座標系とUnityの座標系を合わせる方法を、実際のサンプルコードを通して説明する。