Kinect v2を使って、机の上のリンゴをつかんで移動してみる

2015年1月20日(火)
薬師寺 国安

今回のサンプルは、机の上に置かれたリンゴをつかんで、別な場所に移動するサンプルです。

今回のプログラムも、WPFアプリケーションとして作成します。まずはプロジェクトからの作成です。

プロジェクトを作成する

VS2013メニューの[ファイル]ー[新しいプロジェクト]と選択し、表示される画面から、「テンプレート」に「Visual Basic」を指定し、「WPF アプリケーション」を選択します。名前に「AppleMove」と指定し、「OK」ボタンをクリックします。

画像の追加

ソリューションエクスプローラー内の「AppleMove」を選択し、マウスの右クリックで表示されるメニューから、[追加]ー[新しいフォルダー]と選択し、「Images」というフォルダーを作成します。作成した「Images」フォルダーを選択し、マウスの右クリックで表示されるメニューから、[追加]−[既存の項目]と選択して、リンゴと机のPNG画像2枚を追加しておきます。

これらはダウンロードされたサンプルファイル(AppleMove.zip)に含まれていますので、ご確認ください。

参照設定

参照設定については、連載の第2回目と全く同じですので、そちらを参照してください。

コントロールの配置

「MainWindow.xaml」画面内に、ツールボックスから「Image」コントロールを3個と「Canvas」コントロールを2個配置します。

  1. 最初のImageは、RGBカメラで室内の様子を映すために使用し、名前を「roomImage」としておきます。
  2. 次のImageには、ソリューションエクスプローラー内のImagesフォルダーにある机の画像を表示しておきます。
  3. 3つ目のImageは、名前を「Image1」と指定し、ソリューションエクスプローラー内のImagesフォルダーにあるリンゴの画像を配置しておきます。
  4. 最初のCanvasは、名前を「appleCanvas」と指定します。移動したリンゴを表示させるための領域です。
  5. 次のCanvasは、プレイヤーの関節の位置を表示させる領域で、名前を「CanvasBody」と指定しておきます。表示する円の色を透明色にしますので、画面上では見えません。

全て設定すると図1のようになります。

全てのコントロールを配置した状態

図1:全てのコントロールを配置した状態

これらのコードを書き出すとリスト1のようになります。

リスト1:MainWindow.xaml

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="424" Width="512">
    <Grid>
        <Image x:Name="roomImage"  /> ■(1)
        <Canvas x:Name="appleCanvas" Width="512" Height="424" Margin="0,-31,-8,0" /> ■(4)
        <Canvas x:Name="CanvasBody" Width="512" Height="424" Margin="0,-31,-8,0" /> ■(5)
        <Image Canvas.Left="24" Canvas.Top="256" Width="449" Margin="25,230,30,10" x:Name="deskImage"  Stretch="UniformToFill" Source="Images/机.png"  /> ■(2)
        <Image x:Name="Image1" Source="Images/apple.png" Margin="385,179,54,154"/> ■(3)
     </Grid>
</Window>

プログラムコード

次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示されるMainWindow.xam.vbに、リスト2以降のコードを記述します。

名前空間の読み込みとメンバー変数の宣言

リスト2:MainWindow.xaml.vbの一部

Imports Microsoft.Kinect
Imports System.ComponentModel

Public Class MainWindow
    Private myKinect As KinectSensor
    Private myBodyFrameReader As BodyFrameReader
    Private myBodies As Body()
    Private myHandPositionX As Double
    Private myHandPositionY As Double
    Private myColorSpacePoint As ColorSpacePoint   (1)
    Private myBytesPerPixel As Integer = 4
    Private myColorFrameReader As ColorFrameReader = Nothing
    Private colorBitmap As WriteableBitmap = Nothing
    Private ColorImagePixelData As Byte()
    Private BytesPerPixel As Integer = 4
    Private commonJoint As Joint   (2)

    Private point As DepthSpacePoint   (3)

    Private myImage As Image   (4)
    Private flag As Boolean = False

連載第2回目と共通の部分が多いので、ここでは異なるメンバー変数の主なものだけ解説しておきます。1.カラー空間における2Dの位置を表す構造体のメンバー変数myColorSpacePointを宣言します。2.身体の関節の位置を表すJoint構造体のメンバー変数commonJointを宣言します。3.距離空間における2Dの位置を表す構造体のメンバー変数pointを宣言します。4.Imageクラス型のメンバー変数myImageを宣言します。

ウインドウが読み込まれた時の処理

リスト3:MainWindow.xaml.vbの一部、リスト2の続き

Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    myKinect = KinectSensor.GetDefault   (1)
    myImage = New Image   (2)
    With myImage   (3)
        .Width = 56
        .Height = 56
        .Source = New BitmapImage(New Uri("Images/apple.png", UriKind.Relative))
    End With
    'appleCanvas.Children.Add(myImage)
    If myKinect Is Nothing = False Then   (4)
        Dim myDepthDescription = myKinect.DepthFrameSource.FrameDescription   (5)
        myKinect.Open()   (6)
        myBodyFrameReader = myKinect.BodyFrameSource.OpenReader   (7)
        AddHandler myBodyFrameReader.FrameArrived, AddressOf myBodyFrameReader_FrameArrived   (8)
        myBodies = New Body(myKinect.BodyFrameSource.BodyCount - 1) {}   (9)
        myColorFrameReader = myKinect.ColorFrameSource.OpenReader   (10)
        Dim myColorFrameDescription As FrameDescription = myKinect.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra) (11)
        ColorImagePixelData = New Byte(myColorFrameDescription.Width * myColorFrameDescripton.Height * BytesPerPixel – 1) {}   (12)
        colorBitmap = New WriteableBitmap(myColorFrameDescription.Width, myColorFrameDescripton.Height, 96.0, 96.0, PixelFormats.Bgr32, Nothing)  (13)
        AddHandler myColorFrameReader.FrameArrived, AddressOf myColorFrameReader_FrameArrived   (13)
    End If
End Sub
  1. Kinectを使用可能にします。
  2. 新しいImageのインスタンスmyImageオブジェクトを作成します。
  3. WidthとHeightを指定し、SourceプロパティにImagesフォルダー内にある「apple.png」を指定します。
  4. Kinectセンサーが使用可能な状態にある場合は、以下の処理を行います。
  5. 距離フレームプロパティの形式を取得し、変数myDepthDescriptionで参照します。
  6. Kinectを動作させます。
  7. BodyFrameSource.OpenReaderで、ボディ フレームのソース フレームのリーダーを作成し、変数myBodyFrameReaderで参照します。
  8. myBodyFrameReader.FrameArrivedで、新しいボディフレームの準備ができているときに発生するイベント処理を実行します。
  9. ボディフレームソースのボディの個数を引数に持った、新しいBodyの配列をmyBodiesに格納します。
  10. myKinect.ColorFrameSource.OpenReaderで、カラーフレームのソースフレームのリーダーを作成し、myColorFrameReaderメンバー変数で参照します。
  11. カラー画像の情報をBGRAフォーマットで作成し、変数myColorFrameDescriptionで参照します。
  12. 配列変数ColorImagePixelDataを確保します。
  13. ピクセルデータを格納するビットマップを作成し、変数colorBitmapで参照します。
  14. myColorFrameReader.FrameArrivedでカラーフレーム到着時のイベントを実行します。
  • 画面上のオブジェクトをつかんで移動させるKinect v2プログラム

    『作りながら学ぶKinect v2プログラミング開発』 第6回のサンプルプログラムです。
薬師寺国安事務所

薬師寺国安事務所代表。Visual Basic プログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。
1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。1997年に薬師寺聖とコラボレーション・ユニット PROJECT KySS を結成。2003年よりフリーになり、PROJECT KySS の活動に本格的に参加、.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。Windows Phoneアプリ開発を経て、現在はWindows ストア アプリを多数公開中

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。Microsoft MVP for Development Platforms-Windows Platform Development (Oct 2014-Sep 2015)。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています