Neste caso optei por levantar o eixo do sensor 10 graus, mas isso pode ficar a
seu critério. Você pode notar que a inicialização dos fluxos do Kinect pode ser feita de maneira bastante intuitiva e simples. Essa forma é a mesma para os três tipos de fluxo citados anteriormente.
Agora iremos criar o método que irá receber um quadro de cores do sen-
sor RGB e irá obter a imagem deste quadro. Você notará que apesar de parecer
complicado, também é uma tarefa bastante simples. Este método irá se chamar
ObterImagemSensorRGB, ele deve retornar um ImageSource que será inserido
como fonte de dados para o componente de imagem e receberá por parâmetro um
objeto do tipo ColorImageFrame, que representa um quadro do sensor RGB.
Um objeto do tipo ColorImageFrame é um objeto que pode ser classificado
como recurso, ele implementa a interface IDisposable, ou seja, você deve utilizar o método Dispose() para destruir o objeto ou simplesmente utilizar o comando
using. Para tornar o código mais legível, utilizaremos no exemplo a segunda op-
ção. Dentro do escopo do bloco using teremos que criar um array de bytes e o
converteremos para a fonte do componente de imagem.
private BitmapSource ObterImagemSensorRGB(ColorImageFrame quadro)
{
using (quadro)
{
byte[] bytesImagem = new byte[quadro.PixelDataLength];
quadro.CopyPixelDataTo(bytesImagem);
return BitmapSource.Create(quadro.Width, quadro.Height,
96, 96, PixelFormats.Bgr32, null, bytesImagem,
quadro.Width * quadro.BytesPerPixel);
}
}
Como você pode ver no método anterior, praticamente toda a informação refe-
rente à imagem é retirada do objeto quadro. O método estático Create da classe
BitmapSource recebe uma série de parâmetros, agora iremos entender o signifi-
cado de cada um deles.
33
4.2. Aplicação
Casa do Código
Os dois primeiros são respectivamente a largura e a altura da imagem, basta re-
tirar estas informações do quadro. Os dois seguintes que estão no exemplo: 96,96
são a quantidade de pontos por polegadas (dpi) nos eixos X e Y. O parâmetro se-
guinte se refere ao formato de cada pixel da imagem caso você altere o formato de inicialização do fluxo de cores possivelmente também terá de alterar o formato dos pixels da imagem. O parâmetro que está sendo enviado como null é utilizado para passar uma possível palete de cores, o que neste caso não é interessante. Após este, são enviados por parâmetro os bytes que a imagem contém e finalmente por último é enviado o stride da imagem.
Stride
Quando uma imagem ou vídeo é armazenado na memória de um
computador, seu buffer equivalente na memória pode conter informa-
ções extras, além da própria imagem após o fim de cada linha de pixels.
Estas informações extras geralmente são utilizadas para afetar a forma
como a imagem é armazenada na memória e não têm a ver com a forma
com que a imagem é exibida.
http://msdn.microsoft.com/en-us/library/windows/desktop/
aa473780
Após ter feito este método, precisamos
invocá-lo no evento que interpreta o
clique do botão. Ele irá conter apenas uma linha que fará com que a propri-
edade Source de nosso componente de imagem receba o retorno do método
ObterImagemSensorRGB. Lembre-se que este último método citado precisa re-
ceber por parâmetro o quadro atual do sensor RGB. Para fazermos isso, utilizamos o método OpenNextFrame do objeto ColorStream do sensor, que requer um pa-râmetro que representa o tempo de espera (em milissegundos) até que o frame seja aberto. Neste exemplo utilizaremos o valor 0 (zero), pois desejamos que a foto seja tirada instantaneamente.
private void Button_BaterFoto(object sender, RoutedEventArgs e)
{
imagemCamera.Source =
ObterImagemSensorRGB(kinect.ColorStream.OpenNextFrame(0));
}
34
Casa do Código
Capítulo 4. Fluxo de Cores
Agora podemos executar a aplicação e ao clicar no botão Bater Foto já temos
o resultado esperado!
Figura 4.5: Aplicação utilizando o sensor RGB
Utilizando o evento de quadros novos em um fluxo de cores
Já vimos como podemos buscar quadros dos fluxos sob demanda, que tal refato-
rar esta implementação para utilizar o evento? Com isso teremos uma nova imagem a cada quadro, ou seja, 30 vezes por segundo. Primeiramente removemos o botão
para bater foto (e seu método relacionado ao evento Click) de nossa aplicação, já que ele não faz mais sentido. Depois disso faremos um pequeno ajuste no método
InicializarKinect, iremos interpretar o evento ColorFrameReady do objeto
ColorStream após inicializar o fluxo deste objeto.
O método que interpretará este evento recebe por parâmetro um objeto do tipo
ColorImageFrameReadyEventArgs e é deste objeto que teremos que retirar o
novo quadro de imagem utilizando o método OpenColorImageFrame, ou seja,
35
4.2. Aplicação
Casa do Código
faremos uma chamada muito similar à que existia no método do botão de bater foto, porém desta vez, utilizaremos o quadro do objeto que é enviado por parâmetro e não diretamente do objeto de fluxo.
private void kinect_ColorFrameReady(object sender,