본문 바로가기

Programming/OpenCV

[OpenCVSharp] XNA와 OpenCVSharp 연동하기

XNA의 Texture2D를 통해 OpenCV 에서 받아오는 웹캠 이미지를 출력. (iplImage를 Texture2D로 변환)

using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using OpenCvSharp;


using ProjectMercury;
using ProjectMercury.Emitters;
using ProjectMercury.Modifiers;
using ProjectMercury.Renderers;

namespace yugioh_xna
{

    /// 
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// 
    class GameplayScreen : GameScreen 
    {
        //  using Microsoft.Xna.Framework.Game;
        #region Fields
        ContentManager content;
        SpriteFont gameFont;

        float pauseAlpha;

        #endregion

        #region 선언(Fields)
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        //한글 폰트용 변수
        SpriteFont hanFont;

        Texture2D backgroundTexture;

        public System.Timers.Timer TimerGameTurn = new System.Timers.Timer();
        Texture2D[] TimeTexture = new Texture2D[31];


        Texture2D webCamTexture;
        IplImage cam;// = new IplImage(640, 480, BitDepth.U8, 3);
        IplImage res;// = new IplImage(640, 480, BitDepth.U8, 3);
        CvCapture cap;

        #endregion

        //머큐리 파티클 엔진 변수
        Renderer defaultRenderer;
        ParticleEffect defaultEffect1;
        ParticleEffect defaultEffect2;

        //파티클 position
        float[,] defaultPos = new float[8, 2] {{480.0f, 200.0f}, 
                                               {480.0f, 350.0f}, 
                                               {480.0f, 720.0f}, 
                                               {480.0f, 880.0f}, 
                                               {810.0f, 200.0f}, 
                                               {810.0f, 350.0f}, 
                                               {810.0f, 720.0f},
                                               {810.0f, 880.0f}};



        #region Initialization

        /// 
        /// Constructor.
        /// 
        ///        
        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);

            Content.RootDirectory = "Content";
            graphics = new GraphicsDeviceManager(this);
            graphics.ApplyChanges();
            

            TransitionOffTime = TimeSpan.FromSeconds(0);

            #region 머큐리 엔진
          
            defaultRenderer = new SpriteBatchRenderer
            {
                GraphicsDeviceService = graphics
            };


            defaultEffect1 = new ParticleEffect();
            defaultEffect2 = new ParticleEffect();
  #endregion
 

        }

        /// 
        /// Load graphics content for the game.
        /// 

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

("Hangul_SpriteFont"); gameFont = content.Load("menufont"); backgroundTexture = content.Load("Imeage//배경_1280_1024"); #region 머큐리 엔진 //파티클 Load defaultEffect1 = content.Load("EffectLibrary\\Default1"); defaultEffect1.LoadContent(this.content); defaultEffect1.Initialise(); defaultEffect2 = content.Load("EffectLibrary\\Default2"); defaultEffect2.LoadContent(this.content); defaultEffect2.Initialise(); defaultRenderer.LoadContent(content); cam = new IplImage(640, 480, BitDepth.U8, 3); res = new IplImage(640, 480, BitDepth.U8, 3); cap = CvCapture.FromCamera(CaptureDevice.DShow, 0); cap.SetCaptureProperty(CaptureProperty.FrameWidth, 640); cap.SetCaptureProperty(CaptureProperty.FrameHeight, 480); //웹켐 받아 오기 webCamTexture = new Texture2D(ScreenManager.GraphicsDevice, cap.FrameWidth, cap.FrameHeight, false, SurfaceFormat.Color); //일단로드 우리가, 우리가, 아주 긴 프레임을 완료하고 지금은 잡으려고해서는 //안되는 게임의 타이밍 메커니즘을 말할 ResetElapsedTime 사용가 완료되었습니다. ScreenManager.Game.ResetElapsedTime(); #endregion } /// /// Unload graphics content used by the game. /// public override void UnloadContent() { content.Unload(); } #endregion #region Update and Draw /// /// 업데이트 게임의 상태. 이 방법은 GameScreen.IsActive 속성을 확인합니다, /// 그래서 게임이 일시 중지 메뉴가 활성화되어 있으면 또는 당신에게 /// 탭을 떨어져 다른 응용하는 경우 업데이 트가 중단됩니다. /// public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen) { //base.Update(gameTime, otherScreenHasFocus, false); //점차적으로 또는 우리는 정지 화면의 적용 여부에 따라 페이드 아웃. if (coveredByOtherScreen) pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1); else pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0); if (IsActive) { // TODO: this game isn't very fun! You could probably improve // it by inserting something more interesting in this space :-) #region 머큐리 엔진 defaultEffect1.Trigger(new Vector2(0, 0)); defaultEffect2.Trigger(new Vector2(100, 100)); float SecondsPassed = (float)gameTime.ElapsedGameTime.TotalSeconds; defaultEffect1.Update(SecondsPassed); defaultEffect2.Update(SecondsPassed); #endregion } base.Update(gameTime, otherScreenHasFocus, false); } /// /// 있습니다이 게임은 플레이어의 입력을 처리합니다. /// 업데이트 방법과는 달리, 이것은 게임 플레이 화면이 활성화되었을 때 호출됩니다. /// public override void HandleInput(InputState input) { if (input == null) throw new ArgumentNullException("input"); // Look up inputs for the active player profile. int playerIndex = (int)ControllingPlayer.Value; KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex]; if (input.IsPauseGame(ControllingPlayer)) { TimerGameTurn.Stop(); ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer); } else { TimerGameTurn.Start(); // Otherwise move the player position. Vector2 movement = Vector2.Zero; if (keyboardState.IsKeyDown(Keys.Left)) movement.X--; if (keyboardState.IsKeyDown(Keys.Right)) movement.X++; if (keyboardState.IsKeyDown(Keys.Up)) movement.Y--; if (keyboardState.IsKeyDown(Keys.Down)) movement.Y++; if (movement.Length() > 1) movement.Normalize(); } } /// /// Draws the gameplay screen. /// public override void Draw(GameTime gameTime) { #region 머큐리 엔진 ScreenManager.GraphicsDevice.Clear(ClearOptions.Target, Color.CornflowerBlue, 0, 0); defaultRenderer.RenderEffect(defaultEffect1); defaultRenderer.RenderEffect(defaultEffect2); SaveStateMode mode = new SaveStateMode(ScreenManager.GraphicsDevice); mode.Restore(); cam = cap.QueryFrame(); int Size = cam.ImageSize / 3; byte[] bgrData = new byte[cam.ImageSize]; Color[] colorData = new Color[Size]; System.Runtime.InteropServices.Marshal.Copy(cam.ImageData, bgrData, 0, res.ImageSize); for (int i = 0; i < colorData.Length; i++) { colorData[i] = new Color( bgrData[i * 3 + 2], bgrData[i * 3 + 1], bgrData[i * 3]); } graphics.GraphicsDevice.Textures[0] = null; webCamTexture.SetData(colorData); graphics.GraphicsDevice.SetRenderTarget(null); //// GraphicsDevice.Clear(Color.White); spriteBatch.Begin(); spriteBatch.Draw(webCamTexture, new Rectangle(0, 0, 1280, 1024), Color.White); spriteBatch.End(); #endregion //화면 전환시} if (TransitionPosition > 0 || pauseAlpha > 0) { float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2); ScreenManager.FadeBackBufferToBlack(alpha); } } #endregion struct SaveStateMode { BlendState m_Blenstate; DepthStencilState m_DepthState; RasterizerState m_RasterState; SamplerState m_SamplerState; GraphicsDevice m_Device; public SaveStateMode(GraphicsDevice device) { m_Device = device; m_Blenstate = BlendState.Opaque; m_DepthState = DepthStencilState.Default; m_RasterState = m_Device.RasterizerState; m_SamplerState = m_Device.SamplerStates[0]; } public void Restore() { m_Device.BlendState = m_Blenstate; m_Device.DepthStencilState = m_DepthState; m_Device.RasterizerState = m_RasterState; m_Device.SamplerStates[0] = m_SamplerState; } } } }