首页 > 代码库 > Kinect 开发 —— 骨骼数据与彩色影像和深度影像的对齐

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 = http://www.mamicode.com/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;            }        }    }