본문 바로가기

Dev/Kinect

kinect

using System;
using System.Linq;
using Microsoft.Kinect;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace MFTGuide.Screens
{
    class MainMenuScreen : GameScreen
    {
        Texture2D t_logo;
        Vector2 v_logo;


        Vector2Converter mVector = new Vector2Converter();

        ContentManager content;
        /// <summary>
        /// 손을 후두부로
        /// </summary>
        Texture2DButton bt_0;

        Vector2 v_bt_0 = new Vector2(393.5f, 326.0f);

        /// <summary>
        /// 상지 측방 거상
        /// </summary>
        Texture2DButton bt_1;

        Vector2 v_bt_1 = new Vector2(394.0f, 400.0f);
        /// <summary>
        /// 손을 후두부로
        /// </summary>
        Texture2DButton bt_2;

        Vector2 v_bt_2 = new Vector2(400.0f, 473.0f);

        /// <summary>
        /// 잡기
        /// </summary>
        Texture2DButton bt_3;

        Vector2 v_bt_3 = new Vector2(308.0f, 547.0f);

        // -------------------
        KinectSensor kinectSensor;

        Vector2 handPosition = new Vector2();
        string connectedStatus = "Not connected";

        Texture2D hand;

        public MainMenuScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);

            // 센서에 내용이 변경될 때 호출되는 이벤트를 추가한다.
            KinectSensor.KinectSensors.StatusChanged += new EventHandler<StatusChangedEventArgs>(KinectSensors_StatusChanged);
            DiscoverKinectSensor();
        }


        // ---------------------------------------------------------------

        /// <summary>
        /// 키넥트 센서 상태가 변경될 때 호출한다.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            if (this.kinectSensor == e.Sensor)
            {
                // 키넥트가 연결되어 있지 않거나, 파워가 들어와 있지 않을경우
                if (e.Status == KinectStatus.Disconnected ||
                    e.Status == KinectStatus.NotPowered)
                {
                    this.kinectSensor = null;
                    this.DiscoverKinectSensor();
                }
            }
        }

        /// <summary>
        /// 키넥트 센서를 찾다.
        /// </summary>
        private void DiscoverKinectSensor()
        {
            // 키넥트 센서 연결확인
            foreach (KinectSensor sensor in KinectSensor.KinectSensors)
            {
                // 키넥트 센서가 연결되어있으면
                if (sensor.Status == KinectStatus.Connected)
                {
                    // Found one, set our sensor to this
                    // 키넥트 센서가 연결되어있으면, 키넥트 센서 변수는 센서를 참조한다.
                    kinectSensor = sensor;
                    break;
                }
            }

            // foreach 문에서 키넥트를 센서를 찾지만 없을 경우
            if (this.kinectSensor == null)
            {
                connectedStatus = "Found none Kinect Sensors connected to USB";
                return;
            }

            // 키넥트 센서에 상태를 "kinectSensor.Status"를 사용해서 확인한다.
            switch (kinectSensor.Status)
            {
                case KinectStatus.Connected:
                    {
                        // 키넥트 센서가 연결되어 있음
                        connectedStatus = "Status: Connected";
                        break;
                    }
                case KinectStatus.Disconnected:
                    {
                        // 키넥트 센서가 연결 끊김
                        connectedStatus = "Status: Disconnected";
                        break;
                    }
                case KinectStatus.NotPowered:
                    {
                        // 키넥트 센서가 전원이 안들어와 있음
                        connectedStatus = "Status: Connect the power";
                        break;
                    }
                default:
                    {
                        // 키넥트 센서가 알수 없는 애러가 발생함.
                        connectedStatus = "Status: Error";
                        break;
                    }
            }

            // 정상적으로 연결되어 있다면, 키넥트를 설정 및 초기화한다.
            if (kinectSensor.Status == KinectStatus.Connected)
            {
                InitializeKinect();
            }
        }


        /// <summary>
        /// 키넥트 초기 설정
        /// </summary>
        /// <returns></returns>
        private bool InitializeKinect()
        {
            #region 키넥트 컬러 스트림 초기 설정
            // 키넥트 센서 컬러 처리 : 컬러 포맷을 ColorImageFormat 로 사용 한다.
            // 윈도우 키넥트에서는 640x480 / 1280x 960 해상도와 FPS을 지원한다.
            kinectSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);

            // 키넥트 센서 프레임 레디는 키넥트가 준비가 완료될 시, 호출되는 함수를 등록한다.
            kinectSensor.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(kinectSensor_ColorFrameReady);
            #endregion

            #region 키넥트 뼈대 스트림 초기 설정

            // 키넥트 센서 뼈대 스트림을 활성화한다.
            // 키넥트가 사람의 위치를 따라가다(Track)하다 잘못됭 경우(이러한 경우를 SDK내에서 jitter이라고 한다.)를 막기 위해
            // TransformSmoothParameters를 추가한다.
            // TransformSmoothParameters 은 좀더 부드럽게 관절을 연결하기 위해 셋팅하는 방법.
            kinectSensor.SkeletonStream.Enable(new TransformSmoothParameters()
            {
                // 다듬는다.
                Smoothing = 0.5f,
                // 교정한다.
                Correction = 0.5f,
                // 예측한다.
                Prediction = 0.5f,
                // 이상(Jitter) 반경
                JitterRadius = 0.05f,
                // 최대 탈선 반경
                MaxDeviationRadius = 0.04f
            });
            // 키넥트 센서 프레임 레디는 키넥트가 준비가 완료될 시, 호출되는 함수를 등록한다.
            kinectSensor.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(kinectSensor_SkeletonFrameReady);

            #endregion

            #region 키넥트 시작
            try
            {
                // 키넥트 시작
                kinectSensor.Start();
            }
            catch
            {
                connectedStatus = "Unable to start the Kinect Sensor";
                return false;
            }
            #endregion
            return true;
        }

        void kinectSensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            // skeletonFrame 는 e.OpenSkeletonFrame() 를 사용한다.
            using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
            {
                //skeletonFrame 이 정상이라면
                if (skeletonFrame != null)
                {
                    //int skeletonSlot = 0;

                    //skeletonData 는 스켈래톤 배열이며, 스캘래톤 프레임 길이 만큼의 배열로해서 생성한다.
                    Skeleton[] skeletonData = new Skeleton[skeletonFrame.SkeletonArrayLength];

                    // 그리고 스캘래톤데이터는 스켈레톤 프레임에 데이터를 카피한다.
                    skeletonFrame.CopySkeletonDataTo(skeletonData);

                    // 이부분은 잘모르겠다..

                    // LINQ
                    // 플레이어 스켈레톤은 (특정 데이터만 조회한다..) 시퀀스의 첫 번째 요소를 반환하거나 요소가 없는 경우 기본값 반환
                    Skeleton playerSkeleton = (from s in skeletonData where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault();
                    if (playerSkeleton != null)
                    {
                        // TODO: 포인트 가져온다.

                        // 관절 오른손은 플레이어 스켈레톤에 오른손이다.
                        Joint rightHand = playerSkeleton.Joints[JointType.HandRight];
                        //
                        handPosition = new Vector2((((0.5f * rightHand.Position.X) + 0.5f) * (Config.DISPLAY_WIDTH)), (((-0.5f * rightHand.Position.Y) + 0.5f) * (Config.DISPLAY_HEIGHT)));
                    }
                }
            }
        }

        void kinectSensor_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            using (ColorImageFrame colorImageFrame = e.OpenColorImageFrame())
            {
                if (colorImageFrame != null)
                {

                    byte[] pixelsFromFrame = new byte[colorImageFrame.PixelDataLength];

                    colorImageFrame.CopyPixelDataTo(pixelsFromFrame);

                    Color[] color = new Color[colorImageFrame.Height * colorImageFrame.Width];

                    // Go through each pixel and set the bytes correctly
                    // Remember, each pixel got a Rad, Green and Blue
                    int index = 0;
                    for (int y = 0; y < colorImageFrame.Height; y++)
                    {
                        for (int x = 0; x < colorImageFrame.Width; x++, index += 4)
                        {
                            color[y * colorImageFrame.Width + x] = new Color(pixelsFromFrame[index + 2], pixelsFromFrame[index + 1], pixelsFromFrame[index + 0]);
                        }
                    }

                }
            }
        }

        // ---------------------------------------------------------------


        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            t_logo = content.Load<Texture2D>("Textures/MainMenu/logo_mft");
            v_logo = new Vector2(400.0f, 159.0f);

            bt_0 = new Texture2DButton(
                content.Load<Texture2D>("Textures/MainMenu/bt_0_normal"),
                content.Load<Texture2D>("Textures/MainMenu/bt_0_select"),
                v_bt_0);

            bt_1 = new Texture2DButton(
                content.Load<Texture2D>("Textures/MainMenu/bt_1_normal"),
                content.Load<Texture2D>("Textures/MainMenu/bt_1_select"),
                v_bt_1);

            bt_2 = new Texture2DButton(
                content.Load<Texture2D>("Textures/MainMenu/bt_2_normal"),
                content.Load<Texture2D>("Textures/MainMenu/bt_2_select"),
                v_bt_2);

            bt_3 = new Texture2DButton(
                content.Load<Texture2D>("Textures/MainMenu/bt_3_normal"),
                content.Load<Texture2D>("Textures/MainMenu/bt_3_select"),
                v_bt_3);

            // --------------

            hand = content.Load<Texture2D>("Textures/hand");
        }

        public override void UnloadContent()
        {
            kinectSensor.Stop();
            kinectSensor.Dispose();
            content.Unload();
        }

        #region Update and Draw

        public override void HandleInput(InputState input)
        {
            base.HandleInput(input);

            //MouseState mounState = Mouse.GetState();

            //if (bt_0.IsClick(mounState))
            //{
            //    //LoadingScreen.Load(ScreenManager, true, ControllingPlayer, new MainMenuScreen());
            //}

            //if (bt_1.IsClick(mounState))
            //{
            //    //LoadingScreen.Load(ScreenManager, true, ControllingPlayer, new MainMenuScreen());
            //}

            //if (bt_2.IsClick(mounState))
            //{
            //    //LoadingScreen.Load(ScreenManager, true, ControllingPlayer, new MainMenuScreen());
            //}
           
            //if (bt_3.IsClick(mounState))
            //{
            //    LoadingScreen.Load(ScreenManager, true, ControllingPlayer, new BackgroundScreen(), new ScoreScreen(1, 1));
            //}

            if (bt_0.IsOveray(handPosition))
            {
            }
            if (bt_1.IsOveray(handPosition))
            {
            }
            if (bt_2.IsOveray(handPosition))
            {
            }
            if (bt_3.IsOveray(handPosition))
            {
            }
        }


        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
        }


        public override void Draw(GameTime gameTime)
        {
            // Our player and enemy are both actually just text strings.
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

 

            spriteBatch.Begin();
            spriteBatch.Draw(t_logo, v_logo, null, Color.White, 0.0f, mVector.GetVector2(t_logo, 0.5f, 0.5f), 1.0f, SpriteEffects.None, 1.0f);
            spriteBatch.End();

            bt_0.Draw(spriteBatch);

            bt_1.Draw(spriteBatch);

            bt_2.Draw(spriteBatch);

            bt_3.Draw(spriteBatch);

            spriteBatch.Begin();
            spriteBatch.Draw(hand, handPosition, null, Color.White, 0.0f, mVector.GetVector2(hand, 0.5f, 0.5f), 1.0f, SpriteEffects.None, 1.0f);
            spriteBatch.End();
        }
        #endregion
    }
}

'Dev > Kinect' 카테고리의 다른 글

Kinect 관련 유용한 자료 스크랩  (0) 2012.04.27