Kinect学习笔记(六)——深度数据测量技术及应用

一、Kinect视角场

1、43°垂直方向和57°水平方向可视范围。

image

2、视角场常量值定义

属性

 

描述

 
Format   获取或设置深度图像格式  
MaxDepth   获取最大深度值  
MinDepth   获取最小深度值  
NominalDiagonalFieldOfView   获取红外摄像头的标准场视角,单位是度  
NominalFocalLengthInPixels   获取红外摄像头的标准焦距,单位是像素点  
NominalHorizontalFieldOfView   获取红外摄像头的水平视角,单位是度  
NominalInverseFocalLengthInPixels   获取红外摄像头的标准焦距的倒数  
NominalVerticalFieldOfView   获取红外摄像头的垂直视角,单位为度  
Range   设置红外摄像头采用“默认模式”还是“近景模式”  
TooFarDepth   获取红外值有效范围的最大值,即红外摄像头能看到的最远距离  
TooNearDepth   获取红外值有效范围的最小值,即红外摄像头能看到的最近距离  
UnknownDepth   未知红外距离的数值  

image

3、通过骨骼跟踪对象Skeleton.ClippedEdges的属性,判断用户是否处于Kinect的有效视野范围内。

将骨骼跟踪调节到最佳位置的方法有:

**用户移动到有效视野的横截面中:例如,再Kinect游戏中会提示玩家走近一些

**通过KinectSensor.ElevationAngle属性控制Kinect的垂直仰角,改善用户的有效视角场横截面。

二、深度值与实际距离的对比

1、深度图像的每像素占用2字节,同常量DepthImage.BytesPerPiexl的定义,可以用short变量定义这个像素。其中,高13位表示从Kinect红外摄像头到最近物体对象的距离,以毫米为单位;低三位表示用户索引编号,DepthImageFrame.PlayerIndexBitmaskWidth定义了此值。

image

2、Kinect深度会随着目标物体的距离而发生偏差,距离越远偏差越大。

image

三、深度图像的直方图

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></param> /// <param></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 } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzdgjz.html