LEADTOOLSは高速な多機能画像処理コンポーネントですが、それゆえに画像ファイルに対する処理にのみ適用するようなイメージがあります。しかし、Kinectからのデータは連続した画像データとして取得できます。つまり、動画のように見えていても、処理単位は画像データとなるため、LEADTOOLSが適用できるのではないかと考えました。
結論から言えば、非常に良い結果を得ることができました。
Kinect距離データを画面に表示する
(※サンプルファイルの「CZ1312HistogramVB」に対応)
Kinectからの距離データを、WPFのImageコントロールに表示するサンプルを作成します。
KinectModel.vb
KinectModelクラスには、Kinectからの距離データをImageSourceとして公開する処理を記述します。
重要な部分を抜粋すると次のようになります。
:
(略)
:
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イベントプロシージャで、この中で次の処理を実施しています。
- OpenDepthImageFrameメソッドでフレーム形式の距離データを取得
- CopyPixelDataToメソッドで2バイト配列に格納
- WritePixelsメソッドで2バイト配列をグレースケールのWritebleBitmapに設定
- WritebleBitmapをImageSourceとして公開
MainViewModel.vb
MainViewModelクラスでは、KinectModelが公開しているDepthImageElementプロパティとPropertyChangedイベントを公開しています。
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
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センサーの開始と停止のメソッド起動の記述だけで済みます。
実行結果
距離に応じて手前が濃く、奥が薄いグレースケールで表示できていると思います。いろいろ動いてその変化を確認してみましょう。

