Desenvolvendo com o Kinect para o Windows.

Nós presenciamos o lançamento de novas tecnologias que mudam o nosso dia-a-dia. Quando digo que “mudam nosso dia-a-dia” me refiro ao fato de passarem a integrar o modo como realizamos nossas tarefas do cotidiano.

clip_image002

Alguns exemplos claros são: o smartphone, o micro-ondas, o computador, o tablet e a televisão. Isso é claro… isso é óbvio! Mas, existem outras criações que são tendências, e que ao meu ver, em questão de cinco anos, estarão totalmente integradas ao nosso dia-a-dia, como os aparelhos citados anteriormente.

E eu acredito que o Kinect fará parte desse seleto grupo de dispositivos que estão integrados ao nosso dia-a-dia, mas não acredito que ele esteja apenas atrelado no formato de uma ferramenta para jogos, e sim em uma ferramenta de integração e comunicação com os computadores, assim como o mouse e o teclado.

clip_image004

E tenho nos últimos meses dedicado algum tempo no estudo dos funcionamento do Kinect for Windows. O Kinect for Windows é um dispositivo semelhante ao Kinect para Xbox, exceto pelo falo de ser exclusivo para o uso em computadores.

O uso do Kinect for Windows permite a criação de adicionar olhos e ouvidos ao nosso computador (isso parece legal!). O uso do Kinect for Windows favorece a criação de aplicações que interajam mais naturalmente com os usuários de computadores, simplesmente permitindo o uso de gestos e fala.

O Kinect for Windows é diferente do Kinect for Xbox. Algumas diferenças entre os dois:
– Near mode: habilidade de identificar objetos a 40 centímetros de distância, sem perder precisão. Lembre-se que esse device foi construído para computadores, então estar perto do computador é uma exigência. Ok?
– Seated mode: um dos recursos mais importantes para trabalhar com computadores é a necessidade de identificar usuários que estão sentados, coisa que o Kinect for Xbox não consegue fazer. O Kinect por padrão trabalha com esqueletos com 20 pontos, neste caso o Kinect for Windows faz o tracking de metade deste esqueleto, apenas 10 pontos.
– USB: o Kinect for Windows tem uma saída USB, algo que o Kinect for Xbox não tem.
– Configurações avançadas de câmera: configurações adicionais para ajuste de luminosidade, exposição, etc.
– Kinect Fusion: mapeamento 3D do ambiente (isso é muito legal!).
– Movimentos com as mãos: gestos manuais como abrir e fechar de mãos e pressão sobre objetos podem ser identificados.

clip_image006

Para começarmos a trabalhar com o Kinect for Windows (daqui pra frente chamado apenas de “Kinect”) precisamos fazer o download e a instalação do SDK. O SDK do Kinect pode ser encontrado neste link: http://www.microsoft.com/en-us/kinectforwindows/develop/developer-downloads.aspx

Recomendo “fortemente” que junto ao download (e instalação) do SDK, seja também feito o download e a instalação do Kinect Developer Toolkit (cuja página de download é a mesma do SDK). O Developer Toolkit, como o nome já diz, contém diversas ferramentas que lhe ajudarão na construção de aplicações, além de um conjunto de exemplos (com código fonte) que podem servir como base para o início das atividades de desenvolvimento.

Hoje é possível construir aplicações para o Kinect utilizando C++, C# ou VB.Net. Segue aqui um link para as novidades relacionadas a esta versão do SDK: http://msdn.microsoft.com/en-us/library/jj663803.aspx#SDK_1pt7

Para fazer o download deste exemplo, acesse este link: http://code.msdn.microsoft.com/Desenvolvendo-com-o-Kinect-4b96dfa2

Obs.: Quando este post foi escrito o SDK do Kinect estava na versão 1.7.

Botando a mão na massa!

Começaremos com um exemplo utilizando WPF e o Kinect.

1 – Crie uma aplicação WPF.
2 – Faça referência para as seguintes DLLs (elas estão localizadas a partir do caminho “C\Program Files\Microsoft SDKs\Kinect\”):

Microsoft.Kinect.dll (\v1.7\Assemblies\)
Microsoft.Kinect.Toolkit.dll (\Developer Toolkit v1.7.0\Assemblies\)
Microsoft.Kinect.Toolkit.Controls.dll (\Developer Toolkit v1.7.0\Assemblies\)
Microsoft.Kinect.Toolkit.Interaction.dll (\Developer Toolkit v1.7.0\Assemblies\)

3 – No design do arquivo MinWindow.xaml adicione a seguinte referência:

xmlns:k="http://schemas.microsoft.com/kinect/2013"

Seu código deverá se parecer com a imagem abaixo.

clip_image008

4 – Substitua o GRID existente em MainWindow pela seguinte estrutura.

<Grid Width="Auto">
    <Grid.RowDefinitions>
        <RowDefinition Height="40px"/>
        <RowDefinition Height="105px"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Border Grid.Column="0" Grid.Row="0" BorderBrush="Black" Height="40px" Width="40px" BorderThickness="1">
        <k:KinectSensorChooserUI Panel.ZIndex="1" HorizontalAlignment="Center" VerticalAlignment="Top" Name="sensorChooserUi" Background="WhiteSmoke" />
    </Border>

    <Border Grid.Column="0" Grid.Row="1" BorderBrush="Black" Width="300px" Height="100px" BorderThickness="1">
        <StackPanel  Background="WhiteSmoke" Width="300px" Height="100px" >
            <k:KinectUserViewer Panel.ZIndex="0" VerticalAlignment="Top" HorizontalAlignment="Center" k:KinectRegion.KinectRegion="{Binding ElementName=kinectRegion}" Height="100"  />
        </StackPanel>
    </Border>

    <Border Grid.Column="0" Grid.Row="2" BorderBrush="Black" BorderThickness="1">

    </Border>
</Grid>

Nessa estrutura estamos adicionando alguns controles existentes no Toolkit do Kinect. Esses controles são:

KinectSensorChooserUI: este é um controle bastante útil e importante, que indica o status do sensor Kinect conectado. Este controle nos informa se o sensor está conectado, desconectado, se existe algum erro de conexão, etc.

KinectUserViewer: controle que exibe os pixels de profundidade do(s) usuário(s) identificado(s). A vantagem de utilizar este controle é a possibilidade de visualizar aquilo que o Kinect está registrando. Muitas vezes nossos movimentos estão ultrapassando as fronteiras do Kinect e não percebemos isso. Assim, o KinectUserViewer nos auxilia a visualizar aquilo que o Kinect tem captado.

KinectRegion: este é o controle chave para integração de aplicações WPF com o Kinect. O KinectRegion define uma área útil na qual o usuário pode manipular controles e interagir.

5 – Adicionar código para iteração entre os controles.

O código abaixo deve ser adicionado a tela MainWindow. O código contém comentários e explica o que está sendo feito, mas em poucas palavras este código: cria uma conexão com o sensor Kinect, configura seu funcionamento para trabalhar no modelo “perto” com o controlador “sentado” e encerrando as atividades do sensor Kinect quando a janela é fechada.

    using System;
    using System.Windows;
    using Microsoft.Kinect;
    using Microsoft.Kinect.Toolkit;
    using Microsoft.Kinect.Toolkit.Controls;

    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();

            Loaded += OnLoaded;
            Closing += OnClosing;
        }

        private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e) {
            TurnOffKinect();
        }

        private void OnLoaded(object sender, RoutedEventArgs e) {
            TurnOnKinect();
        }

        #region [ Kinect content ]

        private KinectSensorChooser sensorChooser;

        private void TurnOffKinect() {
            // Encerra as atividades do sensor
            if (this.sensorChooser != null)
                this.sensorChooser.Stop();
        }

        private void TurnOnKinect() {
            // Inicializar KinectSensorChooser
            this.sensorChooser = new KinectSensorChooser();
            this.sensorChooser.KinectChanged += OnSensorChooserOnKinectChanged;
            this.sensorChooserUi.KinectSensorChooser = this.sensorChooser;
            // Inicializar o sensor
            this.sensorChooser.Start();
        }

        private void OnSensorChooserOnKinectChanged(object sender, KinectChangedEventArgs e) {
            bool error = false;

            if (e.NewSensor != null) {
                try {
                    // Configura a resolução da proximidade
                    e.NewSensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
                    // Habilita o esquelo
                    e.NewSensor.SkeletonStream.Enable();
                    try {
                        // Configura o Kinect para trabalhar no modelo "perto"
                        e.NewSensor.DepthStream.Range = DepthRange.Near;
                        // Configura o tracking do esquelo para trabalhar
                        // em um modelo "perto" onde o usuário esteja "sentado"
                        e.NewSensor.SkeletonStream.EnableTrackingInNearRange = true;
                        e.NewSensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
                    } catch (InvalidOperationException) {
                        e.NewSensor.DepthStream.Range = DepthRange.Default;
                        e.NewSensor.SkeletonStream.EnableTrackingInNearRange = false;
                        error = true;
                    }
                } catch (InvalidOperationException) {
                    error = true;
                }
            }

            // Associar o sensor Kinect com o KinectRegion
            if (!error)
                kinectRegion.KinectSensor = e.NewSensor;
        }

        #endregion       
    }

6 – Executando a aplicação.

Após executar a aplicação, utilizando o código acima, acontecerá um erro em tempo de execução. Sim, o código está correto, mas provavelmente a mensagem de erro será algo como: “Unable to invoque library ‘KinectInteraction170_32.dll’” (imagem abaixo). Este erro indica que esta faltando uma biblioteca na pasta de execução da aplicação. Para resolver este problema, basta copiar a DLL “KinectInteraction170_32.dll”, localizada no caminho “C:\Program Files\Microsoft SDKs\Kinect\Developer Toolkit v1.7.0\Redist\x86”, para a pasta Debug (ou Release) da sua solução.

clip_image009

Após isso, basta executar a aplicação novamente e mover-se na frente do Kinect para ativar o “hand” dentro da área delimitada pelo KinectRegion.

A imagem abaixo é uma demonstração do nosso exemplo funcionando.

clip_image011

7 – Adicionando controles para interação com o Kinect.

Agora, adicione ao GRID contido no KinectRegion um controle KinectScrollViewer, assim como no código abaixo:

<k:KinectRegion Name="kinectRegion" Width="Auto">
    <Grid>
        <k:KinectScrollViewer>
            <StackPanel Name="ScrollKinect">

            </StackPanel>
        </k:KinectScrollViewer>
    </Grid>
</k:KinectRegion>

Veja que o controle KinectScrollViewer contém um StackPanel chamado “ScrollKinect”.

Agora, vamos adicionar o seguinte código a nossa Window.

    private void LoadSomeControls()
    {
        for (int i = 0; i < 50; i++)
        {
            KinectTileButton button = new KinectTileButton();
            button.Label = string.Format("Button {0}", i);
            button.Click += TileButtonClick;
            this.ScrollKinect.Children.Add(button);
        }
    }

    void TileButtonClick(object sender, RoutedEventArgs e)
    {
        KinectTileButton button = (KinectTileButton)sender;
        MessageBox.Show(button.Label.ToString());
    }

E adicione uma chamada ao método “LoadSomeControls” no corpo do método “OnLoaded”.

Após executar a aplicação nosso resultado será algo como a janela abaixo.

clip_image013

Uma série de controles, chamados KinectTileButtons, serão listados permitindo que o efeito de clique seja feito através do movimento de pressão sobre o controle, assim como será possível arrastar os controles através do movimento de grip (mão fechada arrastando os itens). As imagens abaixo demonstram esses dois cenários.

clip_image014

Acima a imagem reproduzindo o efeito de pressão sobre um KinectTileButton.

clip_image015

Acima o movimento de grip (mão cerrada), permitindo o “agarre” e “arraste” de controles contidos em um KinectScrollViewer.

Essa foi uma introdução sobre o uso de Kinect for Windows. Teremos muitas novidades nos próximos meses, isso eu posso garantir. Espero que este post funcione como estimulo para a descoberta de novas tecnologias e paradigmas.

Abaixo a foto do meu Kinect for Windows. Gentilmente cedido por Ben Lower e cuidadosamente trazido para terras brasileiras pelo meu grande amigo Mario de Abreu.

clip_image017

Por

MSc. Fernando Henrique Inocêncio Borba Ferreira

Microsoft Most Valuable Professional – Visual C#

Referências:

http://www.microsoft.com/en-us/kinectforwindows

http://www.kinectingforwindows.com/2012/09/07/what-is-the-difference-between-kinect-for-windows-kinect-for-xbox360

http://msdn.microsoft.com/en-us/magazine/jj159883.aspx

http://channel9.msdn.com/coding4fun/kinect/Getting-started-with-Developing-with-Microsoft-Kinect

http://www.microsoft.com/en-us/kinectforwindows/develop/developer-downloads.aspx

Anúncios

24 Responses to Desenvolvendo com o Kinect para o Windows.

  1. Yan Justino says:

    Eita, bem que você disse. rsrrs! Fernando me diz uma coisa. No artigo você falou as diferenças entre o K for windows e o K for XBOX. Eu tenho o kintect do XBOX e gostaria de saber, mesmo com estas diferenças, esse SDK é com patível com o Kintect XBOX?

    • Grande Yan!
      Tudo beleza? 🙂

      Cara, eu fiz esse teste duas semanas atrás, e a resposta é: não.
      O Kinect for XBox não é reconhecido por esses controles do Kinect for Windows.
      Realmente esse SDK é restrito ao uso do Kinect for Windows.

      []s!

      • Valdenir says:

        Olá amigos, primeiramente quero parabenizar pela iniciativa do tutorial, um passo a passo bem eficaz para quem está começando!
        Em segundo lugar, queria dizer que todas as implementações efetuadas no Kinekt for Windows, também podem ser implementadas no Kinekt for XBOX. Algumas diferenças de distância de captação, e também na documentação está esplícito, que o desenvolvedor pode desenvolver com o “For XBOX”, mas não pode comercializar as aplicações, para comercializar necessita-se no “For Windows”, qualquer dúvida, estou no e-mail! Abraços e parabéns pelo tutorial!

      • Olá Valdenir! Obrigado por sua contribuição e obrigado por postar! []s!

  2. MayogaX says:

    Parabéns, mestre, show de bola!

    Imressão ou você precisou fazer uma especie de loop dentro do Main, como se fosse um jogo mesmo, para ir percebendo o sensor do Kinect? Nele você ativa e desativa o Kinect em loop?

    • Oi Pri, obrigado por postar!
      Na verdade eu não crio um laço para ativar o Kinect, apenas faço o start uma vez quando a tela é carregada, assim como faço o stop uma vez quando a tela é fechada.
      O resto é o Kinect trabalhando 🙂

  3. Zanatta says:

    Olá,
    tentamos executar após o item 6, não tem errors nem warning, mas a imagem não aparece, fica em branco todas as telas, após aparecer uma imagem azul de um kinect na menor janela. O que poderia estar acontecendo?

    • Olá Zanatta,
      Tudo bem?

      Vc esta utilizando um Kinect para Windows ou um Kinect para XBox?

      Me manda o seu código fonte que eu dou uma olhada.

      []s!

      • Zanatta says:

        Olá, tudo bem comigo
        Nós utilizamos Kinect para Windows

        o código é esse :

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Windows;
        using System.Windows.Controls;
        using System.Windows.Data;
        using System.Windows.Documents;
        using System.Windows.Input;
        using System.Windows.Media;
        using System.Windows.Media.Imaging;
        using System.Windows.Navigation;
        using System.Windows.Shapes;

        using Microsoft.Kinect;

        using Microsoft.Kinect.Toolkit;
        using Microsoft.Kinect.Toolkit.Controls;
        using Microsoft.Kinect.Toolkit.Interaction;

        namespace WpfApplication1
        {
        ///
        /// Interaction logic for MainWindow.xaml
        ///
        public partial class MainWindow : Window
        {
        public MainWindow() {
        InitializeComponent();

        Loaded += OnLoaded;
        Closing += OnClosing;
        }

        private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e) {
        TurnOffKinect();
        }

        private void OnLoaded(object sender, RoutedEventArgs e) {
        TurnOnKinect();
        }

        #region [ Kinect content ]

        private KinectSensorChooser sensorChooser;
        KinectRegion kinectRegion = new KinectRegion();
        private void TurnOffKinect() {
        // Encerra as atividades do sensor
        if (this.sensorChooser != null)
        this.sensorChooser.Stop();
        }

        private void TurnOnKinect() {
        // Inicializar KinectSensorChooser
        this.sensorChooser = new KinectSensorChooser();
        this.sensorChooser.KinectChanged += OnSensorChooserOnKinectChanged;
        this.sensorChooserUi.KinectSensorChooser = this.sensorChooser;
        // Inicializar o sensor
        this.sensorChooser.Start();
        }

        private void OnSensorChooserOnKinectChanged(object sender, KinectChangedEventArgs e)
        {
        bool error = false;

        if (e.NewSensor != null)
        {
        try
        {
        // Configura a resolução da proximidade
        e.NewSensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
        // Habilita o esquelo
        e.NewSensor.SkeletonStream.Enable();
        try
        {
        // Configura o Kinect para trabalhar no modelo “perto”
        e.NewSensor.DepthStream.Range = DepthRange.Near;
        // Configura o tracking do esquelo para trabalhar
        // em um modelo “perto” onde o usuário esteja “sentado”
        e.NewSensor.SkeletonStream.EnableTrackingInNearRange = true;
        e.NewSensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
        }
        catch (InvalidOperationException)
        {
        e.NewSensor.DepthStream.Range = DepthRange.Default;
        e.NewSensor.SkeletonStream.EnableTrackingInNearRange = false;
        error = true;
        }
        }
        catch (InvalidOperationException)
        {
        error = true;
        }
        }

        // Associar o sensor Kinect com o KinectRegion
        if (!error)
        kinectRegion.KinectSensor = e.NewSensor;
        }

        #endregion
        }
        }

  4. André Nascimento says:

    Parabéns Fernando pelo Blog.
    Estamos utilizando o kinect para xbox. Os códigos acima são para xbox ou para windows?

    • Olá André,
      Tudo bem?
      Sim, esse código eu acredito que seja exclusívo para Kinect for Windows. Fiz um teste rápido algum tempo atrás e os componentes do Kinect for Windows não reconhecem o Kinect for XBox. Talvez seja preciso fazer algum teste mais apurado, mas inicialmente minha tentativa não funcionou. Vc faz parte de alguma universidade?

      Obrigado por postar.
      []s!

      • André Nascimento says:

        Olá Fernando. Obrigado pelo retorno. Somos da Universidade Paulista e precisamos desenvolver um projeto para o TCC. Achamos sua explicação acima muito legal, mas estamos utilizando o Kinect Xbox para o projeto. Se tiver alguma dica. Tks

  5. Allyson says:

    Olá Fernando,
    Tudo bem?
    Gostaria de saber qual a maneira mais viável para reconhecer apenas os dois usuários mais próximos do Kinect, de modo que evite interferências com outras pessoas que estejam passando pelo pela aplicação.

    • Olá Allyson,
      Tudo beleza?
      Também não sei fazer isso. Ainda estou estudando o Kinect e motando algumas aplicações simples. Chegou a pesquisar em outros lugares?
      []s!

  6. Adilio says:

    Boa tarde !
    Você poderia me explicar melhor do item 7 para baixo pois não estou conseguindo:
    7 – Adicionando controles para interação com o Kinect.
    Agora, adicione ao GRID contido no KinectRegion um controle KinectScrollViewer, assim como no código abaixo:

    Veja que o controle KinectScrollViewer contém um StackPanel chamado “ScrollKinect”.
    Agora, vamos adicionar o seguinte código a nossa Window.
    private void LoadSomeControls()
    {
    for (int i = 0; i < 50; i++)
    {
    KinectTileButton button = new KinectTileButton();
    button.Label = string.Format("Button {0}", i);
    button.Click += TileButtonClick;
    this.ScrollKinect.Children.Add(button);
    }
    }

    void TileButtonClick(object sender, RoutedEventArgs e)
    {
    KinectTileButton button = (KinectTileButton)sender;
    MessageBox.Show(button.Label.ToString());
    }
    E adicione uma chamada ao método “LoadSomeControls” no corpo do método “OnLoaded”.

  7. Adilio says:

    Vc teria como encaminhar a pasta com projeto completo?
    adiliofranco@yahoo.com.br

  8. Ola Fernando beleza?

    Tenho uma dúvida estou desenvolvendo uma aplicação com várias janelas WPF, interagindo entre si. Só que quando vou para outra janela WPF ou volto para a principal eu perco a interatividade com o kinect…você saberia me dizer o que pode ser?

    • Olá Thiago,
      Tudo beleza?

      Engraçado, eu não tenho esse problema. Como vc está fazendo? Está criando um KinectUserViewer e um KinectSensorChooserUI para cada página?

      Eu tenho um formulário principal com um KinectUserViewer, um KinectSensorChooserUI e um KinectRegion. Dentro do KinectRegion tenho um Frame chamado TransitionControl. E sempre que preciso naver para uma Page eu executo o código abaixo:

      public void NavigateTo(Page targetPage) {
      TransitionControl.Content = targetPage;
      }

      []s!

      • então eu joguei toda essas propriedades do kinect em todas as telas mas mesmo assim persiste o problema.e uma resposta para ferhenriqueibf Cancelar resposta

        Você poderia me mandar o código dessa sua aplicação que ta rodando esse código ae pra poder navegar entre as telas?

        Muito obrigado cara.

      • Olá Thiago. A questão é q vc não pode jogar todos esses controles em todas as telas. Apenas em uma. Senão realmente vc irá perder as conexões. E vc deve fazer com que o conteúdo das demais telas seja aberto dentro da primeira através do Frame. Não consigo lhe enviar agora cedo, mas vou lhe montar um exemplo e lhe envio esse fim de semana. []s!

  9. Thiago says:

    Beleza man ficarei no aguardo do seu exemplo.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: