Kinect深度圖像濾波


最近在做機器視覺方面的一點工作,用Kinect作sensor獲取深度數據、顏色、手勢識別等。非常感激CNBlog上的兩篇博文:(1)獨釣寒江的http://www.cnblogs.com/yangecnu/archive/2012/03/30/KinectSDK_Geting_Started.html 從中學到了不少關於在WPF平台上使用C#,利用微軟Kinect SDK開發自己的應用程序的知識,給了我很大的幫助,在此表示感謝!

但是博主獨釣寒江的博文中,針對深度圖像濾波,只簡要說了取反和用Bgr32表示深度圖像,效果不是很理想。

后來,發現了另一篇博文(2)何文西的http://www.cnblogs.com/TravelingLight/archive/2012/05/25/2517680.html介紹了國外的一篇文章,上面介紹了外國作者自己開發的兩種濾波方法:像素濾波法,加權移動平均法。效果很好!可惜只有代碼片段無法試驗,而且濾波算法不是特別容易理解。實在可惜!

前幾天偶然跟蹤並找到了作者的源代碼http://kinectdepthsmoothing.codeplex.com/,下載來看。運行發現,程序要求:VS2012以上、Kinect SDK 1.7以上版本,而根據獨釣寒江的博文指導,其中的代碼用的是SDK 1.0,進一步發現其中的一些API函數,數據類型都不相同,再者,Kinectdepthsmoothing中xaml代碼用的是后台創建,而獨釣寒江的博文中xaml用的是布局式,而我對xaml又不懂,如何把這兩個程序結合起來呢?

由於獨釣寒江的博文給出的程序中,有大量的功能實現,比如保存圖像、鼠標單擊顯示像素深度值、彩色渲染、人體尺寸獲取,游戲者索引等等,而外國朋友的kinectdepthsmoothing程序只有濾波和保存圖像,那么考慮把濾波模塊移植到獨釣寒江的程序中,並且不改變原來的布局式界面。在移植的過程中,主要解決了以下幾個類型不兼容的問題:

a) 將short[] pixelData類型改成DepthImagePixel[] pixelData,這里注意:SDK 1.8版本中,private DepthImagePixel[] depthPixels;其中獲取深度數據為

 1 short depth=depthPixels[i].Depth;  

而SKD 1.0版本中,short[] pixelData獲取深度數據的方式為

 1 Int32 depth = this.depthPixels[pIndex] >> DepthImageFrame.PlayerIndexBitmaskWidth;  

需要進行移位操作。而且兩種方式的depth類型不一樣,一個是short16位,一個是Int32位。

b) 用三通道Bgr32格式的colorBitmap存儲深度圖像,而不是Gray16格式的depthBitmap。除了深度數組的格式不一樣之外,外國朋友的程序中,有這樣幾行代碼值得關注,

 

1                 //獲得當前幀最大和最小可用的深度值
2                 short minDepth = (short)lastDepthFrame.MinDepth;
3                 short maxDepth = (short)lastDepthFrame.MaxDepth; 

以及

 1      //在這里將depthPixels數組中的深度值,逐元素,轉換並存儲到colorPixles中                 
 2 
 3                //最后,將colorPixels寫入colorBitmap中                 
 4 
 5                int colorPixelIndex = 0;                 
 6 
 7                for (int i = 0; i < depthPixels.Length; i++)                 
 8 
 9                {                     
10 
11                 //獲取該元素(點)的深度值                     
12 
13                 short depth = depthPixels[i].Depth;                     
14 
15                 byte intensity = (byte)255;
16 
17                 int newMax = depth - minDepth;                     
18 
19                 if (newMax > 0)                                            
20 
21                      {intensity = (byte)(255 - (255 * newMax / (3150)));  }                   
22 
23                  this.colorPixels[colorPixelIndex++] = intensity;//blue                     
24 
25                 this.colorPixels[colorPixelIndex++] = intensity;//green                     
26 
27                 this.colorPixels[colorPixelIndex++] = intensity;//red                     
28 
29                 ++colorPixelIndex;    
30              }

  最后將數據寫入colorBitmap時,代碼為

              this.colorBitmap.WritePixels(
                     new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
                     this.colorPixels,
                     this.colorBitmap.PixelWidth * sizeof(int),
                     0);

  使用了 this.colorBitmap.PixelWidth這個寫法,而不是獨釣寒江博主的程序中,使用depthStream.FrameHeight創建圖像的矩形區域this.depthRect = new Int32Rect(0, 0, depthStream.FrameWidth, depthStream.FrameHeight);

c) 此外,初始化變量(數據容器depthPixels和colorPixels)時,要注意colorPixels的大小

1                 this.depthPixels = new DepthImagePixel[depthStream.FramePixelDataLength];
2                 this.colorPixels = new byte[depthStream.FramePixelDataLength * sizeof(int)];

總之,將兩個程序結合起來,要注意兩個方面,一是界面的形式,布局還是后台創建,二是,.cs程序中由於使用的SDK版本不同,有很多API和數據類型不一致的地方,需要修改。由於正在做后續的實驗,比如加入了自己的利用深度數據進行邊緣檢測的代碼,還有很多想法沒有實現,暫時寫到這里吧。到時候會將完整代碼上傳到網絡上,供大家參考!謝謝。

下篇文章將介紹基於深度值的目標分割,並附上完整代碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM