Kinect 开发 —— 骨骼数据与彩色影像和深度影像的对齐

  • 在显示彩色影像和深度影像时最好使用WriteableBitmap对象;
  • 要想将骨骼数据影像和深度影像,或者彩色影像叠加到一起,首先要确定深度影像的分辨率和大小,为了方便,这里将深度影像数据和彩色影像数据都采用640x480Fps30的格式,同时将Grid的大小也设置为640*480。
  • 要将骨骼数据和深度影像数据叠加,需要将关节点转换到深度影像所在空间中,可以直接调用MapSkeletonPointToDepthPoint,如果要将骨骼数据叠加到彩色影像上,只需要调用MapSkeletonPointToColorPoint方法。


前端代码

界面很简单,在Grid对象下面有两个Image对象,和一个嵌套的Grid对象。前面两个Image对象分别用来显示彩色影像数据和深度影像数据,后面的Grid对象是用来绘制骨骼的,需要注意的是Grid对象的属性要设置为Transparent,这样的话就可以将Grid上绘制骨骼而不会遮住下面的彩色影像或者深度影像了。



后台代码

public partial class MainWindow : Window
    {
        private KinectSensor kinectDevice;
        private readonly Brush[] skeletonBrushes;//绘图笔刷

        private WriteableBitmap depthImageBitMap;
        private Int32Rect depthImageBitmapRect;
        private Int32 depthImageStride;
        private DepthImageFrame lastDepthFrame;

        private WriteableBitmap colorImageBitmap;
        private Int32Rect colorImageBitmapRect;
        private int colorImageStride;
        private byte[] colorImagePixelData;

        private Skeleton[] frameSkeletons;

        public MainWindow()
        {
            InitializeComponent();

            skeletonBrushes = new Brush[] { Brushes.Red };

            KinectSensor.KinectSensors.StatusChanged += KinectSensors_StatusChanged;
            this.KinectDevice = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
        }

        public KinectSensor KinectDevice
        {
            get { return this.kinectDevice; }
            set
            {
                if (this.kinectDevice != value)
                {
                    //Uninitialize
                    if (this.kinectDevice != null)
                    {
                        this.kinectDevice.Stop();
                        this.kinectDevice.SkeletonFrameReady -= kinectDevice_SkeletonFrameReady;
                        this.kinectDevice.ColorFrameReady -= kinectDevice_ColorFrameReady;
                        this.kinectDevice.DepthFrameReady -= kinectDevice_DepthFrameReady;
                        this.kinectDevice.SkeletonStream.Disable();
                        this.kinectDevice.DepthStream.Disable();
                        this.kinectDevice.ColorStream.Disable();
                        this.frameSkeletons = null;
                    }

                    this.kinectDevice = value;

                    //Initialize
                    if (this.kinectDevice != null)
                    {
                        if (this.kinectDevice.Status == KinectStatus.Connected)
                        {
                            this.kinectDevice.SkeletonStream.Enable();
                            this.kinectDevice.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
                            this.kinectDevice.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
                            this.frameSkeletons = new Skeleton[this.kinectDevice.SkeletonStream.FrameSkeletonArrayLength];
                            this.kinectDevice.SkeletonFrameReady += kinectDevice_SkeletonFrameReady;
                            this.kinectDevice.ColorFrameReady += kinectDevice_ColorFrameReady;
                            this.kinectDevice.DepthFrameReady += kinectDevice_DepthFrameReady;
                            this.kinectDevice.Start();

                            DepthImageStream depthStream = kinectDevice.DepthStream;
                            depthStream.Enable();

                            depthImageBitMap = new WriteableBitmap(depthStream.FrameWidth, depthStream.FrameHeight, 96, 96, PixelFormats.Gray16, null);
                            depthImageBitmapRect = new Int32Rect(0, 0, depthStream.FrameWidth, depthStream.FrameHeight);
                            depthImageStride = depthStream.FrameWidth * depthStream.FrameBytesPerPixel;

                            ColorImageStream colorStream = kinectDevice.ColorStream;
                            colorStream.Enable();
                            colorImageBitmap = new WriteableBitmap(colorStream.FrameWidth, colorStream.FrameHeight,
                                                                                            96, 96, PixelFormats.Bgr32, null);
                            this.colorImageBitmapRect = new Int32Rect(0, 0, colorStream.FrameWidth, colorStream.FrameHeight);
                            this.colorImageStride = colorStream.FrameWidth * colorStream.FrameBytesPerPixel;
                            ColorImage.Source = this.colorImageBitmap;

                            DepthImage.Source = depthImageBitMap;
                        }
                    }
                }
            }
        }

        void kinectDevice_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
        {
            using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
            {
                if (depthFrame != null)
                {
                    short[] depthPixelDate = new short[depthFrame.PixelDataLength];
                    depthFrame.CopyPixelDataTo(depthPixelDate);
                    depthImageBitMap.WritePixels(depthImageBitmapRect, depthPixelDate, depthImageStride, 0);
                }
            }
        }

        void kinectDevice_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            using (ColorImageFrame frame = e.OpenColorImageFrame())
            {
                if (frame != null)
                {
                    byte[] pixelData = new byte[frame.PixelDataLength];
                    frame.CopyPixelDataTo(pixelData);
                    this.colorImageBitmap.WritePixels(this.colorImageBitmapRect, pixelData, this.colorImageStride, 0);
                }
            }
        }

        void kinectDevice_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            using (SkeletonFrame frame = e.OpenSkeletonFrame())
            {
                if (frame != null)
                {
                    Polyline figure;
                    Brush userBrush;
                    Skeleton skeleton;

                    LayoutRoot.Children.Clear();
                    frame.CopySkeletonDataTo(this.frameSkeletons);

                    for (int i = 0; i < this.frameSkeletons.Length; i++)
                    {
                        skeleton = this.frameSkeletons[i];

                        if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
                        {
                            userBrush = this.skeletonBrushes[i % this.skeletonBrushes.Length];

                            //绘制头和躯干
                            figure = CreateFigure(skeleton, userBrush, new[] { JointType.Head, JointType.ShoulderCenter, JointType.ShoulderLeft, JointType.Spine,
                                                                JointType.ShoulderRight, JointType.ShoulderCenter, JointType.HipCenter
                                                                });
                            LayoutRoot.Children.Add(figure);

                            figure = CreateFigure(skeleton, userBrush, new[] { JointType.HipLeft, JointType.HipRight });
                            LayoutRoot.Children.Add(figure);

                            //绘制作腿
                            figure = CreateFigure(skeleton, userBrush, new[] { JointType.HipCenter, JointType.HipLeft, JointType.KneeLeft, JointType.AnkleLeft, JointType.FootLeft });
                            LayoutRoot.Children.Add(figure);

                            //绘制右腿
                            figure = CreateFigure(skeleton, userBrush, new[] { JointType.HipCenter, JointType.HipRight, JointType.KneeRight, JointType.AnkleRight, JointType.FootRight });
                            LayoutRoot.Children.Add(figure);

                            //绘制左臂
                            figure = CreateFigure(skeleton, userBrush, new[] { JointType.ShoulderLeft, JointType.ElbowLeft, JointType.WristLeft, JointType.HandLeft });
                            LayoutRoot.Children.Add(figure);

                            //绘制右臂
                            figure = CreateFigure(skeleton, userBrush, new[] { JointType.ShoulderRight, JointType.ElbowRight, JointType.WristRight, JointType.HandRight });
                            LayoutRoot.Children.Add(figure);
                        }
                    }
                }
            }
        }

        private Polyline CreateFigure(Skeleton skeleton, Brush brush, JointType[] joints)
        {
            Polyline figure = new Polyline();

            figure.StrokeThickness = 8;
            figure.Stroke = brush;

            for (int i = 0; i < joints.Length; i++)
            {
                figure.Points.Add(GetJointPoint(skeleton.Joints[joints[i]]));
            }

            return figure;
        }

        private Point GetJointPoint(Joint joint)
        {
            CoordinateMapper cm = new CoordinateMapper(kinectDevice);

            DepthImagePoint point = cm.MapSkeletonPointToDepthPoint(joint.Position, this.KinectDevice.DepthStream.Format);
            //ColorImagePoint point = cm.MapSkeletonPointToColorPoint(joint.Position, this.KinectDevice.ColorStream.Format);
            point.X *= (int)this.LayoutRoot.ActualWidth / KinectDevice.DepthStream.FrameWidth;
            point.Y *= (int)this.LayoutRoot.ActualHeight / KinectDevice.DepthStream.FrameHeight;

            return new Point(point.X, point.Y);
        } 

        private void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case KinectStatus.Initializing:
                case KinectStatus.Connected:
                case KinectStatus.NotPowered:
                case KinectStatus.NotReady:
                case KinectStatus.DeviceNotGenuine:
                    this.KinectDevice = e.Sensor;
                    break;
                case KinectStatus.Disconnected:
                    //TODO: Give the user feedback to plug-in a Kinect device.
                    this.KinectDevice = null;
                    break;
                default:
                    //TODO: Show an error state
                    break;
            }
        }

    }

Kinect 开发 —— 骨骼数据与彩色影像和深度影像的对齐,布布扣,bubuko.com

时间: 2024-10-28 08:37:09

Kinect 开发 —— 骨骼数据与彩色影像和深度影像的对齐的相关文章

Kinect 开发 &mdash;&mdash; 骨骼追踪

骨骼追踪技术通过处理景深数据来建立人体各个关节的坐标,骨骼追踪能够确定人体的各个部分,如那部分是手,头部,以及身体.骨骼追踪产生X,Y,Z数据来确定这些骨骼点.骨骼追踪系统采用的景深图像处理技术使用更复杂的算法如矩阵变换,机器学习及其他方式来确定骨骼点的坐标. 获取骨骼数据 彩色影像数据,景深数据分别来自ColorImageSteam和DepthImageStream,同样地,骨骼数据来自SkeletonStream.访问骨骼数据和访问彩色影像数据.景深数据一样,也有事件模式和 "拉"

Kinect 开发 &mdash;&mdash; 骨骼追踪(下)

Kinect 连线游戏 在纸上将一些列数字(用一个圆点表示)从小到大用线连起来.游戏逻辑很简单,只不过我们在这里要实现的是动动手将这些点连起来,而不是用笔或者鼠标. 在开始写代码之前,需要明确定义我们的游戏目标.连线游戏是一个智力游戏,游戏者需要将数字从小到大连起来.程序可以自定义游戏上面的数字和位置(合称一个关卡).每一个关卡包括一些列的数字(以点表示)及其位置.我们要创建一个DotPuzzle类来管理这些点对象的集合.可能一开始不需要这个类,仅仅需要一个集合就可以,但是为了以后方便添加其他功

Kinect 开发 &mdash;&mdash; 骨骼追踪 (下)

基于景深数据的用户交互 骨骼数据中关节点不仅有X,Y值,还有一个深度值 除了使用WPF的3D特性外,在布局系统中可以根据深度值来设定可视化元素的尺寸大小来达到某种程序的立体效果. 下面的例子使用Canvas.ZIndex属性来设置元素的层次,手动设置控件的大小并使用ScaleTransform来根据深度值的改变来进行缩放.用户界面包括一些圆形,每一个圆代表一定的深度.应用程序跟踪用户的手部关节点,以手形图标显示,图标会根据用户手部关节点的深度值来进行缩放,用户离Kinect越近,手形图表越大,反

Kinect 开发 &mdash;&mdash; 杂一

Kinect 提供了非托管(C++)和托管(.NET)两种开发方式的SDK,如果您用C++开发的话,需要安装Speech Runtime(V11),Kinect for Windows Runtime和驱动的,如果您使用C#和VB.NET的话,需要Microsoft.Kinect.dll和Mirosoft.Speech.dll两个dll,这两个其实是对前C++里面的两个dll的.NET封装,不论何种开发,您都需要安装driver,所有这些都包含在Kinect SDK安装包中,安装方法您可以参考之

虚拟现实技术应用和Kinect开发——基于煤层气仿真训练系统

这篇是计算机中系统仿真/虚拟现实类的优质预售推荐<虚拟现实技术应用和Kinect开发--基于煤层气仿真训练系统>. 编辑推荐 本书内容新颖.层次清晰,适合从事相关理论研究及应用的专业人士和高校师生参考使用. 内容简介 本书依托国家科技重大专项项目--煤层气田地面集输信息集成及深度开发技术(2011ZX05039-004-02),借助于虚拟现实技术,开发一套专门应用于煤层气集输系统安全操作的仿真训练系统.本书详细介绍了虚拟现实技术以及煤层气产业的研究现状.煤层气仿真训练系统的应用与需求分析,然后

【Kinect开发笔记之(一)】初识Kinect

一.Kinect简介 Kinect是微软在2010年6月14日对XBOX360体感周边外设正式发布的名字.它是一种3D体感摄影机(开发代号"Project Natal"),同时它导入了即时动态捕捉.影像辨识.麦克风输入.语音辨识.社群互动等功能. 二.Kinect分类 Kinect for Xbox 360:该版本设计之初就是为了Xbox 360定制的,并未考虑其他的平台.从微软授权角度而言,它无法用于商业开发. Kinect for Windows : 固件上做了升级,支持"

【Kinect开发笔记之(二)】Kinect for windows发展历程

新版本SDK和旧版本的SDK完全兼容,如果您之前安装过旧版本的,可以直接安装新版本的SDK,但是如果您之前的开发版本是Beta版的,则需要卸载之后再安装新版本.在Kinect for Windows SDK 1.0版本中,SDK和示例文件是打包一起安装的.而在之后的版本,为了可以分别升级,微软把这两者分开独立为Kinect for Windows SDK和Kinect for Windows Developer Toolkit这两部分,所以需要分别下载安装, Kinect for Windows

Kinect开发学习笔记之(一)Kinect介绍和应用

Kinect开发学习笔记之(一)Kinect介绍和应用 [email protected] http://blog.csdn.net/zouxy09 一.Kinect简单介绍 Kinectfor Xbox 360,简称 Kinect,是由微软开发,应用于Xbox 360 主机的周边设备.它让玩家不须要手持或踩踏控制器,而是使用语音指令或手势来操作 Xbox360 的系统界面.它也能捕捉玩家全身上下的动作,用身体来进行游戏,带给玩家"免控制器的游戏与娱乐体验".其在2010年11月4日于

Kinect 开发 &mdash;&mdash; 硬件设备解剖

Kinect for Xbox: 360 不支持"近景模式" 三只眼睛 -- 红外投影机,RGB摄像头,红外深度投影头  -- 色彩影像中的每个像素分别与深度影像中的一个像素对应 四只耳朵 -- L形布局的麦克风阵列 -- 过滤背景噪声,定位声源 -- 根据麦克风阵列接听声音的时间差来判断声源方向 Moving Touch 传动马达电动机 -- 用于仰角控制 PS 1080 Soc 芯片 -- 深度图像获取能力   Xbox 360 (有效视距  1.2 ~~ 3.5)  最近距离 -