56
BARDIAU Romain CRĂCIUN Anamaria DANILUC Dora SAVU Alexandra SOUTI Bilal [DÉVELOPPEMENT D'UNE API DE RECONNAISSANCE DE GESTES POUR LE CAPTEUR KINECT]

DÉveloppement d'une API de reconnaissance de …deptinfo.unice.fr/twiki/pub/Minfo/Affectation10-11/Rapport-01.pdf · humain fourni par le capteur Kinect, ... La reconnaissance du

Embed Size (px)

Citation preview

BARDIAU Romain CRĂCIUN Anamaria DANILUC Dora SAVU Alexandra SOUTI Bilal

[DÉVELOPPEMENT D'UNE API DE RECONNAISSANCE DE GESTES POUR LE CAPTEUR KINECT]

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 2

Abstract

Les gestes et la reconnaissance des gestes sont des termes de plus en plus rencontrés dans les

discussions sur l'interaction homme-machine, surtout en ce qui concerne le domaine des jeux

vidéo, avec l’apparition des nouveaux contrôleurs développés par les constructeurs de consoles

de jeux.

L’intégration du contrôle à travers des gestes dans des logiciels embarqués ou qui contrôlent

des objets à distance pourrait constituer un grand pas en avant dans des domaines comme la

robotique ou la domotique.

C’est dans ce contexte que se situe le sujet de ce TER, qui consiste en la création d’une API de

reconnaissance de gestes qui permettrait l’utilisation du capteur Kinect développé par

Microsoft dans des projets qui ne se limitent pas qu’à la console de jeux Xbox pour laquelle

Kinect a été initialement conçu.

Une fois l’API développée, son utilisation a été illustrée à travers un programme qui contrôle un

robot uniquement à l’aide des gestes, ce qui a permis de donner une première vue sur une des

utilisations possibles de la reconnaissance des gestes dans des applications situées en dehors

de l’univers des jeux vidéo.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 3

Remerciements

Nous souhaitons remercier toute l’équipe pédagogique de l’Université de Nice-Sophia Antipolis

ainsi que les intervenants professionnels responsables du Master I Informatique pour tous les

enseignements qu’ils nous ont apportés.

Nous remercions également Mr Michel BUFFA, notre tuteur pour ce TER, pour l’aide et les

conseils concernant les missions évoquées dans ce rapport, ainsi que pour les idées qui nous

ont aidés à structurer le sujet de ce projet.

Mr Fabrice Huet, le responsable du TER, pour son soutien et son aide, et pour l’intérêt qu’il

nous a porté.

L’équipe de SimplySim, Nicolas Dalmasso et Bertrand Copigneaux, pour nous avoir accueillis et

pour avoir partagé leur expérience dans le domaine avec nous.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 4

Table des matières

Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Introduction

Présentation du sujet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

Gestes et reconnaissance des gestes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

Description du capteur Kinect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Description du robot Mindstorms NXT 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

Projets existants dans le domaine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Travail réalisé

Choix technologiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Outils développés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Construction du robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Les algorithmes utilisés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

L’algorithme $1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

L’algorithme $N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

Main ouverte/main fermée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

Programmation de l’API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

Description de l’API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

Les classes de l’API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

Les plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

L’utilisation de l’API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

Programmation du robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 5

Le code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Le contrôle du robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

L’association des gestes détectés par l’API aux actions du robot . . . . . . . . . 35

Organisation de l’équipe

Découpage des tâches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

Estimation du travail réalisé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Bilan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

Annexes

Références . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Liste des gestes reconnus par le plugin Dollar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

Liste des gestes reconnus par le plugin NDollar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

Liste des poses reconnues par le plugin NDollar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 6

Introduction

Présentation du sujet

Le but de ce TER a été de créer une API de reconnaissance des gestes en utilisant le squelette

humain fourni par le capteur Kinect, qui pourra être par la suite intégrée dans des applications

qui utilisent le contrôle par mouvements (Control By Gesture) à travers des interfaces

utilisateur de type NUI (Natural User Interfaces). Une fois l’API développée, un deuxième

objectif a été de créer une application qui se sert de cette API pour illustrer son utilité dans le

contexte de la robotique, et ceci en utilisant le robot Lego Mindstorms NXT 2.0.

Gestes et reconnaissance des gestes

La reconnaissance du mouvement est un sujet informatique qui a comme but d'interpréter les

gestes de l'humain via des algorithmes mathématiques. Les gestes peuvent provenir de

n'importe quel mouvement du corps ou d’une pose, mais les centres d’intérêt dans ce domaine

sont le visage, plus précisément la reconnaissance des émotions qui s’expriment à travers le

visage, et les gestes faits avec la main.

La reconnaissance des gestes peut être considérée comme un moyen pour les ordinateurs de

commencer à comprendre le langage du corps humain, créant ainsi une liaison plus forte entre

les machines et les humains, autre que celle offerte par les interfaces primitives en mode texte

ou même des interfaces graphiques, qui limitent encore la communication au clavier et à la

souris.

En ce qui concerne la programmation de la reconnaissance du mouvement, celle-là peut être

accomplie avec des techniques de vision par ordinateur et de traitement d'images.

Comme Baudel et Beaudouin-Lafon (1993) le soulignent, il y a un certain nombre d'avantages

offerts par l’utilisation des gestes pour l’interaction :

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 7

Une interaction naturelle : les gestes sont une forme naturelle de l'interaction, et sont

faciles à utiliser ;

Simple et puissant : un geste simple peut être utilisé pour spécifier à la fois une

commande ainsi que ses paramètres ;

Une interaction directe : la main utilisée en tant que périphérique d’entrée élimine le

besoin d’objets intermédiaires entre la personne et la machine.

Dispositifs d’entrée qui permettent la reconnaissance des gestes

Le fait de suivre les mouvements d'une personne et de déterminer quels gestes elle est en train

de faire peut être obtenu grâce à divers outils.

Bien qu'il y ait une grande quantité de recherche dans le domaine de la reconnaissance à l’aide

des images ou de la vidéo, des différences existent entre les outils et environnements utilisés

entre les différentes implémentations :

Caméras basées sur la profondeur : en utilisant des caméras spécialisées, on peut

générer une carte de profondeur de ce qui est vu par la caméra sur des courtes

distances, et utiliser ces données pour calculer une approximation d’une représentation

3D de ce qui est vu. Ceux-ci peuvent être efficaces pour la détection de gestes de la

main grâce à leur précision sur des courtes distances.

Caméras stéréo : en utilisant deux caméras dont les positions relatives d’une par

rapport à l’autre sont connues, une représentation 3D peut être approximée en utilisant

les données enregistrées par les deux caméras.

Gestes basés sur un contrôleur : des contrôleurs tels qu’une télécommande ou un

téléphone portable peuvent agir comme des extensions du corps, de manière à ce que

lorsque les gestes sont effectués, certains de leurs mouvements peuvent être facilement

capturés par des logiciels. La souris est un tel exemple, où le mouvement de la souris est

associé à un symbole en train d’être dessiné par la main d’une personne, et la manette

Wii est un autre exemple d’un tel dispositif, qui peut étudier les changements

d'accélération dans le mouvement de la main au cours du temps pour représenter des

gestes.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 8

Description du capteur Kinect

Kinect est un périphérique développé par Microsoft, destiné à la console de jeux vidéo Xbox

360, qui permet de contrôler des jeux vidéo sans utiliser de manette.

Le périphérique est basé sur une technologie logicielle développée par Rare, une

filiale de Microsoft Game Studios appartenant à Microsoft, et sur une caméra spécifique créée

par PrimeSense, qui interprète les informations sur la scène 3D obtenue à travers une lumière

infrarouge structurée et projetée en continu. Ce système de scanner 3D appelé « Light

Coding » utilise une variante de la reconstruction 3D basée sur l’image.

Le capteur Kinect est une barre horizontale reliée à une petite base avec un pivot motorisé,

conçu pour être placé au-dessus ou en dessous de l'affichage vidéo (téléviseur, écran d’un

ordinateur). Le dispositif comporte une caméra RGB, un capteur de profondeur et un

microphone multi-réseau exécutant un logiciel propriétaire, qui fournissent la capture du

mouvement du corps en 3D, la reconnaissance faciale et la reconnaissance vocale.

Le capteur de profondeur se compose d'un projecteur laser infrarouge combiné à un capteur

CMOS monochrome, qui capture des données vidéo en 3D dans toutes les conditions de

lumière ambiante. Le rayon de détection de ce capteur est réglable, et le logiciel de Kinect est

capable de calibrer automatiquement le capteur en fonction du gameplay ou de

l'environnement physique du joueur, pouvant accueillir la présence des meubles ou d'autres

obstacles.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 9

Caractéristiques techniques de Kinect

Capteur :

Lentilles détectant la couleur et la profondeur ;

Microphone à reconnaissance vocale ;

Capteur motorisé pour suivre les déplacements ;

Champ de vision :

Champ de vision horizontal : 57 degrés ;

Champ de vision vertical : 43 degrés ;

Marge de déplacement du capteur : ± 27 degrés ;

Portée du capteur : 1.2m – 3.5m ;

Flux de données :

320×240 en couleur 16 bits à 30 images/sec ;

640×480 en couleur 32 bits à 30 images/sec ;

Audio 16 bits à 16 kHz ;

Système de reconnaissance physique :

Jusqu’à 6 personnes et 2 joueurs actifs ;

15 articulations par squelette ;

Application des mouvements des joueurs sur leurs avatars Xbox Live ;

Audio :

Chat vocal Xbox Live et chat vocal dans les jeux (nécessite un compte Xbox Live Gold) ;

Suppression de l’écho ;

Reconnaissance vocale multilingue ;

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 10

Description du robot Mindstorms NXT 2.0

Mindstorms NXT 2.0 est un robot programmable créé par Lego, qui associe la polyvalence

illimitée des systèmes de construction LEGO à une brique intelligente.

L’ensemble du robot comprend :

La brique intelligente NXT LEGO qui inclut un microprocesseur de 32 bits, un grand

écran à matrice, 4 ports d'entrée et 3 ports de sortie ainsi qu'un lien de communication

USB et Bluetooth ;

Trois servomoteurs interactifs ;

Quatre capteurs dont un capteur ultrasonique, 2 capteurs de contact et un capteur de

couleurs. Le capteur de couleurs dispose de trois fonctionnalités : il distingue les

couleurs et la lumière et fonctionne comme une lampe ;

612 pièces LEGO® nécessaires pour créer une multitude de robots ;

Les éléments qui composent le robot LEGO Mindstorms NXT 2.0

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 11

Projets existants dans le domaine

Kinect

Nui.Vision : Une mini librairie créé par Vangos Pterneas qui permet d’utiliser Kinect plus

facilement pour juste récupérér les images des caméras (Depth et Normal) ainsi que le

squelette (en WPF).

Cette librairie était disponible juste sous forme de fichier dll mais on s’est inspiré de son

utilisation pour créer notre propre API.

http://www.studentguru.gr/blogs/vangos/archive/2011/03/15/kinect-and-wpf-

complete-body-tracking.aspx

UserTracker.net : Exemple fourni par OpenNi pour montrer comment utiliser les

fonctions de OpenNi (en windows Forms).

Faast : Flexible Action and Articulated Skeleton Toolkit : permet d’associer un geste a

une entrée clavier, écrit en C++.

http://projects.ict.usc.edu/mxr/faast/

Kinect + Mindstorm : Vidéo où une personne contrôle un robot LEGO Mindstorms avec

Kinect, mais le code de l’application n’est pas disponible.

http://thenxtstep.blogspot.com/2011/03/kinect-mindstorms.html

Mindstorms NXT

Après une recherche sur Google pour pouvoir découvrir plusieurs applications qui ont été

développées en utilisant C# et la librairie MindSqualls, voici les projets qu’on a pu trouver:

NXT Tri-Bot collection using C# Express and MindSqualls Library. Cette application

donne une rétroaction visuelle de ce que les moteurs et les capteurs font. L'application

a beaucoup de labels indiquant l’état actuel des différents paramètres.

http://nxtcodecollection.codeplex.com/

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 12

Basic Robot Control using NKH Mindsqualls Libraries. Ce code montre comment faire

un contrôle de base d'un robot LEGO NXT via une connexion Bluetooth.

http://www.codeproject.com/KB/cross-platform/Basic-Robot-Control.aspx

Nxt mindsqualls collection of code. L'application fait que les Capteurs / Motors

réalisent un certain nombre de tâches en utilisant une souris et un joystick. Les

programmes offrent à l'utilisateur une rétroaction visuelle de ce qu’un ou plusieurs

moteur (s) ainsi que les capteurs font à un moment donné. L'application offre aussi un

support pour les webcams et pour une Logitech Extreme 3D Pro Joystick. Il a également

un support pour les capteurs standard et le HiTechnicCompassSensor.

http://code.google.com/p/nxtmindsquallscollectionofcode/

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 13

Travail réalisé

Choix technologiques

L’API Kinect

Pour le choix du driver de Kinect, on a choisi celui de OpenNi puisque c’est le driver officiel pour

l’utilisation de Kinect sur un ordinateur. Il existe en version C++ et C# (.NET), et on a préféré

celui de C# puisque le langage est plus proche de Java, un langage qui nous est familier. De plus,

la librairie est plus facile à utiliser mais malheureusement moins documentée.

Pour la reconnaissance des gestes, nous avons opté pour l'algorithme $1 (que nous allons

détailler plus loin dans ce document), puisqu’il était le seul qui permettait une reconnaissance

rapide, sans une phase d’apprentissage, comparé à d'autres algorithmes tels que les réseaux de

neurones ou les Hidden Markov Model.

Un autre choix dans la création de l’API a été de ne pas utiliser l’algorithme $3, une variante du

$1 mais qui prend en compte les trois directions de l’espace (un point dans cet algorithme est

caractérisé par les trois coordonnées, X, Y et Z). Ce choix a été motivé par le fait que dans les

implémentations existantes de cet algorithme, les résultats qu’il offre pour la détection d’un

geste sont trop souvent des faux positifs.

Le robot

Il existe plusieurs libraires C# pour contrôler un robot Lego:

Mindsqualls

NXT.Net

Aforge.Net

Au début, nous avons pensé à utiliser la deuxième, NXT.Net, parce qu’elle est écrite dans une

version plus récente de la plateforme .net, 3.0. Mais après avoir étudié plus en détail les

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 14

caractéristiques de cette librairie on a découvert qu’elle n’avait pas de documentation et aussi

qu’elle présentait encore des bugs. Cela nous a déterminé à chercher d’autres librairies.

Aforge.Net, même si stable, présente une contrainte technique qui nous a contraint à ne la pas

prendre en considération : la méthode qui réalise la rotation des moteurs n’a pas de paramètre

pour le degré de rotation. Donc, on ne peut pas tourner le robot à droite avec 10 degrés ou 20

degrés, mais seulement avec 90 degrés. Cette contrainte nous a poussés à utiliser la libraire

Mindsqualls.

Minsqualls.net a 2 versions: 1.1 et 1.2. La deuxième, même si elle contient des nouvelles

méthodes et attributs, présente un problème technique: avant de réaliser une nouvelle

rotation, le moteur est remis à sa position initiale. Donc, si on veut tourner le robot deux fois à

droite avec 10 degrés, sa nouvelle position n’est pas décalée de la position initiale avec 20

degrés, mais avec 10 degrés, parce qu’avant de tourner pour la deuxième fois à droite, le

moteur est tourné en sens inverse pour arriver à sa position initiale. Ce problème n’est pas

rencontré dans la première version de la libraire.

Donc, le choix final a été la librairie Mindsqualls v1.1.

Outils développés

NDollarKinectPlayer

Cet outil permet de visualiser et créer les fichiers. xml qui seront utilisés par l’implémentation

de l’algorithme $N pour représenter les gestes.

L’application peut être utilisée de deux manières, pour enregistrer un geste à l’aide de Kinect,

ou pour ouvrir, visualiser et modifier un geste existant :

Création d’un geste : Dans le menu « File » on choisit l’option « New… », cela aura pour

effet de lancer Kinect, qui attendra la calibration de l’utilisateur à travers la pose de

calibration, et qui ensuite affichera le squelette sur la fenêtre principale de l’application.

Pour commencer a enregistrer, il faut cliquer sur le bouton « Start », puis effectuer

devant Kinect le geste qu’on veut sauvegarder, et cliquer sur le bouton « Stop » pour la

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 15

fin de l’enregistrement, qui sera suivi de l’apparition d’une fenêtre qui permet la

sauvegarde du geste dans le fichier .xml.

Capture écran de l’outil NDollarKinectPlayer

Visualisation d’un geste existant : Dans le menu « File » on choisit l’option « Open… »

pour ouvrir un fichier .xml déjà existant. Des barres de défilement (des sliders)

permettent la visualisation du geste enregistre ainsi que sa modification, de la façon

suivante :

o Un premier slider nous permet de faire défiler les différentes positions du

squelette pour visualiser le geste pas à pas. Les boutons « Next » et « Previous »

effectuent la même action.

o Deux sliders supplémentaires offrent la possibilité de modifier le geste qui a été

enregistré, en le découpant, pour garder le nombre de pas optimal nécessaire à

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 16

la reconnaissance du geste. Chaque pas d’un slider représente une position du

squelette à un moment donné pendant l’exécution du geste. Pour que le geste

soit mieux reconnu par le plugin NDollar, il est conseillé qu’il contienne 30 à 50

positions de squelette.

MusicApp

Pour montrer une utilisation possible de l’API de gestes Kinect développée, on a créé une

application qui utilise les gestes détectés par l’API pour produire de la musique. Le code de

cette application sera inclus dans l’archive livrable de l’API et va constituer un exemple pour les

développeurs qui veulent utiliser l’API.

Le principe de l’application est le suivant :

Au lancement, Kinect sera connecté à l’application et la fenêtre principale du

programme affichera l’image de profondeur renvoyée par le capteur. Une musique de

fond sera également démarrée.

A partir de ce moment, l’utilisateur qui se trouve devant le capteur doit prendre la pose

de calibration du Kinect, et attendre que le squelette soit affiché sur la fenêtre.

Une fois que le squelette a été détecté, l’utilisateur peut faire des gestes qui chacun

vont contrôler un son additionnel qui sera ajouté à la musique de fond de la manière

suivante :

o La première fois qu’un geste est détecté, il lance un son qui sera ajouté par-

dessus la musique de fond (le son ajouté ne remplace pas la musique existante

ou les autres sons qui sont en train d’être joués, il sera joué en parallèle avec

ceux-ci).

o La deuxième fois que le même geste est détecté, le son lancé la première fois par

le même geste sera arrêté.

Cette utilisation des gestes permettra à l’utilisateur de l’application de créer de la

musique en rajoutant ou en supprimant des sons.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 17

Capture écran de l’outil MusicApp, après la pose de calibration de Kinect

En tant que simple application d’exemple pour l’utilisation de l’API, l’application ne contient pas

d’autres fonctionnalités, et la musique de fond ainsi que les sons rajoutés à l’aide des gestes

sont prédéfinis.

Construction du robot

Pour montrer la fonctionnalité de la libraire de gestes Kinect, on a décidé d’utiliser un robot

Lego Mindstorms NXT 2.0.

Le modèle que nous avons construit s’appelle Shooterbot. Il est composé de :

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 18

1 micro-ordinateur qui est le cerveau du robot. Il gère les commandes données et

provoque l’entrainement des moteurs pour réaliser l’action désirée ;

1 senseur ultrasonique qui aide le robot à détecter les mouvements ;

1 senseur de couleur qui peut détecter les couleurs ou qui peut agir comme une lampe ;

3 moteurs: 2 entraînent les roues et 1 est utilisé pour tirer avec les boules colorées ;

Le robot « Shooterbot »

Le robot peut être connecté à l’ordinateur via Bluetooth en utilisant un port COM.

Bluetooth est une technologie qui permet d'envoyer et de recevoir des données sans utiliser de

câbles. Nous avons utilisé le Bluetooth pour établir une connexion sans fil entre notre

ordinateur et le robot NXT. Le Bluetooth peut être aussi utilisé pour établir une connexion sans

fil NXT à un autre NXT. Nous avons transféré le programme entre notre PC et le robot et avons

contrôlé ce dernier à l’aide de cette technologie.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 19

Les algorithmes utilisés

L’algorithme $1

Le principal défi de l’API que nous avons réalisée a été de déterminer les algorithmes les plus

adaptés dans le cadre de reconnaissance de gestes. En effet dans ce domaine les méthodes

sont nombreuses telles que les réseaux de neurones ou les Hidden Markov Model (HMM). Ces

algorithmes sont très sophistiqués. Néanmoins ils nécessitent un entrainement effectué au

préalable (learning) plusieurs fois sur la même forme voulant être enregistrée. Cela rend ces

types d’algorithmes moins pratiques pour du prototypage d’interface dans lequel l’utilisateur

ou le développeur voudrait définir ses propres formes enregistrables, reconnaissables en un

temps immédiat. De plus ce niveau de sophistication entraine une difficulté tant au niveau

programmation que debug. Le $1 recognizer est à l’inverse simple à implémenter dans

n’importe quel contexte même dans un contexte de prototypage rapide.

Un geste effectué par une personne se définit par un ensemble de points. Ces points sont alors

comparés à un autre ensemble de points préalablement stockés. On devine très rapidement

que la seule comparaison entre chacun de ces points n’est pas suffisante pour déterminer le

meilleur candidat parmi les ensembles de points préenregistrés (templates) i.e. les gestes à

reconnaitre. En effet les variations entre 2 gestes faits par la même personne mais à des

vitesses différentes et/ou un matériel différent ne générera pas le même nombre de points et

de ce fait la comparaison est déjà impossible sur ce seul critère. S’ajoute à cela le problème de

l’orientation et de l’échelle du geste/figure en question et donc les problèmes d’angles qui en

découlent. C’est pour cela que le $1 recognizer a été construit de telle manière à ce qu’il soit

insensible à tous ces types de variations. De plus l’apprentissage (learning) d’un geste n’est

effectué qu’une seule fois i.e. ne nécessite qu’un seul passage pour créer un template

contrairement aux HMM et réseaux de neurones. Il faut aussi noter que le $1 recognizer ne

considère que des mouvements « unistroke » i.e. une seule figure continue formée par un geste

à l’inverse de mouvements « multistroke ». Le $1 recognizer se définit ainsi en quatre étapes.

Les trois premières sont effectuées que cela soit pour créer les templates une première fois ou

pour pouvoir comparer ces derniers à des gestes effectués dans l’immédiat.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 20

Exemple de gestes reconnus par l’algorithme $1

Le ré-échantillonnage

Afin de pouvoir comparer le geste effectué avec les templates préexistants on doit tout d’abord

ré-échantillonner l’ensemble de points (stroke) ainsi créé. On calcule tout d’abord le total de

points M créés par le geste. On divise ce total par N-1 où N ne sera ni trop petit ce qui

provoquerait une perte importante de précision ni trop grand qui entrainerait un nombre de

comparaisons trop important consommant alors du temps. De cette division résulte une valeur

d’incrément I qui représentera la distance entre chaque nouveau point. Ces derniers formeront

l’ensemble de nouveaux points ré-échantillonné sous la forme d’une liste. A la fin de cette

première étape tous les templates pré-chargés ou tous les gestes effectués au temps T courant

ont la même taille N.

La rotation à 0° basée sur l’angle indicatif

Avec maintenant deux ensembles de points ordonnés il n’est pas possible de déterminer à

première vue l’angle de rotation à appliquer sur ces deux ensembles pour qu’ils soient égaux

dans leur orientation. Néanmoins on s’aperçoit d’une solution assez simple. On calcule l’angle

entre le barycentre du geste et le premier point créé par le geste : c’est l’angle indicatif. Ce

dernier est mis à 0°.

La mise à l’échelle et la translation :

Après avoir effectué la rotation le geste est mis à l’échelle par rapport à ce que l’on nomme le

rectangle de référence (reference square ou bounding box). Ce dernier est calculé en prenant

les minimums et maximums en x et y des points. La mise à l’échelle effectuée il ne reste plus

qu’à effectuer une translation du geste où le barycentre est mis à (0, 0).

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 21

Obtenir le meilleur score :

Un premier calcul est effectué afin de trouver et comparer la distance moyenne entre chaque

point du candidat (geste effectué) C et les points de chacun des templates Ti. Cette distance

définit ce que l’on appelle path-distance entre C et les Ti. La path-distance la plus petite des Ti

avec C est convertie en un score exprimé en pourcentage. Ce score est le résultat de la

reconnaissance de gestes.

L’algorithme $N

L’algorithme de $N commence par appliquer toutes les permutations possibles à chaque stroke,

c'est-à-dire regarder toutes les combinaisons possibles des strokes en partant du début ou de la

fin du geste.

Ensuite il génère tous les unistrokes à partir des combinaisons calculées avant, et va appliquer

l’algorithme $1 sur chacun d’entre eux. Cette opération renvoie le pourcentage de « similarité »

calcule pour chaque unistroke, et à la fin, l’algorithme en choisit le meilleur candidat.

Dans notre implémentation de l’algorithme on a choisi de supprimer cette première étape à

cause du nombre trop élevé de combinaisons (32 768, a cause des 15 strokes différentes, une

pour chaque articulation du squelette). Cette étape n’est pas nécessaire dans notre cas,

puisque le squelette est toujours représenté de la même manière et donc les articulations sont

toujours dans le même ordre.

Main ouverte/main fermée

Pendant le développement de l’API, il s’est avéré intéressant d’avoir la possibilité de détecter si

la main de la personne qui se trouve devant le Kinect est ouverte ou fermée. Cette

fonctionnalité pourrait être utilisée pour marquer le début / la fin d’un geste, pour le distinguer

d’autres gestes similaires : par exemple, dans le cas ou la personne veut dessiner un triangle en

utilisant un geste, le fait que sa main est fermée pendant la durée du geste qui dessine la forme

pourrait indiquer au logiciel que la personne est en train de dessiner un symbole et qu’on ne

désire pas la détection d’autres gestes intermédiaires, comme par exemple la main qui va

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 22

horizontalement de droite à gauche pendant le dessin, geste qui ne sera donc pas pris en

compte si la main est fermée.

Pour détecter si la main est ouverte ou fermée, on se base sur l’image de profondeur renvoyée

par Kinect, de la façon suivante :

On applique un filtre sur l’image de profondeur renvoyée par Kinect, pour ne garder que

les éléments les plus proches du capteur : les mains. (Ceci implique le fait que les mains

doivent être plus proches du capteur que le reste du corps, donc ça ne marchera pas

dans le cas où cette contrainte n’est pas respectée, mais grâce à la bonne précision

offerte par Kinect, il est possible de trouver les bons paramètres pour le filtre qu’on

applique sur l’image afin que la distance entre les mains et le reste du corps ne soit pas

grande) ;

Sur l’image obtenue, on détermine le contour de chaque main ;

Pour chaque contour de la main, on calcule son enveloppe convexe ;

On calcule les défauts de convexité sur l’enveloppe convexe trouvée :

o Dans le cas où il y a de grands défauts de convexité, cela signifie que la main est

ouverte, puisque la forme sera concave entre les doigts ;

o Sinon, cela veut dire que la main est fermée.

Calcul de l’enveloppe convexe à partir de l’image de profondeur de la main

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 23

Programmation de l’API

Description de l’API

Notre API se base sur le code fourni par OpenNi, qui est le driver officiel pour l’utilisation de

Kinect sur un ordinateur. Cette API est écrite en C# et elle est destinée a une utilisation avec

WPF, la nouvelle manière de Microsoft pour faire les IHM qui remplace l’ancienne, les Forms.

Les classes de l’API

Context

Toute notre API commence par la classe « Context », c’est celle-là qui permet de récupérer les

images vues par Kinect. Ces images sont renvoyées sous la forme d’un « ImageSource », ce qui

permet un affichage facile en WPF. Les images ont une résolution de 640 x 480 mais il est facile

de faire des miniatures de ces images avec WPF : en créant une image plus petite, WPF se

chargera d’adapter l’image à la taille qu’il doit afficher. Ce « Context » peut aussi lire un fichier

.oni qui contient un enregistrement de ce qui est capté par Kinect, et donc peut fonctionner

sans avoir besoin de la connexion du capteur à l’ordinateur, en agissant comme une simulation

de ce dernier.

De plus, en utilisant la classe « UserGenerator » de OpenNi qui permet de récupérer les pixels

composant l’image d’un utilisateur détectée par Kinect, on peut juste représenter l’utilisateur

sans dessiner l’environnement qui l’entoure.

HandTracking

Le « HandTracking » est une classe qui hérite de « Context ». Cette classe apporte la détection

de la main de l’utilisateur fournie par OpenNi. Cette détection commence au moment où

l’utilisateur fait un geste avec sa main, le « Wave » qui consiste à bouger la main à droite et à

gauche plusieurs fois devant Kinect. Au moment où la main est détectée, la classe va générer

des évènements pour donner les coordonnées X, Y et Z de la main.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 24

Cette classe utilise le « GestureGenerator » de OpenNi qui permet de détecter un geste. On ajoute donc le geste « Wave » au « GestureGenerator » qui va générer un événement « GestureRecognized ». Quand cet événement est généré, on commence le suivi de la main à partir de la classe « HandsGenerator » fournie aussi par OpenNi, générant ainsi à chaque nouvelle image fournie par Kinect l’événement « HandUpdate » qui nous donne les coordonnées de la main. On génère donc notre événement avec juste ces coordonnées.

BodyTracking

Le « BodyTracking » est une classe qui hérite aussi de « Context ». Cette classe va permettre de

fournir de manière plus aisée les coordonnées des 15 articulations de l’utilisateur repéré par

Kinect. Pour démarrer la détection il faut commencer par faire une pose. Une fois cette pose

détectée, l’API commence à générer des événements avec les coordonnées de l’utilisateur.

Cette classe va utiliser aussi « SkeletonCapability » et « PoseDetectionCapability » de OpenNi qui permettent respectivement de récupérer les coordonnées du squelette (les 15 articulations), et de détecter la pose de calibration du Kinect. Dans cette classe on va maintenir une liste de tous les utilisateurs calibrés avec un identifiant et les coordonnées de chacune de leurs articulations. Cette liste sera mise à jour à chaque nouvelle image et générera un événement qui contiendra cette liste.

BodyGestureGenerator

Cette classe va permettre de générer des événements lorsque qu’un geste sera reconnu à partir

du squelette fourni par le « BodyTracking ». Nous avons choisis que la reconnaissance des

gestes allait être effectuée sous la forme de plugins. C’est donc le plugin qui va reconnaitre un

geste et générer l’événement.

Chaque plugin devra implémenter l’interface « Gesture », qui doit avoir trois événements

« Start », « End » et « Recognised ». De plus il doit avoir un constructeur vide, une méthode

« getName() » et une méthode « construct() ». On détaillera la raison de ces contraintes plus

loin dans ce document.

Le « BodyGestureGenerator » va garder une liste de tous les plugins qui ont été ajoutés. Pour

ajouter un plugin, la classe a besoin de son nom. Elle va donc :

chercher dans le dossier des plugins (par défaut dans le dossier « plugins » situé a la

racine du projet)

lire tous les fichiers .dll (qui représentent les versions compilées des plugins)

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 25

construire toutes les classes qui implémentent l’interface « Gesture »

appeler la fonction « getName() » pour voir si c’est le bon plugin, et dans le cas ou le

nom correspond alors la classe appelle la méthode « construct() » du plugin, sinon le

Garbage Collector va supprimer le plugin créé. C’est pour cette raison qu’on a besoin du

constructeur vide dans le plugin.

De plus, on peut passer en argument un tableau d’objets au moment d’ajouter un plugin à la

méthode « construct ». Cette méthode maintient un tableau de trois objets :

le premier correspond au « BodyTracker »

le second correspond au « BodyGestureGenerator »

le dernier correspond au tableau d’arguments passé en paramètre au moment de l’ajout

du plugin.

Lorsque l’un des trois événements de « Gesture » est généré par un plugin, il est récupéré par

le « BodyGesturegenerator », qui génère un nouvel événement avec le nom du plugin qui l’a

généré et les arguments associés.

EventArgs

Pour l’implémentation du pattern Plugin, nous avons créés trois classes qui décrivent les

arguments des événements :

UsersEventArgs

Possède une liste des squelettes des utilisateurs calibrés. Le squelette est la

classe « UserSkeleton » qui possède un ID (commence à 1 pour le premier

utilisateur détecté) et 15 éléments « Point3D » (classe de OpenNi) qui

correspondent à chacune des articulations.

Les 15 articulations du squelette sont:

Head Neck LeftShoulder LeftElbow LeftHand RightShoulder RightElbow

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 26

RightHand Torso LeftKnee LeftHip LeftFoot RightKnee RightHip RightFoot

PositionEventArgs

Argument envoyé pour les évènements du « HandTracker ». Possède l’Id de

l’utilisateur qui a généré l’évènement et les coordonnées de la main.

GestureEventArgs

Argument renvoyé pour les évènements du « BodyGestureGenerator ». Possède

le nom du geste qui a généré l’évènement et un tableau d’objets qui correspond

aux arguments que le plugin veut envoyer. C’est un tableau d’objets puisqu’on

ne peut pas prédire les types renvoyés par un plugin.

Les plugins

Pour détecter les gestes, on a développé trois plugins différents, en fonction de l’algorithme

utilisé pour la détection :

Le plugin Dollar

Ce plugin, qui utilise une implémentation (voir Annexes, [1]) de l’algorithme $1 décrit dans ce

document, prend en paramètre les gestes que l’on veut reconnaitre avec l’algorithme

(représentés par des fichiers .xml) à partir d’un tableau de String. Ces gestes se trouvent dans

un répertoire « xml » dans le répertoire « plugin » et on ne chargera que les gestes dont

l’application a besoin. Dans le cas où on choisit de charger tous les gestes, il suffit de remplacer

le paramètre du constructeur du plugin par « All ».

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 27

Pour détecter un geste, cette classe conservera une liste des dernières coordonnées de la main

droite de chaque utilisateur détecté en récupérant l’évènement « UsersUpdated » du

BodyTracker qui lui est passé en paramètre. On va donc garder une liste des 70 derniers points

(qui peut être modifiée par un paramètre à la construction). Cette liste sera mise à jour à

chaque nouvel évènement, et si la liste d’un utilisateur est pleine alors on passe cette liste de

points à l’algorithme « Dollar » qui va nous donner le geste, parmi ceux qu’on veut reconnaitre,

qui ressemble le plus a cette liste. On considère qu’un geste a été bien fait s’il dépasse un Score

de 0.85 (fourni par Dollar, le score est compris entre 0 et 1, où 1 est l’identique liste à celle de

comparaison i.e. le template). Si on a un bon geste alors on vide la liste pour que le même geste

ne revienne pas à l’évènement suivant (il n’y aura qu’un nouveau point donc c’est fortement

probable) et on génère l’évènement « Recognised » avec un « GestureEventArgs » qui a le nom

du geste reconnu ainsi que dans le tableau des arguments on mettra, l’ID de l’utilisateur qui a

fait le geste ainsi que son score.

Le plugin Ndollar

Ce plugin, qui utilise une implémentation (voir Annexes, *2+) de l’algorithme $N, est très

similaire au plugin « Dollar » car il utilise la version « Multistroke » de l’algorithme $N. La

différence vient du fait que l’on va devoir garder une liste des dernières coordonnées de

chaque articulation de chaque utilisateur. De plus on accepte un geste s’il a un score de 0.75 à

cause du fait qu’avec autant de « Stroke » (chaque articulation est un « Stroke » de Dollar) il est

plus difficile de faire un bon score (et en plus le capteur Kinect ne donne pas des coordonnées

parfaites).

Les réglages sont plus compliqués à faire dans ce plugin (taille de liste de 50 points par défaut)

car si on augmente le score il détectera moins bien les gestes mais si on le diminue (ou

augmente la taille de la liste), on a plus de chance d’avoir un faux positif.

L’évènement généré sera le même que celui de Dollar.

Pour les besoins de ce plugin nous avons développé un outil pour créer les fichiers xml qui

serviront à la reconnaissance des gestes. Nous en parlerons plus tard.

Ce plugin nécessite en plus un dossier « conf » à la racine du projet (même lieu que plugins). Ce

dossier doit contenir deux fichiers xml « config.xml » et « config-onedollar.xml ». Ces fichiers

seront fournis avec le plugin. De plus, dans le dossier « plugins » où l’on a mis le dll du plugin

NDollar, nous devons ajouter un dossier nommé « xml$N », ce dossier devra contenir des

dossiers où sont mis les xml (les noms des dossiers importe peu, c’est pour pouvoir les ranger, il

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 28

peut y en avoir qu’un seul). Dans ses dossiers, il y aura donc les fichiers xml des gestes que

NDollar pourra charger.

Le plugin Volant

Ce plugin va permettre de simuler le fait d’avoir un volant avec Kinect. Le plugin Volant va

commencer par détecter si les deux avant-bras de l’utilisateur sont parallèles. Si c’est le cas

alors il lance un Timer d’une seconde qui s’il arrive à la fin générera alors un évènement Start.

Par contre si les deux avant-bras ne sont plus parallèles avant la fin du Timer alors on l’arrête et

il sera relancé en refaisant la pose. Ce Timer permet de ne pas faire le geste volant par accident

car on regarde le geste à chaque nouvel évènement de « UsersUpdated ».

Pour finir le geste volant, il faut écarter les bras (on regarde la différence de distance entre les

mains et les coudes et si elle est assez grande alors on a fini le geste volant). Ici aussi on va

utiliser un Timer mais de 0.2 secondes pour éviter une sortie du volant non voulue. On génèrera

un évènement « End » à la fin du Timer s’il n’a pas été interrompu car les bras se sont

rapprochés.

Quand la position d’entrée en volant a été reconnue, on va calculer l’angle entre les deux mains

par rapport à l’horizontal de la main gauche. On aura donc un angle positif si la main droite est

au dessus de la main gauche ce qui correspond à un virage vers la gauche, et négatif si la main

droite est en dessous de la main gauche ce qui est donc un virage à droite.

On génèrera donc un évènement « Recognised » avec en premier paramètre du tableau

d’argument l’Id de l’utilisateur et en second l’angle du volant.

L’utilisation de l’API

Pour utiliser notre API, les références suivantes doivent être rajoutées au projet :

KinectAPI.dll, qui contient le code de l’API de reconnaissance de gestes ;

OpenNi.net.dll, qui contient l’API de base fourni par OpenNI ;

Le fichier SamplesConfig.xml, qui est le fichier de configuration pour utiliser Kinect, doit être

ajoute dans le répertoire /bin/debug du projet.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 29

La liaison avec l’API se fait explicitement à l’aide du code suivant :

using KinectAPi ;

Puisque l’initialisation de Kinect est une opération couteuse en termes de temps, elle doit être

effectuée au moment de l’initialisation de l’application :

Le même conseil devra être suivi pour les classes « HandTracker » et « KinectAPIContext ».

Pour afficher l’image de Kinect en WPF, il faut utiliser un worker déclaré à l’initialisation aussi :

Le code des handlers pour les événements déclarés est le suivant :

// Le thread de rendu graphique CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering); // Le worker BackgroundWorker _bgWorker = new BackgroundWorker(); _bgWorker.DoWork += new DoWorkEventHandler(Worker_DoWork);

// Avec Kinect BodyTracker _skeleton = new BodyTracker(); OU // Pour utiliser un autre fichier de configuration que celui par defaut pour Kinect BodyTracker _skeleton = new BodyTracker(@"PathToFile\SamplesConfig.xml”); OU // Avec la video qui remplace le capteur Kinect BodyTracker _skeleton = new BodyTracker(@"PathToFile\VideoKinect.oni”);

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 30

L’image captée par la camera RGB de Kinect se trouve dans _skeleton.RawImage, et l’image

captée par la camera de profondeur se trouve dans _skeleton.DepthImage.

Pour capturer les événements lancés par les classes « BodyTracker » et « HandTracker », qui

signalent les modifications dans la position du squelette / dans la position de la main, il faut

déclarer des handlers spécifiques, de la manière suivante :

A l’intérieur des handlers, on peut récupérer les coordonnées du squelette / de la main :

// BodyTracker _skeleton.UsersUpdated += new BodyTracker.UsersUpdatedHandler(Users_Updated); // HandTracker _handTracker.HandPosition += new HandTracker.HandPositionHandler(HandPosition_Updated);

void CompositionTarget_Rendering(object sender, EventArgs e) {

if (!_bgWorker.IsBusy) {

_bgWorker.RunWorkerAsync(); }

} void Worker_DoWork(object sender, DoWorkEventArgs e) { // Car le worker n’a pas le droit d’accéder aux elements de l’IHM

Dispatcher.BeginInvoke((Action)delegate { // Les images declarees dans le xaml (le fichier qui décrit l’IHM)

imgCamera.Source = _skeleton.RawImage; imgDepth.Source = _skeleton.DepthImage;

}); }

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 31

Pour ajouter les plugins nécessaires à la détection des gestes, on crée une nouvelle instance de

la classe « BodyGestureGenerator », on rajoute dans sa liste de plugins les noms des plugins

qu’on veut utiliser, et on déclare les handlers pour les événements qui décrivent la

reconnaissance d’un geste :

Comme notre API est basée sur le mécanisme de Plugins et comme on ne peut pas savoir à l’

avance le type des plugins qui vont être utilisés par l’application qui intègre l’API, une solution

simple est le switch/case sur le nom des plugins pour différencier les gestes reconnus :

// Déclaration BodyGestureGenerator _gestureGenerator = new BodyGestureGenerator(_skeleton); // Ajout des plugins _gestureGenerator.Add("Volant"); _gestureGenerator.Add("NDollar", new string[] { "LeftHi5", "RightHi5" }); // Déclaration des Handlers _gestureGenerator.Recognised += new

BodyGestureGenerator.GestureRecognisedHandler(_gestureGenerator_Recognised); _gestureGenerator.Start += new

BodyGestureGenerator.GestureStartHandler(_gestureGenerator_Start); _gestureGenerator.End += new

BodyGestureGenerator.GestureEndHandler(_gestureGenerator_End);

void Users_Updated(object sender, UsersEventArgs e) {

foreach (var user in e.users) {

float headX = user.Head.X; float headY = user.Head.Y; float headZ = user.Head.Z; …

} } void HandPosition_Updated(object sender, PositionEventArgs e) { float X = e.X; … }

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 32

Programmation du robot

Le code

Afin d'utiliser le robot, il faut d'abord le connecter à l’ordinateur via Bluetooth. Le port

Bluetooth est un paramètre qui doit être réglé dans l'interface utilisateur, car il peut être

différent d'un ordinateur à un autre. Une fois qu’on connait le port, il faut suivre les étapes

suivantes pour établir une connexion:

1. On crée une instance de l'unité centrale du robot :

nxt = new NxtBrick(port);

2. On crée les instances des moteurs :

nxt.MotorB = new NxtMotor() nxt.MotorC = new NxtMotor(); nxt.MotorA = new NxtMotor();

3. On synchronise les moteurs qui entrainent les roues pour qu’ils tournent en même

temps :

motorPair = new NxtMotorSync(nxt.MotorB, nxt.MotorC);

4. On crée les instances des senseurs qu’on veut utiliser, dans notre cas, les Senseur

Ultrasonic :

void _gestureGenerator_Recognised(string gesture, object[] args) {

switch (gesture) {

case "Volant": … break;

case "LeftHi5": … break;

} }

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 33

nxt.Sensor4 = new NxtUltrasonicSensor();

5. On réalise la connexion à l'unité centrale du robot :

nxt.Connect();

Une fois qu’on est connecté au robot on peut faire les prochaines actions:

a. Aller en avant

motorPair.Run((sbyte)power, 0, 0);

La méthode Run reçoit comme paramètres:

power : la puissance avec laquelle les moteurs synchronisés vont tourner. Pour

aller en avant, il faut que la puissance soit positive ;

tacho limit : le degré de rotation des moteurs (dans ce cas, 0 signifie que les

moteurs vont tourner à l’infini) ;

turn ratio: détermine la direction du robot (à gauche, à droite, tout droit) ;

b. Aller en arrière

On utilise la même méthode comme pour l’action “aller en avant”, mais cette fois la

puissance doit être négative.

c. Tourner à droite

motorPair.Run((sbyte)power, 0, turn);

On utilise la même méthode comme ci-dessus, mais cette fois on doit indiquer la

direction du robot. Le paramètre turn doit être plus grand que 0 pour que le robot

tourne à droite.

d. Tourner à gauche

C’est similaire avec l’action de tourner à droite. La seule différence est la valeur du

paramètre turn, qui doit être plus petite que 0.

e. Idle

Cette action met les moteurs synchronises dans un état inactif :

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 34

motorPair.Idle();

f. Break

C’est l’action qui réduit la puissance des moteurs synchronisés à 0 :

motorPair.Brake();

g. Tirer avec des balles colorées

Cette fois on n’utilise pas les moteurs synchronisés, mais le troisième moteur qui est

utilisé pour des actions auxiliaires, dans notre cas, le tir des balles colorées :

nxt.MotorA.Run(power, degree);

La méthode Run utilisée pour un seul moteur n’a pas le paramètre turn ratio. Donc on

peut indiquer seulement la puissance du moteur et le degré de rotation.

h. Augmenter la puissance des moteurs synchronisés

i. Diminuer la puissance des moteurs synchronisés

j. Signaler a l’utilisateur quand le robot est proche d’un obstacle

Si le robot détecte un obstacle, à l’aide de son Senseur Ultrasonic il va le signaler à

l’utilisateur via un message sur l’interface graphique et diminuera la puissance des

moteurs synchronisés pour donner à l’utilisateur le temps de penser à une action afin

d’éviter l’obstacle.

Pour fermer la connexion Bluetooth du robot on doit utiliser la méthode suivante :

nxt.Disconnect();

Le contrôle du robot

On a implémenté trois moyens pour contrôler le robot:

Des boutons

Des touches

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 35

Kinect

Dans l’interface graphique il existe des boutons qui implémentent presque toutes les

fonctionnalités du robot.

L’association des gestes détectés par l’API aux actions du robot

Certains gestes qui sont reconnus par le Kinect sont interprétés par le robot. En conséquence

quand un geste est reconnu il est transmis au robot qui effectue une certaine action.

Les gestes sont qui sont interprétés sont:

Hi5 avec la main gauche. Quand le Kinect détecte ce geste le robot commence à se

déplacer tout droit. Ce geste réalise une action permanente: une fois que le geste est

détecté par le Kinect et interprété par le robot, il se déplace jusqu'au moment où le

geste d’arrêt stop ou celui qui commande la marche arrière soit détecté.

Demi-cercle avec la main droite. La direction du demi-cercle doit être de droite à

gauche. Quand le Kinect détecte ce geste le robot commence à se déplacer vers la

droite. La direction de déplacement (marche avant/marche arrière) ne change pas, cela

signifie que dans le cas où le robot se déplaçait déjà vers l’avant, il bougera vers la droite

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 36

et continuera d’aller vers l’avant, et dans le cas où le robot se déplaçait déjà en marche

arrière il bougera vers la droite et continuera d’aller en marche arrière. Chaque fois que

ce geste est détecté le robot bouge avec 10 degrés à droite en fonction de la position

précédente. Ce geste ne détermine pas une action permanente: quand le geste est

détecté, le robot bouge vers la droite avec 10 degrés une seule fois. Si on veut faire

tourner le robot plusieurs gestes de ce type sont nécessaires.

Demi-cercle avec la main gauche. La direction du demi-cercle doit être de gauche à

droite. Quand le Kinect détecte ce geste le robot commence à se déplacer vers la

gauche. La direction de déplacement (marche avant/marche arrière) ne change pas, cela

veut dire que dans le cas où le robot se déplaçait déjà vers l’avant, il bougera vers la

gauche et continuera d’aller vers l’avant, et dans le cas où le robot se déplaçait déjà en

marche arrière il bougera vers la gauche et continuera d’aller en marche arrière. Chaque

fois que ce geste est détecté le robot bouge avec 10 degrés à gauche en fonction de la

position précédente. Ce geste ne détermine pas une action permanente: quand le geste

est détecté, le robot bouge vers la gauche avec 10 degrés une seule fois. Si on veut faire

tourner le robot plusieurs gestes de ce type sont nécessaires.

Bouger la main droite de droite vers le gauche. Quand le Kinect détecte ce geste le

robot lance une balle colorée. Ce geste ne détermine pas une action permanente:

quand le geste est détecté, le robot lance une seule balle, et ce geste n'a aucune

influence sur la direction de déplacement du robot.

Les deux mains devant le corps. Quand le Kinect détecte ce geste le robot s'arrête. Ce

geste réalise une action permanente: une fois que le geste est détecté par Kinect et

interprété par le robot, il n'effectuera plus aucune autre action jusqu'au moment où un

autre geste soit détecté.

Les deux mains vers le haut. Quand le Kinect détecte ce geste le robot commence à

bouger en marche arrière. Ce geste réalise une action permanente: une fois que le geste

est détecté par Kinect et interprété par le robot, celui-ci se déplace jusqu'au moment où

le geste d’arrêt ou celui qui commande la marche en avant soit détecté.

Pour une description en détail des gestes décrits précédemment ainsi que des images de

chaque geste, référez-vous à la section [Annexes] de ce document.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 37

Organisation de l’équipe

Découpage des tâches

Lors de l'élaboration du cahier des charges et de la réflexion préliminaire au projet, le travail à

effectuer a été découpé en différentes tâches indépendantes les unes des autres.

Ce découpage a été respecté, et nous a permis de bien évaluer l'avancement de notre travail et

de bien répartir les tâches entre les membres de l'équipe.

Avant le début du travail on a créé un diagramme de Gantt pour visualiser les différentes

parties qui composent le projet ainsi que les durées affectées à chacune d’entre elles :

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 38

Cette distribution des tâches a été bien respectée, et leur durée a été assez bien calculée. A la

fin du projet on a obtenu le diagramme de Gantt suivant qui montre les affectations et les

durées réelles :

Certaines tâches nous ont pris plus de temps que prévu initialement, tandis que d’autres ont

été finies plus tôt, donc dans l’ensemble on peut considérer qu’on a réussi à avoir une

distribution uniforme du travail.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 39

Estimation du travail réalisé

Romain BardiauDocumentation sur la technologie

Programmation API - squelette API

Integration pattern Plugin

Programmation API - $1

Programmation API - $N

Programmation API - Creation gestes

Programmation API - Outil visualisation gestes

Anamaria Craciun

Construction Robot

Documentation sur la technologie

Programmation Robot

Integration Robot avec Kinect API

Redaction de la documentation

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 40

Dora Daniluc

Construction Robot

Documentation sur la technologie

Programmation Robot

Interface graphique

Redaction de la documentation

Alexandra Savu

Documentation sur la technologie

Programmation API - squelette API

Programmation API - $N

Programmation API - Creation gestes

Programmation MusicApp

Redaction de la documentation

Bilal Souti

Documentation sur la technologie

Recherche algorithmes des gestes

Programmation API - Gestes 1ere version

Programmation API - Main ouverte/fermeeRedaction de la documentation

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 41

Bilan

L’API Kinect

La plus grande difficulté pendant le développement de l’API a été le fait de réussir à

implémenter les gestes de manière à ce que leur détection ne se superpose pas. Pour les

gestes créés à l’aide de l’algorithme $1 ceci a été plus facile, puisque les formes dessinées par

les gestes (cercle, triangle, rectangle) sont assez différentes et donc leur détection donne

rarement des faux positifs (ca n’arrive que rarement qu’un geste qui dessine un cercle soit

détecté en tant que geste qui dessinait un triangle par exemple, et ceci juste dans les cas où

l’utilisateur ne fait pas un geste complet ou assez bien défini pour que la détection se fasse

d’une manière correcte).

Une contrainte qu’on a rencontrée pendant le développement a été celle de la vitesse de

calcul. Certains algorithmes nécessitent beaucoup de calcul et c’est pour ca qu’en fonction de la

puissance de l’ordinateur sur lequel l’application qui utilise l’API est exécutée, la détection de

certains gestes peut prendre plus ou moins de temps. C’est pour ca qu’une prochaine version

de l’API devrait se concentrer sur l’optimisation de la détection des gestes pour baisser le

temps de calcul et donc de réponse des applications aux gestes effectués.

Cette dernière contrainte nous a obligés de laisser de côté une des fonctionnalités prévues pour

l’API : la détection de la main ouverte ou fermée. A cause des algorithmes utilisés pour

effectuer cette détection ainsi qu’à cause du temps de calcul nécessaire à l’application des

filtres sur l’image renvoyée par Kinect, le fait de déterminer si la main est ouverte ou fermée ne

peut pas se faire en même temps que la détection des gestes. Ceci a influencé aussi la manière

dont on reconnait certains gestes et nous a obligés à changer de perspective en ce qui concerne

la construction des gestes. Avant de remarquer cette contrainte technique, on avait prévu de

créer des gestes dont le début et la fin seraient marqués par le fait que l’utilisateur ouvre et

ferme la main. Ceci aurait peut être permis d’avoir des gestes plus complexes et ça aurait

certainement baissé le nombre de faux positifs.

Une autre difficulté rencontrée a été celle des faux positifs pour la détection des gestes en

utilisant l’algorithme $N. Puisque cet algorithme se base sur tous les 15 joints du squelette

pour faire la détection d’un geste ainsi que sur un pourcentage de « similarité » entre le geste

exécuté par l’utilisateur devant Kinect et les fichiers .xml qui décrivent les gestes reconnus par

l’API, il y a souvent des faux positifs au moment de la reconnaissance de certains gestes qui ne

différent que de très peu par rapport à un autre geste. Ceci nous a contraints à ne pas inclure

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 42

certains gestes dans cette distribution de notre API (comme par exemple les gestes faits avec

les jambes, comme les coups de pied par exemple), et de prévoir des recherches plus

approfondies sur ce sujet pour une version ultérieure.

Le robot

Le plus grand problème en ce qui concerne les librairies C# pour le contrôle des robots Lego

Mindstorms NXT 2.0 est celle de la documentation. Dans certains cas, la documentation

n’existe pas, et dans d’autres, elle est très vague. Par exemple, pour la méthode Run de la

classe NxtMotor, la page de documentation contient les informations suivantes:

Run the motor : Syntax: public void Run ( sbyte power, uint tachoLimit) Parameters : power (SByte): The power for the motor tachoLimit (UInt32): The duration in degrees, 0 = unlimited

Même si l’utilisation du Run est assez intuitive, ce n’est pas le cas de toutes les autres

méthodes comme: Poll, Coast. Les auteurs n’expliquent pas les significations contextuelles de

certains termes. Cela nous a donné des difficultés à comprendre la fonctionnalité des certaines

méthodes.

Pour résoudre ce problème nous avons étudié les exemples fournis par les auteurs pour

déduire les significations des méthodes.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 43

Conclusion

Des deux mois qu’on a passé pour le développement de ce projet de TER nous ont permis de

mieux comprendre la quantité et la structure du travail nécessaires pour un projet de recherche

dans un domaine qui au début ne nous était pas familier. Nous avons dû faire de nombreux

choix tout au long de ce projet à cause des nombreux domaines auxquels touche ce projet. Cela

nous a aidé à comprendre le déroulement d’un grand projet, aussi bien sur les aspects

techniques en découvrant des nouveaux algorithmes pour l’informatique ambiante, que sur les

aspects d'organisation puisque nous avons du nous organiser pour mettre en œuvre une

infrastructure logicielle importante.

Dans le cas où des personnes s’intéresseraient à notre API Kinect ou à l’application du robot

LEGO qui utilise l’API, on envisage de continuer ce projet pendant les mois à venir afin de

l’améliorer encore.

Compétences acquises non étudiées en classe

Pendant la période qu’on a travaillé sur ce projet, on a eu l’occasion de découvrir des nouvelles

technologies (Kinect, le robot LEGO), on a appris un nouveau langage de programmation (C#),

avec l’environnement de programmation Visual Studio qu’on n’avait pas encore eu l’occasion

de voir pendant les cours, et ça nous a surtout permis d’avoir un premier aperçu de ce qui

implique le développement d’un projet d’envergure dans le cadre d’une équipe.

Bilan personnel

Bardiau Romain

Ce projet a été une expérience grâce à ce qu'il m'a appris mais aussi à la mise en place des

solutions vues en cours cette année. J'ai pu appliquer le pattern "Plugin" dans un cadre autre

qu'un exercice de cours. J'ai découvert de nouveaux algorithmes dans le domaine de la

reconnaissance gestuelle et du traitement d'images. De plus, j'ai rencontré la difficulté de

devoir faire une application qui réagit en temps réel. Enfin j'ai découvert le langage C# (et .NET)

et l'environnement Visual Studio que je n'avais jamais utilisé. Ces expériences m'ont enrichi en

tant que futur informaticien.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 44

Craciun Anamaria

Ce projet m’a donné l’occasion de travailler avec des technologies et des utiles que je n’ai

jamais utilisé ou que je les ai peu utilisé. Un tel exemple est le langage C# et l’environnent

Visual Studio. J’ai découvert que le C# n’est pas assez différent du langage Java est va surement

être un bon choix pour les futures projets. En ce qui concerne l’environnent de programmation,

il est beaucoup plus complexe qu’Eclipse, mais il est bien organisé et pas trop difficile a

apprendre. Aussi, une autre nouveauté a été le travail avec le robot Lego. C’est la première fois

que j’ai eu l’occasion de construire et de programmer un tel robot et je pense que c’était un

expérience très intéressante. Je suis également contente d'avoir travaillé dans une équipe avec

des membres tres compétents et tres passionnes par la technologie.

Daniluc Dora

Ce TER a été mon deuxième grand projet. Pour le premier projet j'ai travaillé seule mais pour ce

projet j'ai eu l'avantage de travailler dans une équipe tres bien organisé et sérieuse. Moi, j'ai

travaillé pour la partie robot du projet. Pendant le projet j'ai enrichi mes connaissances de

programmation en particulier les connaissances de C#. En conclusion, ce projet a été une

expérience inoubliable pour moi.

Savu Alexandra

Ce fût un réel plaisir de travailler sur ce projet, pour de multiples raisons. La principale étant

surement le fait qu’on a eu l’occasion de travailler avec la toute nouvelle technologie qui est le

capteur Kinect, et qu’on a pu le faire dans un contexte académique. La possibilité de participer

a un projet qui combine la robotique avec des sujets de domotique m’a également fait plaisir.

Je suis très fière du travail réalisé par notre équipe et je garderai un excellent souvenir de cette

expérience très enrichissante.

Souti Bilal

Affirmer que ce projet m'a énormément apporté dans mon cursus serait perçu comme un

cliché. Néanmoins, c'est celui qui a été le plus considérable parmi tous les projets personnels

et/ou universitaires tant en terme de temps que d'apprentissage. En effet cela aura été la

première fois que je passe autant de temps à rechercher les méthodes préexistantes dans le

domaine de la reconnaissance de gestes. J'ai pu alors découvrir des domaines dont je ne

connaissais quasiment rien tel que le traitement de l'image et la reconnaissance de formes.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 45

C'est pour moi le bénéfice principal de ce TER: rechercher l'existant et partir de ce dernier pour

former sa propre conception du problème à résoudre et des solutions qui peuvent être

apportées.

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 46

Annexes

Références

Baudel, T. & Beaudoin Lafon, M. [1993] « Charade : Remote control of objects using free hand

gestures » Communications of ACM 36(7), pages 28-35, Juin.

Kurtenbach and Hulteen (1990) Chapter 14: GESTURE BASED INTERACTION

http://www.billbuxton.com/input14.Gesture.pdf

Les pages Wikipedia sur Kinect

http://en.wikipedia.org/wiki/Kinect

http://fr.wikipedia.org/wiki/Kinect

Le site internet de la librairie NXT.Net

http://nxtnet.codeplex.com/

Le site internet de la librairie Aforge.Net

http://www.aforgenet.com/

Le site internet de la librairie Mindsqualls

http://www.mindsqualls.net/Documentation.aspx

La page officiele du robot LEGO Mindstorms

http://mindstorms.lego.com/en-us/Default.aspx

La page des algorithmes

http://en.wikipedia.org/wiki/Hidden_Markov_model

http://en.wikipedia.org/wiki/Artificial_neural_network

http://faculty.washington.edu/wobbrock/pubs/gi-10.2.pdf

L’implémentation de l’algorithme $1 qu’on a utilisé dans ce projet

[1] http://depts.washington.edu/aimgroup/proj/dollar/

L’implémentation de l’algorithme $N qu’on a utilisé dans ce projet

[2] http://depts.washington.edu/aimgroup/proj/dollar/ndollar.html

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 47

Liste des gestes reconnus par le plugin Dollar

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 48

Liste des gestes reconnus par le plugin NDollar

Jump

RightHand-RightToLeft

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 49

RightHand-LeftToRight

RightHand-DownToUp

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 50

RightHand-UpToDown

LeftHand-RightToLeft

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 51

LeftHand-LeftToRight

LeftHand-DownToUp

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 52

LeftHand-UpToDown

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 53

Liste des poses reconnues par le plugin NDollar

HumanT

LeftHi5

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 54

RightHi5

DoubleHi5

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 55

LeftPause

RightPause

Développement d'une API de reconnaissance de gestes pour le capteur Kinect 56

Wait