Kinnect開發——Visual Studio下開發流程


     配置好環境,就可以在Visual Studio下利用C#進行開發了。

     1、新建項目,選擇C#中的“windows窗體應用程序”。

      2、添加引用:
           第一個引用:在.net選項中選擇Microsoft.Kinect
           第二個引用:在瀏覽選項中找到EMGU的Emgu\emgucv-windows-x86 2.4.0.1717\bin,添加Emgu.CV.dll、Emgu.CV.UI.dll、Emgu.Util.dll
           第三個引用:在Microsoft SDKs的Microsoft SDKs\Kinect\Developer Toolkit v1.8.0\bin下的Microsoft.Speech.dll

     3、然後就像平常編程一樣了。

     4、基本例程

    

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


using System.Drawing.Imaging;
using System.Runtime.InteropServices;

using Microsoft.Kinect;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;

using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;
using LightBuzz.Vitruvius;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        //啓用的Kinect設備
        private KinectSensor sensor;

        //數據緩衝存儲空間
        ColorImageFormat colorImageFormat;
        DepthImageFormat depthImageFormat;

        private byte[] colorPixels;
        private DepthImagePixel[] depthPixels;
        private byte[] depthPixels4Channels;
        private Skeleton[] skeletonData;

        //顯示圖像中間結構  Kinect -> Bitmap -> Emgu CV
        private Bitmap colBitmap;
        private Bitmap depBitmap;

        int depthWidth, depthHeight;
        int colorWidth, colorHeight;

        private Image colorImage;
        private Image depthImage;

        //EmguCV 繪製字符串時候使用的字體
        private MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_COMPLEX, 0.3, 0.3);
        //繪製骨骼使用的Image
        private Image skeletonImage;

        private ColorImagePoint[] colorCoordinates;


        //語音識別引擎
        private SpeechRecognitionEngine speechEngine;

        GestureController _gestureController;


        [System.Runtime.InteropServices.DllImport("user32")]
        private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
        //移動鼠標 
        const int MOUSEEVENT_MOVE = 0x0001;
        //模擬鼠標左鍵按下 
        const int MOUSEEVENT_LEFTDOWN = 0x0002;
        //模擬鼠標左鍵擡起 
        const int MOUSEEVENT_LEFTUP = 0x0004;
        //模擬鼠標右鍵按下 
        const int MOUSEEVENT_RIGHTDOWN = 0x0008;
        //模擬鼠標右鍵擡起 
        const int MOUSEEVENT_RIGHTUP = 0x0010;
        //模擬鼠標中鍵按下 
        const int MOUSEEVENT_MIDDLEDOWN = 0x0020;
        //模擬鼠標中鍵擡起 
        const int MOUSEEVENT_MIDDLEUP = 0x0040;
        //標示是否採用絕對座標 
        const int MOUSEEVENT_ABSOLUTE = 0x8000;

        [System.Runtime.InteropServices.DllImport("user32")]
        public static extern void keybd_event(
            byte bVk, //虛擬鍵值
            byte bScan,// 一般爲0
            int dwFlags, //這裏是整數類型 0 爲按下,2爲釋放
            int dwExtraInfo //這裏是整數類型 一般情況下設成爲 0
            );
        const int KEY_DOWN = 0;
        const int KEY_UP = 2;

        public Form1()
        {
            InitializeComponent();
        }


        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //停止設備
            if (null != this.sensor)
            {
                this.sensor.AudioSource.Stop();

                this.sensor.Stop();
            }

            //退出語音識別
            if (null != this.speechEngine)
            {
                this.speechEngine.SpeechRecognized -= SpeechRecognized;
                this.speechEngine.SpeechRecognitionRejected -= SpeechRejected;
                this.speechEngine.RecognizeAsyncStop();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //枚舉Kinect設備,並將第一個連接成功的設備做爲當前設備
            foreach (var potentialSensor in KinectSensor.KinectSensors)
            {
                if (potentialSensor.Status == KinectStatus.Connected)
                {
                    this.sensor = potentialSensor;
                    break;
                }
            }

            if (null != this.sensor)
            {
                //初始化Kinect設置            
                colorImageFormat = ColorImageFormat.RgbResolution640x480Fps30;
                depthImageFormat = DepthImageFormat.Resolution640x480Fps30;

                this.sensor.ColorStream.Enable(colorImageFormat);
                this.sensor.DepthStream.Enable(depthImageFormat);
                this.sensor.SkeletonStream.Enable();

                this.colorPixels = new byte[this.sensor.ColorStream.FramePixelDataLength];
                this.depthPixels = new DepthImagePixel[this.sensor.DepthStream.FramePixelDataLength];
                this.depthPixels4Channels = new byte[this.sensor.DepthStream.FramePixelDataLength * 4];
                this.skeletonData = new Skeleton[this.sensor.SkeletonStream.FrameSkeletonArrayLength];

                this.colorCoordinates = new ColorImagePoint[this.sensor.DepthStream.FramePixelDataLength];

                depthWidth = this.sensor.DepthStream.FrameWidth;
                depthHeight = this.sensor.DepthStream.FrameHeight;

                colorWidth = this.sensor.ColorStream.FrameWidth;
                colorHeight = this.sensor.ColorStream.FrameHeight;

                skeletonImage = new Image(depthWidth, depthHeight);
                skeletonImage.Draw(new Rectangle(0, 0, depthWidth, depthHeight), new Bgr(0.0, 0.0, 0.0), -1);
                imageBox3.Image = skeletonImage;

                this.sensor.ColorFrameReady += this.SensorColorFrameReady;
                this.sensor.DepthFrameReady += this.SensorDepthFrameReady;
                this.sensor.SkeletonFrameReady += this.SensorSkeletonFrameReady;

                _gestureController = new GestureController(GestureType.All);
                _gestureController.GestureRecognized += GestureController_GestureRecognized;
                //啓動設備
                try
                {
                    this.sensor.Start();
                }
                catch (System.IO.IOException)
                {
                    this.sensor = null;
                }
            }

            if (null == this.sensor)
            {
                MessageBox.Show("Kinect設備未準備好");
            }
            else
            {
                this.Text = "Kinect連接成功";
            }

            //獲取Kinect語音識別引擎
            RecognizerInfo ri = GetKinectRecognizer();

            if (null != ri)
            {
                //創建引擎
                this.speechEngine = new SpeechRecognitionEngine(ri.Id);

                //創建識別語法
                var directions = new Choices();
                directions.Add(new SemanticResultValue("one", 1));
                directions.Add(new SemanticResultValue("two", 2));
                directions.Add(new SemanticResultValue("three", 3));
                directions.Add(new SemanticResultValue("four", 4));
                directions.Add(new SemanticResultValue("five", 5));

                var gb = new GrammarBuilder { Culture = ri.Culture };
                gb.Append(directions);
                var g = new Grammar(gb);
                speechEngine.LoadGrammar(g);

                //添加識別處理函數
                speechEngine.SpeechRecognized += SpeechRecognized;
                speechEngine.SpeechRecognitionRejected += SpeechRejected;

                //設置語音引擎參數
                speechEngine.SetInputToAudioStream(
                    sensor.AudioSource.Start(),
                    new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));

                //啓用識別
                speechEngine.RecognizeAsync(RecognizeMode.Multiple);
            }
        }

        void GestureController_GestureRecognized(object sender, GestureEventArgs e)
        {
            Text = e.Name;

            switch (e.Type)
            {
                case GestureType.JoinedHands:
                    break;
                case GestureType.Menu:
                    break;
                case GestureType.SwipeDown:
                    break;
                case GestureType.SwipeLeft:
                    {
                        mouse_event(MOUSEEVENT_MOVE, -10, 0, 0, 0);
                    }
                    break;
                case GestureType.SwipeRight:
                    {
                        mouse_event(MOUSEEVENT_MOVE, 10, 0, 0, 0);
                    }
                    break;
                case GestureType.SwipeUp:
                    break;
                case GestureType.WaveLeft:
                    {
                        keybd_event((byte)Keys.PageDown, 0, KEY_DOWN, 0);
                        keybd_event((byte)Keys.PageDown, 0, KEY_UP, 0);
                    }
                    break;
                case GestureType.WaveRight:
                    {
                        keybd_event((byte)Keys.PageUp, 0, KEY_DOWN, 0);
                        keybd_event((byte)Keys.PageUp, 0, KEY_UP, 0);
                    }
                    break;
                case GestureType.ZoomIn:
                    break;
                case GestureType.ZoomOut:
                    break;
                default:
                    break;
            }
        }
        //識別處理函數
        private void SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            const double ConfidenceThreshold = 0.3;

            if (e.Result.Confidence >= ConfidenceThreshold)
            {
                MessageBox.Show(e.Result.Semantics.Value.ToString());
            }
        }

        //識別拒絕函數,基本無意義
        private void SpeechRejected(object sender, SpeechRecognitionRejectedEventArgs e)
        {
        }

        //獲取Kinect語音識別引擎
        private static RecognizerInfo GetKinectRecognizer()
        {
            foreach (RecognizerInfo recognizer in SpeechRecognitionEngine.InstalledRecognizers())
            {
                string value;
                recognizer.AdditionalInfo.TryGetValue("Kinect", out value);
                if ("True".Equals(value, StringComparison.OrdinalIgnoreCase) &&
                    "en-US".Equals(recognizer.Culture.Name, StringComparison.OrdinalIgnoreCase))
                {
                    return recognizer;
                }
            }

            return null;
        }

        //骨骼數據處理事件
        private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            bool received = false;

            using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
            {
                if (skeletonFrame != null)
                {
                    skeletonFrame.CopySkeletonDataTo(this.skeletonData);
                    received = true;
                }
            }

            if (received)
            {
                foreach (Skeleton skeleton in this.skeletonData)
                {
                    if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
                    {
                        _gestureController.Update(skeleton);
                    }
                }
                //重繪整個畫面,沖掉原有骨骼圖像
                skeletonImage.Draw(new Rectangle(0, 0, skeletonImage.Width, skeletonImage.Height), new Bgr(0.0, 0.0, 0.0), -1);

                DrawSkeletons(skeletonImage, 0);
                imageBox3.Image = skeletonImage;
            }
        }

        private void DrawSkeletons(Image img, int depthOrColor)
        {
            //繪製所有正確Tracked的骨骼
            foreach (Skeleton skeleton in this.skeletonData)
            {
                if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
                {
                    DrawTrackedSkeletonJoints(img, skeleton.Joints, depthOrColor);
                }
            }
        }

        private void DrawTrackedSkeletonJoints(Image img, JointCollection jointCollection, int depthOrColor)
        {
            // Render Head and Shoulders
            DrawBone(img, jointCollection[JointType.Head], jointCollection[JointType.ShoulderCenter], depthOrColor);
            DrawBone(img, jointCollection[JointType.ShoulderCenter], jointCollection[JointType.ShoulderLeft], depthOrColor);
            DrawBone(img, jointCollection[JointType.ShoulderCenter], jointCollection[JointType.ShoulderRight], depthOrColor);

            // Render Left Arm
            DrawBone(img, jointCollection[JointType.ShoulderLeft], jointCollection[JointType.ElbowLeft], depthOrColor);
            DrawBone(img, jointCollection[JointType.ElbowLeft], jointCollection[JointType.WristLeft], depthOrColor);
            DrawBone(img, jointCollection[JointType.WristLeft], jointCollection[JointType.HandLeft], depthOrColor);

            // Render Right Arm
            DrawBone(img, jointCollection[JointType.ShoulderRight], jointCollection[JointType.ElbowRight], depthOrColor);
            DrawBone(img, jointCollection[JointType.ElbowRight], jointCollection[JointType.WristRight], depthOrColor);
            DrawBone(img, jointCollection[JointType.WristRight], jointCollection[JointType.HandRight], depthOrColor);

            // Render other bones...
            DrawBone(img, jointCollection[JointType.ShoulderCenter], jointCollection[JointType.Spine], depthOrColor);

            DrawBone(img, jointCollection[JointType.Spine], jointCollection[JointType.HipRight], depthOrColor);
            DrawBone(img, jointCollection[JointType.KneeRight], jointCollection[JointType.HipRight], depthOrColor);
            DrawBone(img, jointCollection[JointType.KneeRight], jointCollection[JointType.AnkleRight], depthOrColor);
            DrawBone(img, jointCollection[JointType.FootRight], jointCollection[JointType.AnkleRight], depthOrColor);

            DrawBone(img, jointCollection[JointType.Spine], jointCollection[JointType.HipLeft], depthOrColor);
            DrawBone(img, jointCollection[JointType.KneeLeft], jointCollection[JointType.HipLeft], depthOrColor);
            DrawBone(img, jointCollection[JointType.KneeLeft], jointCollection[JointType.AnkleLeft], depthOrColor);
            DrawBone(img, jointCollection[JointType.FootLeft], jointCollection[JointType.AnkleLeft], depthOrColor);
        }

        private void DrawBone(Image img, Joint jointFrom, Joint jointTo, int depthOrColor)
        {
            if (jointFrom.TrackingState == JointTrackingState.NotTracked ||
            jointTo.TrackingState == JointTrackingState.NotTracked)
            {
                return; // nothing to draw, one of the joints is not tracked
            }

            if (jointFrom.TrackingState == JointTrackingState.Inferred ||
            jointTo.TrackingState == JointTrackingState.Inferred)
            {
                DrawBoneLine(img, jointFrom.Position, jointTo.Position, 1, depthOrColor);
            }

            if (jointFrom.TrackingState == JointTrackingState.Tracked &&
            jointTo.TrackingState == JointTrackingState.Tracked)
            {
                DrawBoneLine(img, jointFrom.Position, jointTo.Position, 3, depthOrColor);
            }
        }

        private Point SkeletonPointToDepthScreen(SkeletonPoint skelpoint)
        {
            DepthImagePoint depthPoint = this.sensor.CoordinateMapper.MapSkeletonPointToDepthPoint(skelpoint, depthImageFormat);
            return new Point(depthPoint.X, depthPoint.Y);
        }

        private Point SkeletonPointToColorScreen(SkeletonPoint skelpoint)
        {
            ColorImagePoint colorPoint = this.sensor.CoordinateMapper.MapSkeletonPointToColorPoint(skelpoint, colorImageFormat);
            return new Point(colorPoint.X, colorPoint.Y);
        }

        private void DrawBoneLine(Image img, SkeletonPoint p1, SkeletonPoint p2, int lineWidth, int depthOrColor)
        {
            Point p_1, p_2;

            if (depthOrColor == 0)
            {
                p_1 = SkeletonPointToDepthScreen(p1);
                p_2 = SkeletonPointToDepthScreen(p2);
            }
            else
            {
                p_1 = SkeletonPointToColorScreen(p1);
                p_2 = SkeletonPointToColorScreen(p2);
            }

            img.Draw(new LineSegment2D(p_1, p_2), new Bgr(255, 255, 0), lineWidth);
            img.Draw(new CircleF(p_1, 5), new Bgr(0, 0, 255), -1);

            StringBuilder str = new StringBuilder();
            str.AppendFormat("({0},{1},{2})", p1.X.ToString("0.0"), p1.Y.ToString("0.0"), p1.Z.ToString("0.0"));

            img.Draw(str.ToString(), ref font, p_1, new Bgr(0, 255, 0));
            img.Draw(new CircleF(p_2, 5), new Bgr(0, 0, 255), -1);

            str.Clear();
            str.AppendFormat("({0},{1},{2})", p2.X.ToString("0.0"), p2.Y.ToString("0.0"), p2.Z.ToString("0.0"));
            img.Draw(str.ToString(), ref font, p_2, new Bgr(0, 255, 0));
        }

        private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            bool received = false;
            using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
            {
                if (colorFrame != null)
                {
                    //緩存數據
                    colorFrame.CopyPixelDataTo(this.colorPixels);
                    received = true;
                }
            }

            if (received)
            {
                //將byte數組轉爲Bitmap
                colBitmap = new Bitmap(colorWidth, colorHeight);

                BitmapData colImageBitmapData = colBitmap.LockBits(new Rectangle(0, 0, colBitmap.Width, colBitmap.Height),
                                                ImageLockMode.WriteOnly,
                                                colBitmap.PixelFormat);
                IntPtr IptrColImage = colImageBitmapData.Scan0;

                Marshal.Copy(colorPixels, 0, IptrColImage, colorPixels.Length);
                colBitmap.UnlockBits(colImageBitmapData);

                //顯示Bitmap
                UpdateColImage(colBitmap);
            }
        }

        private void SensorDepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
        {
            bool received = false;
            int minDepth = 1000;
            int maxDepth = 0;

            using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
            {
                if (depthFrame != null)
                {
                    //獲取有效深度範圍
                    minDepth = depthFrame.MinDepth;
                    maxDepth = depthFrame.MaxDepth;

                    //緩存深度數據
                    depthFrame.CopyDepthImagePixelDataTo(this.depthPixels);

                    received = true;
                }
            }

            if (received)
            {
                this.sensor.CoordinateMapper.MapDepthFrameToColorFrame(
                    depthImageFormat,
                    this.depthPixels,
                    colorImageFormat,
                    this.colorCoordinates);

                //將深度數據轉爲Bitmap
                depBitmap = new Bitmap(depthWidth, depthHeight);

                BitmapData depImageBitmapData = depBitmap.LockBits(new Rectangle(0, 0, depBitmap.Width, depBitmap.Height),
                                                ImageLockMode.WriteOnly,
                                                depBitmap.PixelFormat);
                IntPtr IptrDepImage = depImageBitmapData.Scan0;


                for (int y = 0; y < this.depthHeight; ++y)
                {
                    for (int x = 0; x < this.depthWidth; ++x)
                    {
                        int i = x + (y * this.depthWidth);

                        int player = depthPixels[i].PlayerIndex;

                        short depth = depthPixels[i].Depth;
                        byte intensity = (byte)((1.0f * (depth - minDepth) / (maxDepth - minDepth)) * 255f);
                        if (depth < minDepth) intensity = 0;
                        if (depth > maxDepth) intensity = 255;

                        if (player > 0)
                        {
                            int j = x + (y * this.colorWidth);

                            if (cbBody.Checked)
                            {
                                this.depthPixels4Channels[i * 4 + 0] = this.colorPixels[j * 4 + 0];
                                this.depthPixels4Channels[i * 4 + 1] = this.colorPixels[j * 4 + 1];
                                this.depthPixels4Channels[i * 4 + 2] = this.colorPixels[j * 4 + 2];
                            }
                            else
                            {
                                this.depthPixels4Channels[i * 4 + 0] = intensity;
                                this.depthPixels4Channels[i * 4 + 1] = 255;
                                this.depthPixels4Channels[i * 4 + 2] = intensity;
                            }
                        }
                        else
                        {
                            if (depth > minDepth && depth < minDepth + 1000)
                            {
                                this.depthPixels4Channels[i * 4 + 0] = 255;
                                this.depthPixels4Channels[i * 4 + 1] = intensity;
                                this.depthPixels4Channels[i * 4 + 2] = intensity;
                            }
                            else
                            {
                                this.depthPixels4Channels[i * 4 + 0] = intensity;
                                this.depthPixels4Channels[i * 4 + 1] = intensity;
                                this.depthPixels4Channels[i * 4 + 2] = intensity;
                            }
                        }
                        this.depthPixels4Channels[i * 4 + 3] = 255;
                    }
                }

                Marshal.Copy(depthPixels4Channels, 0, IptrDepImage, depthPixels4Channels.Length);
                depBitmap.UnlockBits(depImageBitmapData);

                //顯示深度
                UpdateDepImage(depBitmap);
            }
        }

        private void UpdateColImage(Bitmap bmp)
        {
            try
            {
                colorImage = new Image(bmp);

                if (skeletonData != null)
                {
                    DrawSkeletons(colorImage, 1);
                }

                imageBox1.Image = colorImage;
            }
            catch { }
        }

        private void UpdateDepImage(Bitmap bmp)
        {
            try
            {
                depthImage = new Image(bmp);

                if (this.skeletonData != null)
                    DrawSkeletons(depthImage, 0);

                imageBox2.Image = depthImage;
            }
            catch { }
        }

        private void cbNearMode_CheckedChanged(object sender, EventArgs e)
        {
            //近模式和默認模式切換
            if (this.sensor != null)
            {
                try
                {
                    if (this.cbNearMode.Checked)
                    {
                        this.sensor.DepthStream.Range = DepthRange.Near;
                    }
                    else
                    {
                        this.sensor.DepthStream.Range = DepthRange.Default;
                    }
                }
                catch (InvalidOperationException)
                {
                }
            }
        }

        private void cbSeat_CheckedChanged(object sender, EventArgs e)
        {
            //坐姿和默認模式切換
            if (this.sensor != null)
            {
                try
                {
                    if (this.cbSeat.Checked)
                    {
                        this.sensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
                    }
                    else
                    {
                        this.sensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Default;
                    }
                }
                catch (InvalidOperationException)
                {
                }
            }
        }
       
    }
}

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章