{
int diametroArticulacao =
articulacao.JointType == JointType.Head ? 50 : 10;
int larguraDesenho = 4;
Brush corDesenho = Brushes.Red;
Ellipse objetoArticulacao =
CriarComponenteVisualArticulacao(
diametroArticulacao, larguraDesenho,
corDesenho);
68
Casa do Código
Capítulo 6. Fluxo de Esqueleto do Usuário
ColorImagePoint posicaoArticulacao =
ConverterCoordenadasArticulacao(articulacao,
canvasParaDesenhar.ActualWidth, canvasParaDesenhar.ActualHeight);
double deslocamentoHorizontal =
posicaoArticulacao.X - objetoArticulacao.Width / 2;
double deslocamentoVertical =
(posicaoArticulacao.Y - objetoArticulacao.Height / 2);
if ( deslocamentoVertical >= 0 &&
deslocamentoVertical < canvasParaDesenhar.ActualHeight &&
deslocamentoHorizontal >= 0 &&
deslocamentoHorizontal < canvasParaDesenhar.ActualWidth )
{
Canvas.SetLeft(objetoArticulacao, deslocamentoHorizontal);
Canvas.SetTop(objetoArticulacao, deslocamentoVertical);
Canvas.SetZIndex(objetoArticulacao, 100);
canvasParaDesenhar.Children.Add(objetoArticulacao);
}
}
Agora já temos um método para desenhar uma articulação do usuário, vamos fa-
zer um teste? A primeira coisa a ser feita em nossa janela é substituir o componente Image por um componente do tipo Canvas e renomeá-lo para canvasKinect.
Apenas com esta substituição já encontraremos um problema de compilação, pois o componente Canvas não possui a propriedade Source. No método que interpreta
o evento AllFramesReady vamos substituir a linha que atribuía esta propriedade
do componente Image por uma linha que altere a propriedade Background do
componente Canvas. Também faremos com que o Canvas limpe os seus compo-
nentes cada vez que o método é chamado, para que o rastro do usuários seja apagado e redesenhado a cada quadro, conforme código a seguir.
private void kinect_AllFramesReady
(object sender, AllFramesReadyEventArgs e)
{
byte[] imagem =
ObterImagemSensorRGB(e.OpenColorImageFrame());
69
6.2. Desenhando o Esqueleto do Usuário
Casa do Código
if( chkEscalaCinza.IsChecked.HasValue &&
chkEscalaCinza.IsChecked.Value)
ReconhecerDistancia(e.OpenDepthImageFrame(),
imagem, 2000);
if (imagem != null)
canvasKinect.Background = new ImageBrush(
BitmapSource.Create(kinect.ColorStream.FrameWidth,
kinect.ColorStream.FrameHeight,
96, 96, PixelFormats.Bgr32, null,
imagem,
kinect.ColorStream.FrameBytesPerPixel
* kinect.ColorStream.FrameWidth
)
);
canvasKinect.Children.Clear();
}
Após fazer isso iremos criar o método DesenharEsqueletoUsuario que re-
ceberá o SkeletonFrame por parâmetro e, assim como os outros métodos que
utilizam o quadro de outros fluxos, também devemos utilizar o comando using.
A classe Skeleton define a implementação virtual do esqueleto do usuário, então iremos utilizá-la para obter a articulação da mão do usuário. Isso pode ser feito através da propriedade Joints. Esta propriedade possui um indexador de acordo com
o tipo da articulação conforme descrito na figura 6.1. Agora apenas para testes, iremos desenhar as elipses na posição das articulações das mãos do usuário, conforme o código.
private void DesenharEsqueletoUsuario
(SkeletonFrame quadro)
{
if (quadro == null) return;
using (quadro)
{
Skeleton[] esqueletos =
new Skeleton[quadro.SkeletonArrayLength];
70
Casa do Código
Capítulo 6. Fluxo de Esqueleto do Usuário
quadro.CopySkeletonDataTo(esqueletos);
IEnumerable<Skeleton> esqueletosRastreados =
esqueletos.Where( esqueleto =>
esqueleto.TrackingState ==
SkeletonTrackingState.Tracked);
if (esqueletosRastreados.Count() > 0)
{
Skeleton esqueleto =
esqueletosRastreados.First();
EsqueletoUsuarioAuxiliar funcoesEsqueletos =
new EsqueletoUsuarioAuxiliar(kinect);
funcoesEsqueletos.DesenharArticulacao(
esqueleto.Joints[JointType.HandRight],
canvasKinect );
funcoesEsqueletos.DesenharArticulacao(
esqueleto.Joints[JointType.HandLeft],
canvasKinect );
}
}
}
Para finalizarmos precisamos fazer a chamada para o método acima, após a lim-
peza dos componentes do Canvas. Para obtermos o novo quadro do esqueleto que
iremos enviar por parâmetro precisamos utilizar e.OpenSkeletonFrame() no
método que interpreta o evento de todos os quadros. Com estas implementações
prontas, já podemos obter resultados conforme a figura 6.2.
71
6.2. Desenhando o Esqueleto do Usuário
Casa do Código
Figura 6.2: Desenhando a articulação das mãos
Neste ponto, já temos recursos para desenhar todas as articulações do usuá-
rio, mas iremos adicionar na classe EsqueletoUsuarioAuxiliar a funcio-
nalidade para desenhar os ossos entre as articulações. Vamos fazê-la através de dois métodos:
DesenharOsso e CriarComponenteVisualOsso. O método
CriarComponenteVisualOsso deve retornar um objeto do tipo Line e rece-
ber por parâmetro a largura e cor da linha que iremos utilizar para desenhá-la e as coordenadas X e Y das articulações de destino e origem, conforme o exemplo.
private Line CriarComponenteVisualOsso
(int larguraDesenho, Brush corDesenho,
double origemX, double origemY, double destinoX, double destinoY)