今回のサンプルは、机の上に置かれたリンゴをつかんで、別な場所に移動するサンプルです。
今回のプログラムも、WPFアプリケーションとして作成します。まずはプロジェクトからの作成です。
プロジェクトを作成する
VS2013メニューの[ファイル]ー[新しいプロジェクト]と選択し、表示される画面から、「テンプレート」に「Visual Basic」を指定し、「WPF アプリケーション」を選択します。名前に「AppleMove」と指定し、「OK」ボタンをクリックします。
画像の追加
ソリューションエクスプローラー内の「AppleMove」を選択し、マウスの右クリックで表示されるメニューから、[追加]ー[新しいフォルダー]と選択し、「Images」というフォルダーを作成します。作成した「Images」フォルダーを選択し、マウスの右クリックで表示されるメニューから、[追加]−[既存の項目]と選択して、リンゴと机のPNG画像2枚を追加しておきます。
これらはダウンロードされたサンプルファイル(AppleMove.zip)に含まれていますので、ご確認ください。
参照設定
参照設定については、連載の第2回目と全く同じですので、そちらを参照してください。
コントロールの配置
「MainWindow.xaml」画面内に、ツールボックスから「Image」コントロールを3個と「Canvas」コントロールを2個配置します。
- 最初のImageは、RGBカメラで室内の様子を映すために使用し、名前を「roomImage」としておきます。
- 次のImageには、ソリューションエクスプローラー内のImagesフォルダーにある机の画像を表示しておきます。
- 3つ目のImageは、名前を「Image1」と指定し、ソリューションエクスプローラー内のImagesフォルダーにあるリンゴの画像を配置しておきます。
- 最初のCanvasは、名前を「appleCanvas」と指定します。移動したリンゴを表示させるための領域です。
- 次のCanvasは、プレイヤーの関節の位置を表示させる領域で、名前を「CanvasBody」と指定しておきます。表示する円の色を透明色にしますので、画面上では見えません。
全て設定すると図1のようになります。
図1:全てのコントロールを配置した状態
これらのコードを書き出すとリスト1のようになります。
リスト1:MainWindow.xaml
01 | <Window x:Class="MainWindow" |
04 | Title="MainWindow" Height="424" Width="512"> |
06 | <Image x:Name="roomImage" /> ■(1) |
07 | <Canvas x:Name="appleCanvas" Width="512" Height="424" Margin="0,-31,-8,0" /> ■(4) |
08 | <Canvas x:Name="CanvasBody" Width="512" Height="424" Margin="0,-31,-8,0" /> ■(5) |
09 | <Image Canvas.Left="24" Canvas.Top="256" Width="449" Margin="25,230,30,10" x:Name="deskImage" Stretch="UniformToFill" Source="Images/机.png" /> ■(2) |
10 | <Image x:Name="Image1" Source="Images/apple.png" Margin="385,179,54,154"/> ■(3) |
プログラムコード
次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示されるMainWindow.xam.vbに、リスト2以降のコードを記述します。
名前空間の読み込みとメンバー変数の宣言
リスト2:MainWindow.xaml.vbの一部
01 | Imports Microsoft.Kinect |
02 | Imports System.ComponentModel |
04 | Public Class MainWindow |
05 | Private myKinect As KinectSensor |
06 | Private myBodyFrameReader As BodyFrameReader |
07 | Private myBodies As Body() |
08 | Private myHandPositionX As Double |
09 | Private myHandPositionY As Double |
10 | Private myColorSpacePoint As ColorSpacePoint (1) |
11 | Private myBytesPerPixel As Integer = 4 |
12 | Private myColorFrameReader As ColorFrameReader = Nothing |
13 | Private colorBitmap As WriteableBitmap = Nothing |
14 | Private ColorImagePixelData As Byte() |
15 | Private BytesPerPixel As Integer = 4 |
16 | Private commonJoint As Joint (2) |
18 | Private point As DepthSpacePoint (3) |
20 | Private myImage As Image (4) |
21 | Private flag As Boolean = False |
連載第2回目と共通の部分が多いので、ここでは異なるメンバー変数の主なものだけ解説しておきます。1.カラー空間における2Dの位置を表す構造体のメンバー変数myColorSpacePointを宣言します。2.身体の関節の位置を表すJoint構造体のメンバー変数commonJointを宣言します。3.距離空間における2Dの位置を表す構造体のメンバー変数pointを宣言します。4.Imageクラス型のメンバー変数myImageを宣言します。
ウインドウが読み込まれた時の処理
リスト3:MainWindow.xaml.vbの一部、リスト2の続き
01 | Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded |
02 | myKinect = KinectSensor.GetDefault (1) |
03 | myImage = New Image (2) |
07 | .Source = New BitmapImage(New Uri("Images/apple.png", UriKind.Relative)) |
09 | 'appleCanvas.Children.Add(myImage) |
10 | If myKinect Is Nothing = False Then (4) |
11 | Dim myDepthDescription = myKinect.DepthFrameSource.FrameDescription (5) |
13 | myBodyFrameReader = myKinect.BodyFrameSource.OpenReader (7) |
14 | AddHandler myBodyFrameReader.FrameArrived, AddressOf myBodyFrameReader_FrameArrived (8) |
15 | myBodies = New Body(myKinect.BodyFrameSource.BodyCount - 1) {} (9) |
16 | myColorFrameReader = myKinect.ColorFrameSource.OpenReader (10) |
17 | Dim myColorFrameDescription As FrameDescription = myKinect.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra) (11) |
18 | ColorImagePixelData = New Byte(myColorFrameDescription.Width * myColorFrameDescripton.Height * BytesPerPixel – 1) {} (12) |
19 | colorBitmap = New WriteableBitmap(myColorFrameDescription.Width, myColorFrameDescripton.Height, 96.0, 96.0, PixelFormats.Bgr32, Nothing) (13) |
20 | AddHandler myColorFrameReader.FrameArrived, AddressOf myColorFrameReader_FrameArrived (13) |
- Kinectを使用可能にします。
- 新しいImageのインスタンスmyImageオブジェクトを作成します。
- WidthとHeightを指定し、SourceプロパティにImagesフォルダー内にある「apple.png」を指定します。
- Kinectセンサーが使用可能な状態にある場合は、以下の処理を行います。
- 距離フレームプロパティの形式を取得し、変数myDepthDescriptionで参照します。
- Kinectを動作させます。
- BodyFrameSource.OpenReaderで、ボディ フレームのソース フレームのリーダーを作成し、変数myBodyFrameReaderで参照します。
- myBodyFrameReader.FrameArrivedで、新しいボディフレームの準備ができているときに発生するイベント処理を実行します。
- ボディフレームソースのボディの個数を引数に持った、新しいBodyの配列をmyBodiesに格納します。
- myKinect.ColorFrameSource.OpenReaderで、カラーフレームのソースフレームのリーダーを作成し、myColorFrameReaderメンバー変数で参照します。
- カラー画像の情報をBGRAフォーマットで作成し、変数myColorFrameDescriptionで参照します。
- 配列変数ColorImagePixelDataを確保します。
- ピクセルデータを格納するビットマップを作成し、変数colorBitmapで参照します。
- myColorFrameReader.FrameArrivedでカラーフレーム到着時のイベントを実行します。