• kinect学习笔记(四)——各种数据流


    一、kinect开发的一个流程图

    image

    1、我们可以知道一个简单的框架就是几部分

    (1)选择使用的kinect传感器

    KinectSensor.KinectSensors[0]

    (2)打开需要的数据流

    _kinect.DepthStream.Enable();
    _kinect.ColorStream.Enable();
    _kinect.SkeletonStream.Enable();

    (3)注册事件

    其实就是主要的算法在这里体现。

    有个小窍门:VS的CodeSnippet快速生成事件代码,如在代码“_kinect.DepthFrameReady+=”后面连续按两次“Tab”键,就会生成相应的时间并处理相应的代码。

    二、初始化、启用kinect设备

    代码如下,记得要声明一个私有成员变量_kinect,并在MainWindow()里面调用。

    KinectSensor _kinect;
    
            private void startKinect()
            {
                if(KinectSensor.KinectSensors.Count>0)
                {
                    //选择第一个kinect设备
                    _kinect = KinectSensor.KinectSensors[0];
                    MessageBox.Show("Kinect目前状态为:" + _kinect.Status);
    
                    //初始化设定,启用彩色图像,深度图像和骨骼追踪
                    _kinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
                    _kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
                    _kinect.SkeletonStream.Enable();
    
                    //注册时间,该方法将保证彩色图像,深度图像和骨骼图像的同步
                    _kinect.AllFramesReady += _kinect_AllFramesReady;
    
                    //启动kinect
                    _kinect.Start();
                }
                else
                {
                    MessageBox.Show("没有发现任何kinect设备");
                }
            }

    void _kinect_AllFramesReady(object sender, AllFramesReadyEventArgs e)
    {
                
    }


    三、彩色图像流数据处理

    1、在MainWindows窗体上新增一个Image控件,命名为imageCamera

    2、在_kinect_AllFramesReady事件处理中增加如下代码、

    //显示彩色摄像头
               using(ColorImageFrame colorFrame = e.OpenColorImageFrame())
               {
                   if(colorFrame == null)
                   {
                       return;
                   }
    
                   byte[] pixels = new byte[colorFrame.PixelDataLength];
                   colorFrame.CopyPixelDataTo(pixels);
    
                   //BGR32格式图片一个像素为4个字节
                   int stride = colorFrame.Width * 4;
                   ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, 96, 96, PixelFormats.Bgr32, null, pixels, stride);
    
                  
               }

          BGR32图像的1像素对应4字节(32位),分别是B,G,R,阿尔法通道(透明度)。

          BitmapSource.Create是一个从数组到二维矩阵的过程。

          Stride为图片步长,代表图片一行像素所占的字节数,为摄像头传输图片的宽度乘以4,

          DPI,越高越清晰,普通的显示器就是96差不多。

    3、效果图

    image

    四、深度数据捕获

    1、定义深度图像的有效视角范围。

    const float MaxDepthDistance = 4095;
            const float MinDepthDistance = 850;
            const float MaxDepthDistanceOffest = MaxDepthDistance - MinDepthDistance;
    
            private const int RedIndex = 2;
            private const int GreenIndex = 1;
            private const int BlueIndex = 0;

    2、代码

    private byte[]convertDepthFrameToColorFrame(DepthImageFrame depthFrame)
            {
                short[] rawDepthData = new short[depthFrame.PixelDataLength];
                depthFrame.CopyPixelDataTo(rawDepthData);
    
                Byte[] piexls = new byte[depthFrame.Height * depthFrame.Width * 4];
    
                for(int depthIndex = 0,colorIndex=0;depthIndex<rawDepthData.Length&&colorIndex<piexls.Length;depthIndex++,colorIndex+=4)
                {
                    int player = rawDepthData[depthIndex] & DepthImageFrame.PlayerIndexBitmask;
    
                    int depth = rawDepthData[depthIndex];
                    if(depth<=900)
                    {
                        piexls[colorIndex + BlueIndex] = 255;
                        piexls[colorIndex + GreenIndex] = 0;
                        piexls[colorIndex + RedIndex] = 0;
                    }
                    else if(depth>900&&depth<2000)
                    {
                        piexls[colorIndex + BlueIndex] = 0;
                        piexls[colorIndex + GreenIndex] = 255;
                        piexls[colorIndex + RedIndex] = 0;
                    }
                    else if(depth>2000)
                    {
                        piexls[colorIndex + BlueIndex] = 0;
                        piexls[colorIndex + GreenIndex] = 0;
                        piexls[colorIndex + RedIndex] = 255;
                    }
    
                    byte intensity = CalculateIntensityFromDepth(depth);
                    piexls[colorIndex + BlueIndex] = intensity;
                    piexls[colorIndex + GreenIndex] = intensity;
                    piexls[colorIndex + RedIndex] = intensity;
    
                    if(player>0)
                    {
                        piexls[colorIndex + BlueIndex] = Colors.LightGreen.B;
                        piexls[colorIndex + GreenIndex] = Colors.LightGreen.G;
                        piexls[colorIndex + RedIndex] = Colors.LightGreen.R;
                    }
                }
                return piexls;
            }
    
            void _kinect_AllFramesReady(object sender, AllFramesReadyEventArgs e)
            {
                //显示彩色摄像头
               using(ColorImageFrame colorFrame = e.OpenColorImageFrame())
               {
                   if(colorFrame == null)
                   {
                       return;
                   }
    
                   byte[] pixels = new byte[colorFrame.PixelDataLength];
                   colorFrame.CopyPixelDataTo(pixels);
    
                   //BGR32格式图片一个像素为4个字节
                   int stride = colorFrame.Width * 4;
                   ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, 96, 96, PixelFormats.Bgr32, null, pixels, stride);
    
               }
    
                using(DepthImageFrame depthFrame = e.OpenDepthImageFrame())
                {
                    if(depthFrame==null)
                    {
                        return;
                    }
    
                    byte[] piexls = convertDepthFrameToColorFrame(depthFrame);
    
                    int stride = depthFrame.Width * 4;
                    imageDepth.Source = BitmapSource.Create(depthFrame.Width, depthFrame.Height, 96, 96, PixelFormats.Bgr32, null, piexls, stride);
    
                }

    3、效果图

    image

    五、骨骼追踪

    1、首先注释掉我们之前注册的时间,重新注册一个彩色数据流时间和一个骨骼事件,然后添加如下代码

    private Skeleton[] skeletons;
            void _kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
            {
                bool isSkeletonDataEeady = false;
                using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
                {
                    if(skeletonFrame!=null)
                    {
                        skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
                        skeletonFrame.CopySkeletonDataTo(skeletons);
                        isSkeletonDataEeady = true;
                    }
    
                }
    
                if(isSkeletonDataEeady==true)
                {
                    Skeleton currentSkeleton = (from s in skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault();
                    if(currentSkeleton !=null)
                    {
                        lockHeadWithSpot(currentSkeleton);
                    }
             
                }
            }
    
            void lockHeadWithSpot(Skeleton s)
            {
                Joint head = s.Joints[JointType.Head];
                ColorImagePoint colorPoint = _kinect.MapSkeletonPointToColor(head.Position, _kinect.ColorStream.Format);
    
                Point p = new Point((int)(ImageCamera.Width * colorPoint.X / _kinect.ColorStream.FrameWidth),
                                     (int)(ImageCamera.Height * colorPoint.Y / _kinect.ColorStream.FrameHeight));
    
                Canvas.SetLeft(ellipseHead, p.X);
                Canvas.SetRight(ellipseHead, p.Y);
            }
    
            void _kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
            {
                using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
                {
                    if (colorFrame == null)
                    {
                        return;
                    }
    
                    byte[] pixels = new byte[colorFrame.PixelDataLength];
                    colorFrame.CopyPixelDataTo(pixels);
    
                    //BGR32格式图片一个像素为4个字节
                    int stride = colorFrame.Width * 4;
                    ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, 96, 96, PixelFormats.Bgr32, null, pixels, stride);
    
                }
               
            }

    2、效果图

    image

    六关闭kinect设备

    private void stopKinect()
            {
                if(_kinect != null)
                {
                    if(_kinect.Status== KinectStatus.Connected)
                    {
                        _kinect.Stop();
                    }
                }
            }
  • 相关阅读:
    LIS例题
    基数排序板子
    lower_bound和upper_bound在刷leetcode的时候...
    leetcode1081/316 求字典序最小的包含所有出现字符一次的子序列
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合 【深度优先搜索】【原创】
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合【原创】
    Spring 中注入 properties 中的值
    Java 枚举活用
    Intellij IDEA 快捷键整理(TonyCody)
    WIN API -- 2.Hello World
  • 原文地址:https://www.cnblogs.com/BlueMountain-HaggenDazs/p/4072605.html
Copyright © 2020-2023  润新知