Kinectで得た人体情報を転送して、Windows Phoneの画面上に関節の位置を表示してみる
プロジェクトの作成(Windows Phoneアプリケーション)
VS 2010のメニューから[ファイル(F)/新規作成(N)/プロジェクト(P)]と選択します。次に、「インストールされたテンプレート」から「Silverlight for Windows Phone」を選択し、右に表示される項目から「Windows Phone アプリケーション」を選択して、「名前(N)」に任意のプロジェクト名を指定します。ここでは「KINECT_WindowsPhone_Skeleton」という名前を付けています(図6)。Windows Phone OSのバージョンは7.1を選択します。
参照の追加
VS2010のメニューから「プロジェクト(P)/参照の追加(R)」と選択して、各種コンポーネントを追加しておきます。今回追加するのは、Coding4Fun.Kinect.KinectService.CommonとCoding4Fun.Kinect.KinectService.PhoneClientの2つです。「.NET」タブ内に表示されていないDLLファイルは「参照」タブからDLLファイルを指定します。
Coding4Fun.Kinect.KinectService.Common.dlとCoding4Fun.Kinect.KinectService.PhoneClient.dllは、kinectservice.zipを解凍したフォルダの、\KinectService\Phone Client\フォルダ内に存在しますので、これを指定してください。
コントロールの配置
ツールボックスからデザイン画面上にCanvasコントロールを1個、その子要素として、Imageを1個、Ellipseを10個配置します。次にCanvasの外にTextBlockを2個とButtonコントロールを1個配置します。書き出されるXAMLコードはリスト1、レイアウトは図7のようになります。EllipseのNameに指定している名前はリスト1を参照してください。
リスト1 (MainPage.xaml)
(1)x:NameがSkeletonという
<phone:PhoneApplicationPage x:Class="KINECT_WindowsPhone_Skeleton.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <!--LayoutRoot は、全てのページ コンテンツが配置されるルート グリッドです--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Canvas x:Name="Skeleton" Width="448" Height="336" Margin="12,108,20,324"> ■(1) <Image Height="336" Name="Image1" Stretch="Fill" Width="448" Canvas.Left="0" Canvas.Top="0" /> ■(1) <Ellipse Canvas.Left="0" Canvas.Top="0" Height="15" Name="headEllipse" Stroke="Black" Width="15" Fill="Orange" /> ■(2) <Ellipse Canvas.Left="15" Canvas.Top="0" Height="15" Name="rightEllipse" Stroke="Black" Width="15" Fill="SlateGray" /> ■(2) <Ellipse Canvas.Left="30" Canvas.Top="0" Height="15" Name="leftEllipse" Stroke="Black" Width="15" Fill="SpringGreen" /> ■(2) <Ellipse Canvas.Left="45" Canvas.Top="0" Height="15" Name="hipCenterEllipse" Stroke="Black" Width="15" Fill="Red" /> ■(2) <Ellipse Canvas.Left="60" Canvas.Top="0" Height="15" Name="ElbowRightEllipse" Stroke="Black" Width="15" Fill="Beige" /> ■(2) <Ellipse Canvas.Left="75" Canvas.Top="0" Height="15" Name="ElbowLeftEllipse" Stroke="Black" Width="15" Fill="Firebrick" /> ■(2) <Ellipse Canvas.Left="90" Canvas.Top="0" Height="15" Name="shoulderRightEllipse" Stroke="Black" Width="15" Fill="Bisque" /> ■(2) <Ellipse Canvas.Left="105" Canvas.Top="0" Height="15" Name="shoulderLeftEllipse" Stroke="Black" Width="15" Fill="Chartreuse" /> ■(2) <Ellipse Canvas.Left="120" Canvas.Top="0" Height="15" Name="HipRightEllipse" Stroke="Black" Width="15" Fill="Moccasin" /> ■(2) <Ellipse Canvas.Left="135" Canvas.Top="0" Height="15" Name="HipLeftEllipse" Stroke="Black" Width="15" Fill="MediumOrchid" /> ■(2) </Canvas> ■(1) <TextBlock Height="47" HorizontalAlignment="Left" Margin="15,487,0,0" Name="TextBlock1" Text="Address" VerticalAlignment="Top" Width="87" /> <TextBox Height="74" HorizontalAlignment="Left" Margin="87,473,0,0" Name="addressTextBox" VerticalAlignment="Top" Width="293" /> ■(3) <Button Content="OK" Height="74" HorizontalAlignment="Left" Margin="372,473,0,0" Name="okButton" VerticalAlignment="Top" Width="90" /> </Grid> ~コード略~ </phone:PhoneApplicationPage>
次に、ソリューションエクスプローラー内のMainPage.xamlを展開して表示される、MainPage.xaml.vbをダブルクリックしてリスト2のコードを記述します。
ロジックコードを記述する
リスト2 (MainPage.xaml.vb)
Option Strict On
KinectServiceに接続するための機能を提供する、2つの名前空間をインポートしておきます。
Imports Coding4Fun.Kinect.KinectService.Common Imports Coding4Fun.Kinect.KinectService.PhoneClient Partial Public Class MainPage Inherits PhoneApplicationPage ' コンストラクター Public Sub New() InitializeComponent() End Sub
リスナーに接続するためのクライアントであるSkeletonClientクラス型のメンバ変数_skeletonClientを宣言します。同様にColorClientクラス型のメンバ変数_colorClientを宣言します。
Dim _skeletonClient As SkeletonClient Dim _colorClient As ColorClient
[OK]ボタンがクリックされた時の処理
Address入力ボックスに入力されたIPアドレスを、変数myIPAddressに格納しておきます。IPアドレスが入力されていない場合は、警告メッセージを表示し、処理を抜けます。IPアドレスが入力されていたなら、新しいSkeletonClientのインスタンスとColorClientのインスタンスを作成します。ColorClientが接続されていなかった場合は、ConnectメソッドでIPアドレスとポートを指定して接続します。
SkeletonClientが接続されていなかった場合は、同じくConnectメソッドでIPアドレスとポートを指定して接続します。
AddHandlerステートメントでRGBカメラのフレームが更新された場合のイベントハンドラを追加します。同じく、スケルトンのフレームが更新された場合のイベントハンドラを追加します。
Private Sub okButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles okButton.Click Dim myIPAddress As String = addressTextBox.Text If myIPAddress = String.Empty Then MessageBox.Show("Addressを入力してください。") Exit Sub Else _skeletonClient = New SkeletonClient() _colorClient = New ColorClient()
If Not _colorClient.IsConnected Then _colorClient.Connect(myIPAddress, 4530) Else _colorClient.Disconnect() End If If Not _skeletonClient.IsConnected Then _skeletonClient.Connect(myIPAddress, 4532) Else _skeletonClient.Disconnect() End If AddHandler _colorClient.ColorFrameReady, AddressOf client_ColorFrameReady AddHandler _skeletonClient.SkeletonFrameReady, AddressOf client_SkeletonFrameReady End If End Sub
RGBカメラのフレームが更新された時に発生するイベント
Image1のSourceプロパティにRGBカメラのフレームをビットマップイメージに変換して表示します。
Private Sub client_ColorFrameReady(ByVal sender As Object, ByVal e As ColorFrameReadyEventArgs) If e.ColorFrame.BitmapImage IsNot Nothing Then Image1.Source = e.ColorFrame.BitmapImage End If End Sub
スケルトンフレームが更新された時に発生するイベント
Skeletonクラス用オブジェクト変数mySkeletonで、スケルトンデータを持つe.SkeletonFrame.Skeletons内で、全ての関節の位置がトラッキングされた状態にある、シーケンスの最初の要素を取得していきます。
頭、左手、右手、腰の中央、左肘、右肘、左肩、右肩、左腰、右腰の関節を取得し、各部位に該当する円を、身体の部位に収まるよう描画するSetEllpisePositionプロシージャを実行します。
Private Sub client_SkeletonFrameReady(ByVal sender As Object, ByVal e As SkeletonFrameReadyEventArgs) Dim mySkeleton As Skeleton = (From s In e.SkeletonFrame.Skeletons Where s.TrackingState = SkeletonTrackingState.Tracked Select s).FirstOrDefault() If mySkeleton Is Nothing Then Return End If SetEllipsePosition(headEllipse, mySkeleton.Joints(CInt(JointType.Head))) SetEllipsePosition(leftEllipse, mySkeleton.Joints(CInt(JointType.HandLeft))) SetEllipsePosition(rightEllipse, mySkeleton.Joints(CInt(JointType.HandRight))) SetEllipsePosition(hipCenterEllipse, mySkeleton.Joints(CInt(JointType.HipCenter))) SetEllipsePosition(ElbowLeftEllipse, mySkeleton.Joints(CInt(JointType.ElbowLeft))) SetEllipsePosition(ElbowRightEllipse, mySkeleton.Joints(CInt(JointType.ElbowRight))) SetEllipsePosition(shoulderLeftEllipse, mySkeleton.Joints(CInt(JointType.ShoulderLeft))) SetEllipsePosition(shoulderRightEllipse, mySkeleton.Joints(CInt(JointType.ShoulderRight))) SetEllipsePosition(HipLeftEllipse, mySkeleton.Joints(CInt(JointType.HipLeft))) SetEllipsePosition(HipRightEllipse, mySkeleton.Joints(CInt(JointType.HipRight))) End Sub
各円が身体の関節の位置に納まる処理
Canvas.SetLeftとSetTopプロパティの書式は下記です。
- Canvas.SetLeft(プロパティ値の書き込み対象の要素,指定した要素のCanvas.Left属性を設定)
- Canvas.SetTop(プロパティ値の書き込み対象の要素,指定した要素のCanvas.Top属性を設定)
448はImage1のWidth、336はImage1のHeightの値です。円の位置合わせのためにWidthとHeighの半分の値を加算しています。
Private Sub SetEllipsePosition(myEllipse As Ellipse, myJoint As Joint) Canvas.SetLeft(myEllipse, (448 * myJoint.Position.X) + 224) Canvas.SetTop(myEllipse, (336 * -myJoint.Position.Y) + 168) End Sub End Class
以上で今回のサンプルは終了です。
人間の関節情報をWindows Phoneに表示するサンプルプログラム
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Windows Phoneで自宅の様子をリモート監視するKinectプログラムを作ってみる
- Kinectで手の動きに合わせてモニタ上の画像を動かすサンプル
- Kinectで人体を認識して棒人間を動かすサンプル
- 声で選んだアイテムをプレイヤーの身体に装着・連動させるKinectサンプル
- Kinectで手の動きとカーソルを連動して操作するサンプル
- Kinectを使ったバーチャル試着室で着せ替えシミュレーション
- Kinect v2で実現する打楽器のバーチャル演奏
- Kinect v2を使って、机の上のリンゴをつかんで移動してみる
- センサーとサウンドの処理を組み込んでアプリを完成させる
- Kinectを使って、自分の手のひらに小さな分身を出現させてみる