{
87
7.1. Iniciando a Estrutura Base para Detectar Movimentos
Casa do Código
private T movimento;
public EstadoRastreamento EstadoAtual { get; private set; }
public event EventHandler MovimentoIdentificado;
public event EventHandler MovimentoEmProgresso;
public Rastreador()
{
EstadoAtual = EstadoRastreamento.NaoIdentificado;
movimento = Activator.CreateInstance<T>();
}
public void Rastrear(Skeleton esqueletoUsuario)
{
EstadoRastreamento novoEstado =
movimento.Rastrear(esqueletoUsuario);
if (novoEstado == EstadoRastreamento.Identificado &&
EstadoAtual != EstadoRastreamento.Identificado)
ChamarEvento(MovimentoIdentificado);
if (novoEstado == EstadoRastreamento.EmExecucao &&
(EstadoAtual == EstadoRastreamento.EmExecucao ||
EstadoAtual == EstadoRastreamento.NaoIdentificado))
ChamarEvento(MovimentoEmProgresso);
EstadoAtual = novoEstado;
}
private void ChamarEvento(EventHandler evento)
{
if (evento != null)
evento(movimento, new EventArgs());
}
}
Com isso, nossa estrutura básica para poses já está pronta, voltaremos mais tarde para implementar a parte de gestos de nossa estrutura, agora vamos implementar as poses que de fato serão rastreadas.
88
Casa do Código
Capítulo 7. Rastreando e Identificando Movimentos
7.2
Utilizando Poses em Nossa Aplicação
A primeira pose que iremos criar é uma pose simples, conhecida como T. Esta
pose consiste em manter os dois braços esticados para os lados em altura paralela aos ombros, fazendo com que o formato do esqueleto do usuário se assemelhe com
a letra T (motivo do nome da pose).
Agora iremos criar uma nova pasta chamada Poses, que deve ficar dentro da
pasta Movimentos e nela devem ser inseridas todas as classes referentes a poses interpretadas por nossa aplicação. Nela iremos incluir a classe PoseT, lembre-se de que a classe PoseT deve ser uma classe concreta e herdar a classe Pose.
No construtor da classe PoseT já podemos inserir os valores nas proprieda-
des Nome e QuadroIdentificacao neste exemplo utilize respectivamente os
valores PoseT e 10. Quando você incluiu a herança da classe Pose você tornou necessário que a classe PoseT implemente a sobrescrita do método PosicalValida
(não é necessário sobrescrever o método Rastrear pois este já foi sobrescrito na classe Pose). Nesse momento sua classe deve estar semelhante à classe a seguir.
public class PoseT : Pose
{
public PoseT()
{
this.Nome = "PoseT";
this.QuadroIdentificacao = 10;
}
protected override bool PosicaoValida(Skeleton esqueletoUsuario)
{
}
}
Precisamos agora implementar estes métodos, mas antes de começarmos é im-
portante ter em mente que as comparações entre as articulações não devem ser feitas de forma exata, ou seja, é inviável exigir ao usuário que as posições sejam exatamente iguais. Para resolver isso devemos utilizar uma margem de erro na com-
paração dos valores entre quaisquer posições. Antes de implementar o método
PosicaoValida iremos criar uma nova classe estática chamada Util no names-
pace FuncoesBasicas. A classe Util será utilizada para fazer operações comuns,
como por exemplo, a comparação utilizando margem de erro.
89
7.2. Utilizando Poses em Nossa Aplicação
Casa do Código
Após criar a classe Util criaremos o método CompararComMargemErro que
deve receber por parâmetro três valores do tipo double, um valor para ser utilizado como margem de erro e os dois valores que serão comparados. Segue a implementação desta classe.
public static class Util
{
public static bool CompararComMargemErro
(double margemErro, double valor1, double valor2)
{
return valor1 >= valor2 - margemErro &&
valor1 <= valor2 + margemErro;
}
}
Podemos voltar agora para nossa classe PoseT e finalmente implementar o mé-
todo PosicaoValida. Este método deve utilizar as articulações do esqueleto do
usuário que é recebido por parâmetro para validar se o usuário está na posição relativa à pose em questão, neste caso, a pose T.
Na validação desta pose devemos comparar a altura(eixo Y) e a distância(eixo
Z) das mãos e dos cotovelos em relação ao centro dos ombros e se o eixo X das
mãos estão mais distantes de seu respectivo cotovelo. Todas essas comparações que envolvem igualdade devem utilizar margem de erro neste caso utilizaremos como margem de erro o valor 0.30, mas você pode ajustá-lo conforme sua necessidade de precisão, conforme o código.
protected override bool PosicaoValida
(Skeleton esqueletoUsuario)
{
Joint centroOmbros =
esqueletoUsuario.Joints[JointType.ShoulderCenter];
Joint maoDireita =
esqueletoUsuario.Joints[JointType.HandRight];
Joint cotoveloDireito =
esqueletoUsuario.Joints[JointType.ElbowRight];
Joint maoEsquerda =
esqueletoUsuario.Joints[JointType.HandLeft];
90
Casa do Código
Capítulo 7. Rastreando e Identificando Movimentos
Joint cotoveloEsquerdo =
esqueletoUsuario.Joints[JointType.ElbowLeft];
double margemErro = 0.30;
bool maoDireitaAlturaCorreta =
Util.CompararComMargemErro(margemErro,
maoDireita.Position.Y, centroOmbros.Position.Y);