1. 程式人生 > >學習kinect2.0 之colorBasics-WPF

學習kinect2.0 之colorBasics-WPF

/*基於Kinect開發的應用程式最開始需要用到的物件就是KinectSensor物件,
         * 該物件直接表示Kinect硬體裝置。KinectSensor物件是我們想要獲取資料,
         * 包括彩色影像資料,景深資料和骨骼追蹤資料的源頭。


            從KinectSensor獲取資料最常用的方式是通過監聽該物件的一系列事件。
         * 每一種資料流都有對應的事件,當改型別資料流可用時,就會觸發改時間。


           每一種資料流(Color,Depth,Skeleton)都是以資料點的方式在不同的座標系中顯示的,
         * 在後面的討論中我們能夠清楚的看到這一點。將一個數據流中的點資料轉換到另一個數據流中是一個很常見的操作,
         * KinectSensor物件有一些列的方法能夠進行資料流到資料點陣的轉換,
         * 他們是MapDepthToColorImagePoint,MapDepthToSkeletonPoint以及MapSkeletonPointToDepth。*/
           // 1.KinectSensor.open()開啟感測器。
           //2.獲取KinectSensor感測器物件,初始化
          //3.開啟對應的this.kinectSensor.ColorFrameSource.OpenReader(),選定所用的流,(說明Kinect V2會將流都扔給你。) FrameDescription獲得對色彩幀的描述,在這裡是以何種格式。
          //4.註冊色彩幀到達後的處理事件,繫結的方法要自己寫,
          //5.使用WriteableBitmap初始化bitmap(提前),
            //在4.的方法中畫出相應的點陣圖。
          //6.寫返回Bitmap的ImageSource函式,可用其他替帶。
          //7.收尾,釋放資源,KinectSensor.close()關閉感測器。
        //...

        /// <summary>
        /// Active Kinect sensor
        /// </summary>
        private KinectSensor kinectSensor = null;//建立一個感測器物件


        /// <summary>
        /// Reader for color frames
        /// </summary>
/// //建立一個彩色資料介面 類似的還有DepthFrameReader
        private ColorFrameReader colorFrameReader = null;



        /// <summary>
        /// Bitmap to display
        /// </summary>
/// //WriteableBitmap類用於顯示點陣圖
        private WriteableBitmap colorBitmap = null;


        /// <summary>
        /// Current status text to display
        /// </summary>
        private string statusText = null;



        /// <summary>

        /// Initializes a new instance of the MainWindow class.
        /// </summary>
        public MainWindow()
        {
            // get the kinectSensor object
      //KinectSensor類的GetDefault()函式可以取得當前連線的kinect裝置;
            this.kinectSensor = KinectSensor.GetDefault();


            // open the reader for the color frames
    //開啟當前kinect裝置的彩色資料幀資訊源
            this.colorFrameReader = this.kinectSensor.ColorFrameSource.OpenReader();


            // wire handler for frame arrival
//事件  函式  屬性  註冊色彩幀到達後的發生事件,繫結執行函式Reader_ColorFreamArrived
            this.colorFrameReader.FrameArrived += this.Reader_ColorFrameArrived;


            // create the colorFrameDescription from the ColorFrameSource using Bgra format
  //獲得對色彩幀的描述,以Rgba格式
            FrameDescription colorFrameDescription = this.kinectSensor.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra);


            // create the bitmap to display
        //創造用於顯示的bitmap,圖寬,圖高,水平/垂直每英寸畫素點數,畫素點格式,調色盤為空.
            this.colorBitmap = new WriteableBitmap(colorFrameDescription.Width, colorFrameDescription.Height, 96.0, 96.0, PixelFormats.Bgr32, null);


            // set IsAvailableChanged event notifier
            this.kinectSensor.IsAvailableChanged += this.Sensor_IsAvailableChanged;


            // open the sensor
            this.kinectSensor.Open();


            // set the status text
            this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
                                                            : Properties.Resources.NoSensorStatusText;


            // use the window object as the view model in this simple example
            this.DataContext = this;


            // initialize the components (controls) of the window
            this.InitializeComponent();
        }


        /// <summary>
        /// INotifyPropertyChangedPropertyChanged event to allow window controls to bind to changeable data
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;


        /// <summary>
        /// Gets the bitmap to display
        /// </summary>
        /// //以下為wpf的顯示提供圖源
        public ImageSource ImageSource
        {
            get
            {
                return this.colorBitmap;
            }
        }


        /// <summary>
        /// Gets or sets the current status text to display
        /// </summary>
        /// //用於顯示底部顯示狀態資訊
        public string StatusText
        {
            get
            {
                return this.statusText;
            }


            set
            {
                if (this.statusText != value)
                {
                    this.statusText = value;


                    // notify any bound elements that the text has changed
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs("StatusText"));
                    }
                }
            }
        }


        /// <summary>
        /// Execute shutdown tasks
        /// </summary>
        /// <param name="sender">object sending the event</param>
        /// <param name="e">event arguments</param>
        /// //以下為在視窗關閉後關閉感測與釋放從感測器得到的資料,關閉之前先檢查,
        private void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            if (this.colorFrameReader != null)
            {
                // ColorFrameReder is IDisposable
                this.colorFrameReader.Dispose();
                this.colorFrameReader = null;
            }


            if (this.kinectSensor != null)
            {
                this.kinectSensor.Close();
                this.kinectSensor = null;
            }
        }


        /// <summary>
        /// Handles the user clicking on the screenshot button
        /// </summary>
        /// <param name="sender">object sending the event</param>
        /// <param name="e">event arguments</param>
        /// //截圖函式處理
        private void ScreenshotButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.colorBitmap != null)
            {
                // create a png bitmap encoder which knows how to save a .png file
                BitmapEncoder encoder = new PngBitmapEncoder();


                // create frame from the writable bitmap and add to encoder
                encoder.Frames.Add(BitmapFrame.Create(this.colorBitmap));


                string time = System.DateTime.Now.ToString("hh'-'mm'-'ss", CultureInfo.CurrentUICulture.DateTimeFormat);


                string myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);


                string path = Path.Combine(myPhotos,  time+ "截圖" + ".png");


                // write the new file to disk
                try
                {
                    // FileStream is IDisposable
                    using (FileStream fs = new FileStream(path, FileMode.Create))
                    {
                        encoder.Save(fs);
                    }


                    this.StatusText = string.Format(Properties.Resources.SavedScreenshotStatusTextFormat, path);
                }
                catch (IOException)
                {
                    this.StatusText = string.Format(Properties.Resources.FailedScreenshotStatusTextFormat, path);
                }
            }
        }


        /// <summary>
        /// Handles the color frame data arriving from the sensor
        /// </summary>
        /// <param name="sender">object sending the event</param>
        /// <param name="e">event arguments</param>
        private void Reader_ColorFrameArrived(object sender, ColorFrameArrivedEventArgs e)
        {
            // ColorFrame is IDisposable
            using (ColorFrame colorFrame = e.FrameReference.AcquireFrame())
            {
                if (colorFrame != null)
                {
                    //獲得對幀的描述物件
                    FrameDescription colorFrameDescription = colorFrame.FrameDescription;


                    using (KinectBuffer colorBuffer = colorFrame.LockRawImageBuffer())
                    {
                        this.colorBitmap.Lock();


                        // verify data and write the new color frame data to the display bitmap
                        if ((colorFrameDescription.Width == this.colorBitmap.PixelWidth) && (colorFrameDescription.Height == this.colorBitmap.PixelHeight))
                        {   //顯示方法
                            //colorFrame的幀資料轉化到colorBitmap中去
                            byte[] framedata = new byte[colorFrameDescription.Height * colorFrameDescription.Width * 4];
                            colorFrame.CopyConvertedFrameDataToArray(framedata, ColorImageFormat.Bgra);

                        //改變alpha值
 /*                     for (int i = 0; i < framedata.Length - 4; i += 4)
                         {
                             framedata[i +3] = 255;
                         }
 */