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

今回のサンプルは、机の上に置かれたリンゴをつかんで、別な場所に移動するサンプルです。作成するプログラムのファイル一式は、こちらからダウンロードできます。[サンプル]AppleMove.zip今回のプログラムも、WPFアプリケーションとして作成します。まずはプロジェクトからの作成です。プロジェクトを作

薬師寺 国安

2015年1月20日 18:00

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

今回のプログラムも、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でカラーフレーム到着時のイベントを実行します。
この記事のキーワード :

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30