• 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;
                }
            }
    
        }
  • 相关阅读:
    调试技术 Orisun 博客园
    Core Dump和/proc调试 Orisun 博客园
    再谈select, iocp, epoll,kqueue及各种I/O复用机制 Shallway 博客频道 CSDN.NET
    基础很重要
    Speech and Language Processing (2nd Ed.): Updates
    CS 288: Statistical Natural Language Processing
    对C++中string类型的总结
    HTTP代理实现请求报文的拦截与篡改1 jivi 博客园
    学习优秀源码 Orisun 博客园
    分享:苹果老员工可享两年离岗留职待遇
  • 原文地址:https://www.cnblogs.com/sprint1989/p/3863886.html
Copyright © 2020-2023  润新知