一、Kinect視角場
1、43°垂直方向和57°水平方向可視范圍。
2、視角場常量值定義
屬性 |
描述 |
Format | 獲取或設置深度圖像格式 |
MaxDepth | 獲取最大深度值 |
MinDepth | 獲取最小深度值 |
NominalDiagonalFieldOfView | 獲取紅外攝像頭的標准場視角,單位是度 |
NominalFocalLengthInPixels | 獲取紅外攝像頭的標准焦距,單位是像素點 |
NominalHorizontalFieldOfView | 獲取紅外攝像頭的水平視角,單位是度 |
NominalInverseFocalLengthInPixels | 獲取紅外攝像頭的標准焦距的倒數 |
NominalVerticalFieldOfView | 獲取紅外攝像頭的垂直視角,單位為度 |
Range | 設置紅外攝像頭采用“默認模式”還是“近景模式” |
TooFarDepth | 獲取紅外值有效范圍的最大值,即紅外攝像頭能看到的最遠距離 |
TooNearDepth | 獲取紅外值有效范圍的最小值,即紅外攝像頭能看到的最近距離 |
UnknownDepth | 未知紅外距離的數值 |
3、通過骨骼跟蹤對象Skeleton.ClippedEdges的屬性,判斷用戶是否處於Kinect的有效視野范圍內。
將骨骼跟蹤調節到最佳位置的方法有:
**用戶移動到有效視野的橫截面中:例如,再Kinect游戲中會提示玩家走近一些
**通過KinectSensor.ElevationAngle屬性控制Kinect的垂直仰角,改善用戶的有效視角場橫截面。
二、深度值與實際距離的對比
1、深度圖像的每像素占用2字節,同常量DepthImage.BytesPerPiexl的定義,可以用short變量定義這個像素。其中,高13位表示從Kinect紅外攝像頭到最近物體對象的距離,以毫米為單位;低三位表示用戶索引編號,DepthImageFrame.PlayerIndexBitmaskWidth定義了此值。
2、Kinect深度會隨着目標物體的距離而發生偏差,距離越遠偏差越大。
三、深度圖像的直方圖
1、亮度直方圖屬於圖像處理的基本運算,通過它可以提取有效的“亮度”特征。亮度直方圖能體現每個亮度值在圖像中的占有率。利用“亮度”特征值,並基於一定的亮度閥值,可以從果盤中分辨出紅蘿卜和西紅柿。
2、直方圖統計信息的價值
using System; using System.Linq; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using Microsoft.Kinect; using System.Windows.Shapes; namespace KinectDepthHistogram { public partial class MainWindow : Window { //簡化程序,未做預防性代碼 KinectSensor sensor = KinectSensor.KinectSensors.First(); short[] pixelData; public MainWindow() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainWindow_Loaded); this.Unloaded += new RoutedEventHandler(MainWindow_Unloaded); sensor.DepthStream.Enable(); sensor.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(sensor_DepthFrameReady); } private Int32 depthFrameBehind = 0; void sensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e) { bool receivedData = false; using (DepthImageFrame DFrame = e.OpenDepthImageFrame()) { if (DFrame == null) { // The image processing took too long. More than 2 frames behind. depthFrameBehind++; labelDepthFrameBehind.Content = depthFrameBehind.ToString(); } else { pixelData = new short[DFrame.PixelDataLength]; DFrame.CopyPixelDataTo(pixelData); //繪制深度直方圖 DrawDepthHistogram(DFrame, pixelData); receivedData = true; } } if (receivedData) { BitmapSource source = BitmapSource.Create(640, 480, 96, 96, PixelFormats.Gray16, null, pixelData, 640 * 2); depthImage.Source = source; } } void MainWindow_Unloaded(object sender, RoutedEventArgs e) { sensor.Stop(); } void MainWindow_Loaded(object sender, RoutedEventArgs e) { sensor.Start(); } #region DepthHistogram //有效視距范圍的閥值: 0.8米到3米 private const int LowDepthThreshold = 800; private const int HighDepthThreshold = 4000; /// <summary> /// 繪制深度圖像的直方圖 /// </summary> /// <param name="depthFrame"></param> /// <param name="pixelData"></param> private void DrawDepthHistogram(DepthImageFrame depthFrame, short[] pixelData) { int depth; int[] depths = new int[4096]; double chartBarWidth = Math.Max(3, DepthHistogram.ActualWidth / depths.Length); //遍歷深度像素數組,並獲取深度值.並統計每一個深度值出現的次數 for (int i = 0; i < pixelData.Length; i++) { //前13位為深度值,單位毫米 depth = pixelData[i] >> DepthImageFrame.PlayerIndexBitmaskWidth; //有效視距內的統計 if (depth >= LowDepthThreshold && depth <= HighDepthThreshold) { depths[depth]++; } } int maxValue = 0; //查找depth數組中的最大深度值 for (int i = LowDepthThreshold; i < HighDepthThreshold; i++) { maxValue = Math.Max(maxValue, depths[i]); } //繪制直方圖,統計各個深度段的像素個數 DepthHistogram.Children.Clear(); for (int i = LowDepthThreshold; i < HighDepthThreshold; i++) { //顯示有深度數值的 if (depths[i] > 0) { Rectangle r = new Rectangle(); r.Fill = Brushes.Green; r.Width = chartBarWidth; r.Height = DepthHistogram.ActualHeight * (depths[i] / (double)maxValue); r.Margin = new Thickness(1, 0, 1, 0); r.VerticalAlignment = System.Windows.VerticalAlignment.Bottom; DepthHistogram.Children.Add(r); } } } #endregion } }