Cardoso Gabriel Schade - Microsoft Kinect: Crie aplicações interativas стр 16.

Шрифт
Фон

Agora nossos três fluxos estarão ligados simultaneamente, mas não iremos interpretar os eventos ColorFrameReady e DepthFrameReady. Ao invés disso utili-

zaremos o evento AllFramesReady, pois através dele poderemos acessar tanto o

quadro de profundidade quanto o quadro de cores.

private void InicializarKinect(KinectSensor kinectSensor)

{

kinect = kinectSensor;

54

Casa do Código

Capítulo 5. Fluxo de Profundidade

slider.Value = kinect.ElevationAngle;

kinect.DepthStream.Enable();

kinect.SkeletonStream.Enable();

kinect.ColorStream.Enable();

kinect.AllFramesReady += kinect_AllFramesReady;

}

private void kinect_AllFramesReady

(object sender, AllFramesReadyEventArgs e)

{

}

Precisamos alterar o método ObterImagemSensorRGB para retornar o array

de bytes da imagem e não mais o objeto BitmapSource, pois agora precisamos

reutilizar os bytes da imagem no método que reconhecerá a distância dos objetos

além disso, não é mais necessário deixar a lógica de programação referente à escala cinza neste método. Após

estas alterações o método irá se parecer com o método

ilustrado a seguir.

private byte[] ObterImagemSensorRGB(ColorImageFrame quadro)

{

if (quadro == null) return null;

using (quadro)

{

byte[] bytesImagem = new byte[quadro.PixelDataLength];

quadro.CopyPixelDataTo(bytesImagem);

return bytesImagem;

}

}

O método ficou mais simples, pois agora ele apenas retorna os bytes da imagem.

Agora, é a vez de criarmos um novo método chamado ReconhecerDistância,

que deve receber por parâmetro os bytes da imagem e a distância máxima dos objetos para aplicar a escala cinza. A lógica para a escala cinza que foi removida do método anterior deve ser incorporada para este método dentro do bloco de validação da

distância do sensor conforme código.

55

5.3. Aplicação

Casa do Código

private void ReconhecerDistancia

(DepthImageFrame quadro, byte[] bytesImagem, int distanciaMaxima)

{

if (quadro == null || bytesImagem == null) return null;

using (quadro)

{

DepthImagePixel[] imagemProfundidade =

new DepthImagePixel[quadro.PixelDataLength];

quadro.CopyDepthImagePixelDataTo(imagemProfundidade);

for (int indice = 0;

indice < imagemProfundidade.Length;

indice++)

{

if (imagemProfundidade[indice].Depth < distanciaMaxima)

{

int indiceImageCores = indice * 4;

byte maiorValorCor =

Math.Max(bytesImagem[indiceImageCores],

Math.Max(bytesImagem[indiceImageCores + 1],

bytesImagem[indiceImageCores + 2]));

bytesImagem[indiceImageCores] = maiorValorCor;

bytesImagem[indiceImageCores + 1] = maiorValorCor;

bytesImagem[indiceImageCores + 2] = maiorValorCor;

}

}

}

Note que este método não retorna mais o objeto

BitmapSource, isso

ocorre pois criaremos a imagem dentro do método que interpreta o evento

AllFramesReady.

Neste método, sempre iremos captar a imagem do sen-

sor de cores, mas aplicaremos o filtro de escala cinza criado no método

ReconhecerDistância apenas quando o CheckBox Escala cinza estiver mar-

cado, conforme o código a seguir.

private void kinect_AllFramesReady

(object sender, AllFramesReadyEventArgs e)

{

56

Casa do Código

Capítulo 5. Fluxo de Profundidade

byte[] imagem = ObterImagemSensorRGB(e.OpenColorImageFrame());

if (chkEscalaCinza.IsChecked.HasValue &&

chkEscalaCinza.IsChecked.Value)

ReconhecerDistancia(e.OpenDepthImageFrame(), imagem, 2000);

if (imagem != null)

imagemCamera.Source =

BitmapSource.Create(kinect.ColorStream.FrameWidth,

kinect.ColorStream.FrameHeight,

96, 96, PixelFormats.Bgr32, null,

imagem,

kinect.ColorStream.FrameBytesPerPixel

* kinect.ColorStream.FrameWidth);

}

Se tudo foi implementado de maneira correta, o resultado que teremos deverá

ser similar ao resultado ilustrado pela figura 5.3.

57

5.3. Aplicação

Casa do Código

Figura 5.3: Escala cinza por distância

Você deve ter percebido que os pixels em escala cinza não estão perfeitamente

alinhados onde deveriam, isso fica bastante claro na figura 5.3. Este problema de alinhamento ocorre devido ao fato de que os dois sensores: cor e profundidade ficam em locais físicos diferentes. Para nos ajudar com este problema, existem técnicas de mapeamento, que são feitas através da classe CoordinateMapper.

A classe CoordinateMapper faz a transformação de um sistema de coordena-

das para outro entre os fluxos do Kinect. Infelizmente para fazer isso há uma perda no tamanho total da imagem, já que para equalizar os pontos é obrigatório que seja feita uma intersecção entre as visões dos diferentes sensores.

Utilizaremos a classe para mapear os pontos da imagem de profundidade em

um array de tamanho 640x480 (devido ao formato dos fluxos selecionados) e verificar a profundidade através destes pontos mapeados. Além disso, uma outra técnica que nos ajuda a melhorar a qualidade do resultado é verificar se o ponto de profundidade é um ponto reconhecido pelo Kinect. Após estas mudanças o método

ReconhecerDistancia deve ficar como o código adiante.

58

Casa do Código

Capítulo 5. Fluxo de Profundidade

private void

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке