2011年12月13日火曜日

KINECT SDK Beta2 で距離データを扱う( VB + WPF )

このエントリはKINECT SDK Advent Calendar : ATNDの12月13日分です。

kaorun55氏の「KINECT SDK Beta2 で距離データを扱う( C# + WPF )」をVBに変更してみました。

まずは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="521" Width="663">
    <Grid>
        <Image  Name="DepthImage" Height="480" Width="640" />
    </Grid>
</Window>
-------------------------------------------------------------------------------

特に変わったところはないです。Imegeコントロールを1つ貼り付けているだけです。

次にメインのソースです。

-------------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Nui

Class MainWindow
    Inherits Window

    Public nui As Runtime

    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。

        'KINECT確認
        If Runtime.Kinects.Count > 0 Then
            nui = Runtime.Kinects(0)
        Else
            MsgBox("KINECTが接続されていません。")
            Exit Sub
        End If

    End Sub

    Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded

        'KINECT初期化
        nui.Initialize(RuntimeOptions.UseDepth)
        nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution640x480, ImageType.Depth)

        'イベント追加
        AddHandler nui.DepthFrameReady, AddressOf Kinect_DepthFrameReady

    End Sub

    Private Sub Kinect_DepthFrameReady(ByVal sender As Object, ByVal e As ImageFrameReadyEventArgs)

        'Imageコントロールに1フレーム分のデータを設定
        Dim image As PlanarImage = e.ImageFrame.Image
        DepthImage.Source = BitmapSource.Create(image.Width, image.Height, 96, 96, PixelFormats.Gray16, Nothing, ConvGrayScale(image).Bits, image.Width * image.BytesPerPixel)

        'リソース不足になるので強制的にGCを実行
        System.GC.Collect()

    End Sub

    Private Function ConvGrayScale(ByVal source As PlanarImage) As PlanarImage

        '深度情報をグレースケールに変換
        Dim i As Integer
        Dim depth As Integer

        For i = 0 To source.Bits.Length - 2 Step 2

            depth = CInt((source.Bits(i) Or (source.Bits(i + 1) << 8)))

            depth = CInt(&HFFFF - (&HFFFF * depth / &HFFF))

            source.Bits(i) = CByte(depth And &HFF)
            source.Bits(i + 1) = CByte((depth >> 8) And &HFF)

        Next

        ConvGrayScale = source

    End Function

End Class
-------------------------------------------------------------------------------

距離カメラのデータをグレースケールに変更する必要があります。

実はこの辺りの処理をしてくれるtoolがあります。

http://c4fkinect.codeplex.com/からToolkitをダウンロードして、適当な場所に解凍してください。

プロジェクトの参照の追加で先ほど解凍したフォルダの中の「Coding4Fun.Kinect.Wpf.dll」を追加しましょう。

次にメインソースの先頭に「Imports Coding4Fun.Kinect.Wpf」を書き加えます。

Kinect_DepthFrameReadyサブルーチン内の「Dim image As PlanarImage = e.ImageFrame.Image」は削除してください。

次に
「DepthImage.Source = BitmapSource.Create(image.Width, image.Height, 96, 96, PixelFormats.Gray16, Nothing, ConvGrayScale(image).Bits, image.Width * image.BytesPerPixel)」を
「DepthImage.Source = e.ImageFrame.ToBitmapSource()」に変更します。

「ConvGrayScale」ファンクションは必要ありません。

これだけで距離データをグレースケールで表示できます。

変更したソースは以下のようになります。

-------------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Nui
Imports Coding4Fun.Kinect.Wpf

Class MainWindow
    Inherits Window

    Public nui As Runtime

    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。

        'KINECT確認
        If Runtime.Kinects.Count > 0 Then
            nui = Runtime.Kinects(0)
        Else
            MsgBox("KINECTが接続されていません。")
            Exit Sub
        End If

    End Sub

    Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded

        'KINECT初期化
        nui.Initialize(RuntimeOptions.UseDepth)
        nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution640x480, ImageType.Depth)

        'イベント追加
        AddHandler nui.DepthFrameReady, AddressOf Kinect_DepthFrameReady

    End Sub

    Private Sub Kinect_DepthFrameReady(ByVal sender As Object, ByVal e As ImageFrameReadyEventArgs)

        'Imageコントロールに1フレーム分のデータを設定

        DepthImage.Source = e.ImageFrame.ToBitmapSource()

        'リソース不足になるので強制的にGCを実行
        System.GC.Collect()

    End Sub

End Class
-------------------------------------------------------------------------------

ずいぶんと短くなります。

ToolkitはライブラリですのでC#からも利用できます。
ちなみに初期のころにToolkitの名称で公表されていたライブラリはToolboxに名前が変更になったようです。Toolboxの方はKINECT SDKが標準で持っていないジェスチャー認識ができるライブラリのようです。



0 件のコメント:

コメントを投稿