SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(LEADTOOLS)

「LEADTOOLS」を使ってKinectから取得した距離データを可視化しよう

  • X ポスト
  • このエントリーをはてなブックマークに追加

 Microsoft Kinect for Windowsは物体までの距離を計測できるセンサーで、その戻り値はグレースケール相当の2バイトの画像として取得できます。この距離データを可視化するときにデータを見やすくするのに画像処理する場合が多いのですが、1ドットずつ処理していると処理時間がかかりすぎるため、フレームレートの低下を招き、距離データの再生にタイムラグが生じてしまいます。この画像処理の処理速度を向上させるという問題をどのようにすれば解決できるのか悩んでいた時に思いついたのが、今回取り上げるLEADTOOLS Imaging Proの存在です。

  • X ポスト
  • このエントリーをはてなブックマークに追加

 LEADTOOLSは高速な多機能画像処理コンポーネントですが、それゆえに画像ファイルに対する処理にのみ適用するようなイメージがあります。しかし、Kinectからのデータは連続した画像データとして取得できます。つまり、動画のように見えていても、処理単位は画像データとなるため、LEADTOOLSが適用できるのではないかと考えました。

 結論から言えば、非常に良い結果を得ることができました。

Kinect距離データを画面に表示する

 (※サンプルファイルの「CZ1312HistogramVB」に対応)

 Kinectからの距離データを、WPFのImageコントロールに表示するサンプルを作成します。

図1 サンプルプロジェクトの構成
図1 サンプルプロジェクトの構成

KinectModel.vb

 KinectModelクラスには、Kinectからの距離データをImageSourceとして公開する処理を記述します。

 重要な部分を抜粋すると次のようになります。

リスト1 KinectModel.vb
        :
    (略)
        :
Private WithEvents Kinect As KinectSensor

Private _DepthImageElement As ImageSource
Public Property DepthImageElement As ImageSource
    Get
        Return Me._DepthImageElement
    End Get
    Set(value As ImageSource)
        Me._DepthImageElement = value
        OnPropertyChanged()
    End Set
End Property
        :
    (略)
        :
Private Sub DiscoverKinectSensor()
    Me.Kinect = KinectSensor.KinectSensors.FirstOrDefault(
        Function(x)
            Return x.Status = KinectStatus.Connected
        End Function)
    If Me.Kinect IsNot Nothing Then
        Me.Kinect.DepthStream.Enable()
        Me.Kinect.Start()
        Me.DepthImageBitmap = New WriteableBitmap(DepthDesc.Width,
                                                  DepthDesc.Height,
                                                  96.0,
                                                  96.0,
                                                  PixelFormats.Gray16,
                                                  Nothing)
        ReDim Me.DepthImageFrameData(depthDesc.Width * depthDesc.Height - 1)
        Me.DepthImageBitmapRect = New Int32Rect(0,
                                                0,
                                                DepthDesc.Width,
                                                DepthDesc.Height)
        Me.DepthImageStride = DepthDesc.Width * Me.BytesPerPixel
    End If
End Sub
 
Private Sub Kinect_DepthFrameReady(sender As Object,
                                   e As DepthImageFrameReadyEventArgs) _
                               Handles Kinect.DepthFrameReady
    Using frame = e.OpenDepthImageFrame
        If frame IsNot Nothing Then
            frame.CopyPixelDataTo(Me.DepthImageFrameData)
 
            Me.DepthImageBitmap.WritePixels(Me.DepthImageBitmapRect,
                                            Me.DepthImageFrameData,
                                            Me.DepthImageStride,
                                            0)
            Me.DepthImageElement = Me.DepthImageBitmap
        End If
    End Using
End Sub

 重要なポイントは、距離データがセンサーから送られてくるとイベント呼び出しされるKinect_DepthFrameReadyイベントプロシージャで、この中で次の処理を実施しています。

  1. OpenDepthImageFrameメソッドでフレーム形式の距離データを取得
  2. CopyPixelDataToメソッドで2バイト配列に格納
  3. WritePixelsメソッドで2バイト配列をグレースケールのWritebleBitmapに設定
  4. WritebleBitmapをImageSourceとして公開

MainViewModel.vb

 MainViewModelクラスでは、KinectModelが公開しているDepthImageElementプロパティとPropertyChangedイベントを公開しています。

MainWindow.xaml

リスト2 MainWindow.xaml
<Window
    x:Class="MainWindow"
    Title="CZ1312HistogramVB" 
    Height="300" Width="640"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:CZ1312HistogramVB"
    Loaded="WIndow_Loaded" Closing="Window_Closing">
    <Viewbox>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Image Grid.Column="0" Grid.Row="0"
                        Source="{Binding DepthImageElement}"  Width="640" Height="480" />
            <Image Grid.Column="1" Grid.Row="0"
                        Source="{Binding DepthImageElement}"  Width="640" Height="480" />
        </Grid>
    </Viewbox>
</Window>

 WPFの画面定義体であるXAMLで画面を左右に2分割し、同じデータを表示するようにします。あとで一方をLEADTOOLSで見やすくします。

MainWindow.xaml.vb

リスト3 MainWindow.xaml.vb
Class MainWindow
    Private ViewModel As New MainViewModel
 
    Public Sub New()
        InitializeComponent()
        Me.DataContext = Me.ViewModel
    End Sub
 
    Private Sub WIndow_Loaded(sender As Object, e As RoutedEventArgs)
        Me.ViewModel.StartCommand()
    End Sub
 
    Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs)
        Me.ViewModel.StopCommand()
    End Sub
End Class

 データの表示などはXAMLのBindingを使うので、コードビハインド側ではDataContextの設定と、Kinectセンサーの開始と停止のメソッド起動の記述だけで済みます。

実行結果

図2 実行結果
図2 実行結果

 距離に応じて手前が濃く、奥が薄いグレースケールで表示できていると思います。いろいろ動いてその変化を確認してみましょう。

次のページ
LEADTOOLSを適用する

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(LEADTOOLS)連載記事一覧

もっと読む

この記事の著者

初音玲(ハツネアキラ)

 国内SIerのSEでパッケージ製品開発を主に行っており、最近は、空間認識や音声認識などを応用した製品を手掛けています。 個人的には、仕事の内容をさらに拡張したHoloLensなどのMRを中心に活動しています。 Microsoft MVP for Windows Development ブログ:http://hatsune.hatenablog.jp/

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7573 2016/03/14 11:40

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング