Seiten

Dienstag, 20. März 2012

Kinect for Windows mit VB.NET - Anzeigen des Depth Data Stream

Dies ist Teil 2 der kleinen Code-Snippet-Reihe, die sich mit der Programmierung von Kinect for Windows mit VB.NET befasst. Teil 1 demonstriert, wie der Color Image Stream mit VB.NET dargestellt wird. Dieser zweite Teil erweitert das in Teil 1 vorgestellte Projekt und demonstriert, wie mit VB.NET der Depth Data Stream in einer WPF-Anwendung dargestellt wird.

Auf geht's.
Im folgenden wird der vollständige Quellcode der bisherigen Beispiel-Anwendung dargestellt. Die WPF-Anwendung zeigt im gegenwärtigen Status der Entwicklung des Projekts den Color Stream und den Depth Stream eines Kinect for Windows-Sensors.

Hier ist der Quellcode von MainWindow.xaml:
    1 <Window x:Class="MainWindow"
    2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4    Title="Kinect for Windows Test App 01" Height="600" Width="800" WindowState="Maximized">
    5   <Grid ShowGridLines="True">
    6     <Grid.ColumnDefinitions>
    7       <ColumnDefinition />
    8       <ColumnDefinition Width="auto"/>
    9     </Grid.ColumnDefinitions>
   10     <Grid Grid.Column="1">
   11       <Grid.RowDefinitions>
   12         <RowDefinition />
   13         <RowDefinition />
   14       </Grid.RowDefinitions>
   15       <Image x:Name="imVideoStream"
   16             Width="640"
   17             Height="480"
   18             Grid.Row="0" />
   19       <Image x:Name="imDepthStream"
   20             Width="640"
   21             Height="480"
   22             Grid.Row="1" />
   23     </Grid>
   24   </Grid>
   25 </Window>
   26 

Und hier ist der Quellcode von MainWindow.xaml.vb:
    1 Imports Microsoft.Kinect
    2 
    3 Class MainWindow
    4 
    5   Private kinectSensor As KinectSensor
    6 
    7   Private Shared ReadOnly Bgr32BytesPerPixel As Integer =
    8     CInt(Math.Floor((PixelFormats.Bgr32.BitsPerPixel + 7) / 8))
    9 
   10 
   11   Public Sub New()
   12 
   13     InitializeComponent()
   14 
   15     kinectSensor = (From sensorToCheck In kinectSensor.KinectSensors
   16                     Where sensorToCheck.Status = KinectStatus.Connected
   17                     Select sensorToCheck).FirstOrDefault()
   18 
   19     If kinectSensor IsNot Nothing Then
   20 
   21       kinectSensor.ColorStream.Enable(
   22         ColorImageFormat.RgbResolution640x480Fps30)
   23 
   24       kinectSensor.DepthStream.Enable(
   25         DepthImageFormat.Resolution640x480Fps30)
   26 
   27       kinectSensor.Start()
   28 
   29       kinectSensor.DepthStream.Range = DepthRange.Near
   30 
   31       AddHandler kinectSensor.ColorFrameReady,
   32         AddressOf kisColorFrameReady
   33 
   34       AddHandler kinectSensor.DepthFrameReady,
   35         AddressOf kisDepthFrameReady
   36 
   37     End If
   38 
   39   End Sub
   40 
   41 
   42 #Region " COLOR DATA STREAM "
   43 
   44 
   45   Private pixelData As Byte()
   46 
   47   Private outputImage As WriteableBitmap
   48 
   49 
   50   Private Sub kisColorFrameReady(
   51                                 sender As Object,
   52                                 e As ColorImageFrameReadyEventArgs)
   53 
   54     Using imageFrame As ColorImageFrame = e.OpenColorImageFrame()
   55 
   56       If imageFrame IsNot Nothing Then
   57 
   58         Me.pixelData = New Byte(imageFrame.PixelDataLength - 1) {}
   59 
   60         imageFrame.CopyPixelDataTo(Me.pixelData)
   61 
   62         imVideoStream.Visibility = Visibility.Visible
   63 
   64         Me.outputImage = New WriteableBitmap(
   65           imageFrame.Width,
   66           imageFrame.Height,
   67           96,
   68           96,
   69           PixelFormats.Bgr32,
   70           Nothing)
   71 
   72         Me.imVideoStream.Source = Me.outputImage
   73 
   74         Me.outputImage.WritePixels(New Int32Rect(
   75                                    0,
   76                                    0,
   77                                    imageFrame.Width,
   78                                    imageFrame.Height),
   79                                  Me.pixelData,
   80                                  imageFrame.Width * Bgr32BytesPerPixel,
   81                                  0)
   82 
   83       End If
   84 
   85     End Using
   86 
   87   End Sub
   88 
   89 
   90 #End Region
   91 
   92 
   93 #Region " DEPTH DATA STREAM "
   94 
   95 
   96   Private depthPixelData As Short()
   97   Private depthFrame32 As Byte()
   98   Private outputBitmap As WriteableBitmap
   99 
  100   Private Shared ReadOnly IntensityShiftByPlayerR As Integer() =
  101     {1, 2, 0, 2, 0, 0, 2, 0}
  102   Private Shared ReadOnly IntensityShiftByPlayerG As Integer() =
  103     {1, 2, 2, 0, 2, 0, 0, 1}
  104   Private Shared ReadOnly IntensityShiftByPlayerB As Integer() =
  105     {1, 0, 2, 2, 0, 2, 0, 2}
  106 
  107   Private Const RedIndex As Integer = 2
  108   Private Const GreenIndex As Integer = 1
  109   Private Const BlueIndex As Integer = 0
  110 
  111 
  112   Private Sub kisDepthFrameReady(sender As Object,
  113                                  e As DepthImageFrameReadyEventArgs)
  114 
  115     Using imageFrame As DepthImageFrame = e.OpenDepthImageFrame()
  116 
  117       If imageFrame IsNot Nothing Then
  118 
  119         Me.depthPixelData = New Short(imageFrame.PixelDataLength - 1) {}
  120         Me.depthFrame32 = New Byte(
  121           imageFrame.Width * imageFrame.Height * Bgr32BytesPerPixel - 1) {}
  122 
  123         imageFrame.CopyPixelDataTo(Me.depthPixelData)
  124 
  125         Dim convertedDepthBits As Byte() = Me.ConvertDepthFrame(
  126           Me.depthPixelData, DirectCast(sender, KinectSensor).DepthStream)
  127 
  128         Me.outputBitmap = New WriteableBitmap(
  129           imageFrame.Width, imageFrame.Height, 96, 96, PixelFormats.Bgr32, Nothing)
  130 
  131         Me.imDepthStream.Source = Me.outputBitmap
  132 
  133         Me.outputBitmap.WritePixels(New Int32Rect(0,
  134                                                   0,
  135                                                   imageFrame.Width,
  136                                                   imageFrame.Height),
  137                                                 convertedDepthBits,
  138                                                 imageFrame.Width * Bgr32BytesPerPixel,
  139                                                 0)
  140 
  141       End If
  142 
  143     End Using
  144 
  145   End Sub
  146 
  147 
  148   Private Function ConvertDepthFrame(depthFrame As Short(),
  149                                      depthStream As DepthImageStream) _
  150                                    As Byte()
  151 
  152     Dim tooNearDepth As Integer = depthStream.TooNearDepth
  153     Dim tooFarDepth As Integer = depthStream.TooFarDepth
  154     Dim unknownDepth As Integer = depthStream.UnknownDepth
  155 
  156     Dim i16 As Integer = 0, i32 As Integer = 0
  157     While i16 < depthFrame.Length AndAlso i32 < Me.depthFrame32.Length
  158       Dim player As Integer =
  159         depthFrame(i16) And DepthImageFrame.PlayerIndexBitmask
  160       Dim realDepth As Integer =
  161         depthFrame(i16) >> DepthImageFrame.PlayerIndexBitmaskWidth
  162 
  163       ' transform 13-bit depth information into an 8-bit intensity appropriate
  164       ' for display (we disregard information in most significant bit)
  165       Dim intensity As Byte = (Not (realDepth >> 4)) And 255
  166 
  167       If player = 0 AndAlso realDepth = 0 Then
  168         ' white
  169         Me.depthFrame32(i32 + RedIndex) = 255
  170         Me.depthFrame32(i32 + GreenIndex) = 255
  171         Me.depthFrame32(i32 + BlueIndex) = 255
  172       ElseIf player = 0 AndAlso realDepth = tooFarDepth Then
  173         ' dark purple
  174         Me.depthFrame32(i32 + RedIndex) = 66
  175         Me.depthFrame32(i32 + GreenIndex) = 0
  176         Me.depthFrame32(i32 + BlueIndex) = 66
  177       ElseIf player = 0 AndAlso realDepth = unknownDepth Then
  178         ' dark brown
  179         Me.depthFrame32(i32 + RedIndex) = 66
  180         Me.depthFrame32(i32 + GreenIndex) = 66
  181         Me.depthFrame32(i32 + BlueIndex) = 33
  182       Else
  183         ' tint the intensity by dividing by per-player values
  184         Me.depthFrame32(i32 + RedIndex) =
  185           CByte(intensity >> IntensityShiftByPlayerR(player))
  186         Me.depthFrame32(i32 + GreenIndex) =
  187           CByte(intensity >> IntensityShiftByPlayerG(player))
  188         Me.depthFrame32(i32 + BlueIndex) =
  189           CByte(intensity >> IntensityShiftByPlayerB(player))
  190       End If
  191       i16 += 1
  192       i32 += 4
  193     End While
  194 
  195     Return Me.depthFrame32
  196 
  197   End Function
  198 
  199 
  200 #End Region
  201 
  202 
  203   Private Sub MainWindow_Closing(sender As Object,
  204                                  e As System.ComponentModel.CancelEventArgs) _
  205                                Handles Me.Closing
  206 
  207     kinectSensor.Stop()
  208 
  209   End Sub
  210 
  211 
  212 End Class
  213 

An dieser Stelle möchte ich auf diesen Thread aus den Kinect-Forums hinweisen, der mir bei der Übersetzung einer bestimmten Code-Zeile von C# nach VB.NET geholfen hat.

Diese Serie wird in loser Reihenfolge fortgesetzt.
Have fun!

Keine Kommentare:

Kommentar veröffentlichen