必要なもの
1) キネクト
2) Visual Studio
3) Kinect for Windows SDK v1.7
4) Kinect PowerPoint Control
Kinect PowerPoint Control の概要
結局のところ、Kinect の基本的な機能のとても簡単なサンプルです( 音声認識部分もありますが、日本語がどうかわからないので試していません )。
Power Point での使用を想定して作られたようですが、右手が頭より、X 軸で(外側に) 45センチ離れたら 右矢印キーを押し、左手が頭より、X 軸で(外側に) 45センチ離れたら 左矢印キーを押すという機能のみ実装されています。
ここでは、3箇所しか認識させていませんが、同様にして 20箇所の人体の部分を認識可能です。
なので、少しコードを触るだけで、ジェスチャーによるキーコマンドをいくつでも追加できます。そして、ブラウザ側では、jQuery を使って .keydown で受ければいろいろな画面展開が可能になるでしょう。
コマンド受付部分(ここを改造)
private void ProcessForwardBackGesture(Joint head, Joint rightHand, Joint leftHand)
{
// 頭と右手が x 座標で 45 センチ離れた場合に 右矢印キーを押した事にする
if (rightHand.Position.X > head.Position.X + 0.45)
{
if (!isForwardGestureActive)
{
isForwardGestureActive = true;
System.Windows.Forms.SendKeys.SendWait("{Right}");
}
}
else
{
isForwardGestureActive = false;
}
// 頭と左手が x 座標で 45 センチ離れた場合に 左矢印キーを押した事にする
if (leftHand.Position.X < head.Position.X - 0.45)
{
if (!isBackGestureActive)
{
isBackGestureActive = true;
System.Windows.Forms.SendKeys.SendWait("{Left}");
}
}
else
{
isBackGestureActive = false;
}
}
※ 各コマンド用のフラグは MainWindow クラスの変数として追加定義します
実際動かすと良く解りますが、頭と手が認識されると赤い丸が表示され、コマンドを送れる位置に移動すると大きな緑の丸に変化します。コマンドは、いったん赤い丸に戻してからでないと、再度実行する事はできません。
また、認識には少なくとも 150センチ離れる必要があり、C キーで認識円の表示を消す事ができるようです。
画面定義
<Window x:Class="KinectPowerPointControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Kinect PowerPoint Control"
Height="480"
Width="640"
WindowState="Maximized">
<Viewbox Stretch="Uniform">
<Grid>
<Image Name="videoImage"
Width="640"
Height="480"></Image>
<Canvas Background="Transparent">
<Ellipse Fill="Red"
Height="20"
Width="20"
Name="ellipseLeftHand"
Stroke="White" />
<Ellipse Fill="Red"
Height="20"
Width="20"
Name="ellipseRightHand"
Stroke="White" />
<Ellipse Fill="Red"
Height="20"
Width="20"
Name="ellipseHead"
Stroke="White" />
</Canvas>
</Grid>
</Viewbox>
</Window>
※ videoImage に、映像が表示され、最初左上に赤い丸が表示されています。
プログラムの中核となる部分
void sensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (var skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame == null)
return;
if (skeletons == null ||
skeletons.Length != skeletonFrame.SkeletonArrayLength)
{
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
}
skeletonFrame.CopySkeletonDataTo(skeletons);
}
Skeleton closestSkeleton = skeletons.Where(s => s.TrackingState == SkeletonTrackingState.Tracked)
.OrderBy(s => s.Position.Z * Math.Abs(s.Position.X))
.FirstOrDefault();
if (closestSkeleton == null)
return;
// 頭
var head = closestSkeleton.Joints[JointType.Head];
// 右手
var rightHand = closestSkeleton.Joints[JointType.HandRight];
// 左手
var leftHand = closestSkeleton.Joints[JointType.HandLeft];
// NotTracked : 追跡していない
if (head.TrackingState == JointTrackingState.NotTracked ||
rightHand.TrackingState == JointTrackingState.NotTracked ||
leftHand.TrackingState == JointTrackingState.NotTracked)
{
//Don't have a good read on the joints so we cannot process gestures
return;
}
// MainWindow.xaml に定義された ellipse
SetEllipsePosition(ellipseHead, head, false);
SetEllipsePosition(ellipseLeftHand, leftHand, isBackGestureActive);
SetEllipsePosition(ellipseRightHand, rightHand, isForwardGestureActive);
ProcessForwardBackGesture(head, rightHand, leftHand);
}
二つのフラグが立って初めてコマンドを送れるようにも出来ますし、20箇所の場所を使えばいろいろかなりコマンドを作れると思います。また、ブラウザ上の位置とキネクトの座標とを同期させてコマンドを発動する事もできるでしょう。