Update 08/06/2012 –

A nova versão do Kinect SDK foi lançada a pouco tempo e deixou todo esse conteúdo desatualizado. O novo conteúdo pode ser encontrado aqui: https://100loop.com/destaque/kinect-sdk-1-5-parte-1-camera-rgb/

 

 

Fala filhotes! De volta com SDK do Kinect o objetivo agora é mostrar como usar a câmera RGB (câmera colorida). Dessa vez será um pouco diferente do ultimo post pois usaremos um “atalho”, ou seja, uma biblioteca de terceiros que nos ajudará com algumas coisas. Se você não viu o primeiro post sobre o Kinect SDK clique aqui.

Coding4Fun Toolkit

O Kinect SDK já esta ai por um tempo por isso não é de se espantar que muita gente já tenha criado um punhado de bibliotecas com o intuito de ajudar na programação. Uma dessas é a toolkit do Coding4Fun, que contêm vários métodos de extensão que substituem varias conversões loucas que normalmente teríamos de fazer. Você pode ver mais sobre essa biblioteca e baixar o código fonte aqui: http://c4fkinect.codeplex.com/.

Objetivo e Fluxo

O nosso objetivo é simplesmente transmitir o vídeo da câmera do Kinect, como se fosse uma webcam normal. Primeiro vamos aprender os fundamentos da câmera e só depois codificar.
Para codificar seguiremos o mesmo fluxo de antes:

fluxo

NUI

Há um novo conceito de interface que esta sendo muito vinculado ao Kinect, é o NUI ou Interface Natural do Usuário . A idéia é como o nome diz: Uma interface aonde o usuário não tem dificuldade de interagir e entendê-la, ou seja algo que o usuário ache natural.
Podemos nos referir ao runtime do Kinect como NUI afinal ele consegue interpretar os gestos e movimentos dos usuários como comandos.

nui
Para saber mais sobre NUI clique aqui ou aqui.

A câmera RGB

As classes que nós vamos usar para acessar a câmera RGB são essas:

image

Sempre que a câmera do Kinect esta ativa ele dispara um ImageFrameReadyEventArgs no VideoFrameReady, passando um ImageFrame que contem uma PlanarImage que ai sim contêm os bits da nossa imagem. E tendo esses bits podemos finalmente transforma-la em uma Imagem.

Nosso Projeto

Como no projeto anterior nós iremos criar um WPF. Agora basta adicionar uma referência das bibliotecas ao projeto.

image

Referência da API do Kinect e da biblioteca do C4F.

O XAML

Para o nosso exemplo precisaremos apenas de um componente de Imagem, então no Main adicione:

<Grid>
    <Image Height="400" HorizontalAlignment="Left" Margin="37,49,0,0" Name="videoContainer" Stretch="Fill" VerticalAlignment="Top" Width="500" />
</Grid>

O Código

Antes de tudo usamos o toolkit do C4F e a API do Kinect:

using Microsoft.Research.Kinect.Nui;
using Coding4Fun.Kinect.Wpf;

Depois criamos a NUI:

//Kinect Runtime
Runtime nui = new Runtime();

Depois seguimos o aquele nosso fluxo:

 

    private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //Inicializa a camera
            nui.Initialize(RuntimeOptions.UseColor);

            // Sempre que o video tiver preparado chama nossa função
            nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_VideoFrameReady);

            // Devemos abrir o video stream antes do evento ser chamado.
            // Passamos o tipo do Stream, a quantidade dos buffers, a resolução e o tipo de imagem de retorno
            nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
        }

O PoolSize é muito importante, ele representa a quantidade de buffers que ficará na fila, ou seja, enquanto um esta sendo mostrado os outros estão sendo carregados. A Microsoft aconselha a usar 2 buffers sendo que o máximo é 4. Lembrando que:

Quanto mais buffers, mais suave o vídeo fica, porem com uma latência maior.

E agora falta só a nossa função nui_VideoFrameReady né? Bom tem dois modos de fazer ela, o modo simples (usando a biblioteca do coding4fun)

        /// <summary>
        /// Função que irá converter os bits que o kinect envia em imagem
        /// </summary>
        void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
        {
            // Usando o método de extensão do Coding4Fun
            videoContainer.Source = e.ImageFrame.ToBitmapSource();

   }

Ou o modo viking (sem nenhuma biblioteca):

void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
        {
            // Modo "viking" para pegar a imagem do kinect
            // Nossa PlanarImage pegara os "dados brutos" (viking?) da imagem.
            PlanarImage imageData = e.ImageFrame.Image;
            // Agora sim, transformamos esses bits em uma imagem usando o BitmapSource.Create
            // Passando altura/largura, quantidade de pontos por polegada, formato do pixel (Azul, verde e vermelho), passamos os bits da nossa imagem e o stride.
            videoContainer.Source = BitmapSource.Create(imageData.Width, imageData.Height, 96, 96, PixelFormats.Bgr32, null, imageData.Bits, imageData.Width * imageData.BytesPerPixel);
        }

vik1custom

Esse meio é bom para vermos o que o método da Coding4Fun está fazendo.

E com relação ao ultimo parâmetro do BitmapSource.Create, o Stride:

Stride é o numero de bytes entre uma linha de pixels na memória de outra.

Para mais informações sobre o stride veja aqui: http://msdn.microsoft.com/en-us/library/aa473780(VS.85).aspx

Agora só falta fechar a NUI no Window_Closed:

    /// <summary>
        /// Fecha runtime do Kinect
        /// </summary>
        private void Window_Closed(object sender, EventArgs e)
        {
            nui.Uninitialize();
        }

Resultado

O resultado deve ser algo assim:

Uma simples tela mostrando a tela do Kinect. Se você quiser fazer o download do projeto entre aqui: http://www.megaupload.com/?d=Z1NM29BN

Espero que tenham gostado. Pretendo fazer mais posts sobre o assunto. Até mais!

 

Obs: Não, não deu para pentear o cabelo e nem fazer a barba.

Referência

http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/docs/ProgrammingGuide_KinectSDK.pdf

http://channel9.msdn.com/Series/KinectSDKQuickstarts/Camera-Fundamentals