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 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

    }

}

你可能感兴趣的:(kinect)