2013-03-15 130 views
1

我是Kinect和C#的新手。我試圖從Kinect中獲取深度圖像,將其轉換爲位圖以執行一些OpenCV操作,然後顯示它。問題是,我得到的只有深度圖像的三分之一,其餘全部是黑色的(如圖所示)。這不是原始深度圖像,而是繪畫後我收到的圖像。Kinect深度圖像僅部分可見

enter image description here

這裏是代碼 -

圖像和image1的是兩個圖像畫布我有用於顯示。

void DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e) 
    { 

     DepthImageFrame Image; 
     Bitmap bm; 
     using (Image = e.OpenDepthImageFrame()) 
     { 


      if (Image != null) 
      { 
      this.shortpixeldata = new short[Image.PixelDataLength]; 
      this.depthFrame32 = new byte[Image.Width * Image.Height * Bgr32BytesPerPixel]; 


      bmp = new Bitmap(Image.Width, Image.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb); 
      Image.CopyPixelDataTo(this.shortpixeldata); 

      byte[] convertedDepthBits = this.ConvertDepthFrame(this.shortpixeldata, ((KinectSensor)sender).DepthStream); 


      BitmapData bmapdata = bmp.LockBits(
           new System.Drawing.Rectangle(0, 0, Image.Width, Image.Height), 
           ImageLockMode.WriteOnly, 
           bmp.PixelFormat); 


      IntPtr ptr = bmapdata.Scan0; 
      Marshal.Copy(convertedDepthBits, 0, ptr, Image.PixelDataLength); 
      bmp.UnlockBits(bmapdata); 

      MemoryStream ms1 = new MemoryStream(); 
      bmp.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg); 
      System.Windows.Media.Imaging.BitmapImage bImg = new System.Windows.Media.Imaging.BitmapImage(); 
      bImg.BeginInit(); 
      bImg.StreamSource = new MemoryStream(ms1.ToArray()); 
      bImg.EndInit(); 

      image.Source = bImg; 

       if (bmp != null) 
      { 

       Image<Bgr, Byte> currentFrame = new Image<Bgr, Byte>(bmp); 

       Image<Gray, Byte> grayImage = currentFrame.Convert<Gray, Byte>().PyrDown().PyrUp(); 
       Image<Gray, Byte> Dest = new Image<Gray, Byte>(grayImage.Size); 
       CvInvoke.cvCanny(grayImage, Dest, 10, 60, 3); 


       image1.Source = ToBitmapSource(Dest); 

       CalculateFps(); 
      } 



      } 



      else 
      { 
       System.Diagnostics.Debug.WriteLine("depth bitmap empty :/"); 
      } 
     } 
    } 


     private byte[] ConvertDepthFrame(short[] depthFrame, DepthImageStream depthStream) 
     { 
      System.Diagnostics.Debug.WriteLine("depthframe len :{0}", depthFrame.Length); 

     for (int i16 = 0, i32 = 0; i16 < depthFrame.Length && i32 < this.depthFrame32.Length; i16++, i32 += 4) 
     { 

     int realDepth = depthFrame[i16] >> DepthImageFrame.PlayerIndexBitmaskWidth; 


     byte Distance = 0; 


     int MinimumDistance = 800; 
     int MaximumDistance = 4096; 


     if (realDepth > MinimumDistance) 
     { 


     //White = Close 
     //Black = Far 
     Distance = (byte)(255-((realDepth-MinimumDistance)*255/(MaximumDistance-MinimumDistance))); 


     this.depthFrame32[i32 + RedIndex] = (byte)(Distance); 
     this.depthFrame32[i32 + GreenIndex] = (byte)(Distance); 
     this.depthFrame32[i32 + BlueIndex] = (byte)(Distance); 
     } 

     else 
     { 
     this.depthFrame32[i32 + RedIndex] = 0; 
     this.depthFrame32[i32 + GreenIndex] = 150; 
     this.depthFrame32[i32 + BlueIndex] = 0; 
     } 
     } 

     return this.depthFrame32; 
     } 

我嘗試了不同的PixelFormats無濟於事。我無法弄清楚這個問題。有人知道我在做什麼錯嗎? 謝謝

回答

0

好吧,我自己想清楚了。 它始終隱藏在明顯的視野中。

函數ConvertDepthFrame以不同的大小(其4個獨立通道,因此4倍的原始大小)返回字節數組轉換爲數據位,我需要在方法調用中使用要複製的數據長度爲4 * Image.PixelDataLength :Marshal.Copy(...)

現在正常工作。 唷! :)

+0

一旦你有機會,不要忘記接受你的答案。 ;) – weberc2 2013-03-15 20:25:13

0

我建議使用WritableBitmap爲了將深度圖像複製到可查看的格式。在PixelFormat的情況下,該信息在深度圖像本身中可用,因此您應該使用WritableBitmap所採用的相同格式。

您看過Microsoft提供的任何示例嗎?你可以在Kinect for Windows Samples CodePlex頁面找到它們。有幾個示例演示如何將深度數據複製到WritableBitmap然後輸出。例如,這裏是「DepthBasics-WPF」示例應用程序的DepthFrameReady回調函數:

/// <summary> 
/// Event handler for Kinect sensor's DepthFrameReady event 
/// </summary> 
/// <param name="sender">object sending the event</param> 
/// <param name="e">event arguments</param> 
private void SensorDepthFrameReady(object sender, DepthImageFrameReadyEventArgs e) 
{ 
    using (DepthImageFrame depthFrame = e.OpenDepthImageFrame()) 
    { 
     if (depthFrame != null) 
     { 
      // Copy the pixel data from the image to a temporary array 
      depthFrame.CopyDepthImagePixelDataTo(this.depthPixels); 

      // Get the min and max reliable depth for the current frame 
      int minDepth = depthFrame.MinDepth; 
      int maxDepth = depthFrame.MaxDepth; 

      // Convert the depth to RGB 
      int colorPixelIndex = 0; 
      for (int i = 0; i < this.depthPixels.Length; ++i) 
      { 
       // Get the depth for this pixel 
       short depth = depthPixels[i].Depth; 

       // To convert to a byte, we're discarding the most-significant 
       // rather than least-significant bits. 
       // We're preserving detail, although the intensity will "wrap." 
       // Values outside the reliable depth range are mapped to 0 (black). 

       // Note: Using conditionals in this loop could degrade performance. 
       // Consider using a lookup table instead when writing production code. 
       // See the KinectDepthViewer class used by the KinectExplorer sample 
       // for a lookup table example. 
       byte intensity = (byte)(depth >= minDepth && depth <= maxDepth ? depth : 0); 

       // Write out blue byte 
       this.colorPixels[colorPixelIndex++] = intensity; 

       // Write out green byte 
       this.colorPixels[colorPixelIndex++] = intensity; 

       // Write out red byte       
       this.colorPixels[colorPixelIndex++] = intensity; 

       // We're outputting BGR, the last byte in the 32 bits is unused so skip it 
       // If we were outputting BGRA, we would write alpha here. 
       ++colorPixelIndex; 
      } 

      // Write the pixel data into our bitmap 
      this.colorBitmap.WritePixels(
       new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight), 
       this.colorPixels, 
       this.colorBitmap.PixelWidth * sizeof(int), 
       0); 
     } 
    } 
} 

這個特定類的完整代碼可以在這裏找到:http://kinectforwindows.codeplex.com/SourceControl/changeset/view/861462899ae7#v1.x/ToolkitSamples1.6.0/C#/DepthBasics-WPF/MainWindow.xaml.cs

的「Kinect的資源管理器」的例子是另一個很好的回顧,因爲它一次檢查所有三個流。它需要庫中未包含在CodePlex存儲庫中,但可在Kinect for Windows Toolkit中找到。

+0

我需要對繪製的_depthImage_,它使用位圖執行一些openCV操作。用於openCv的EmguCV包裝器不接受_WritableBitmap_ AFAIK。 雖然我已經解決了這個問題,謝謝你的時間! :) – uvcyclotron 2013-03-15 20:17:44

相關問題