Détection de squelette sur Kinect

Par laurent Rebuffie

Cette activité permet d’expliquer comment un capteur de type Kinect (console X box) permet de lire les mouvements d’un ou de plusieurs joueurs ?  On affichera progressivement l’image RGB que restitue la Kinect, puis l’image de profondeur délivrée par la caméra infra rouge et enfin le squelette des joueurs.

capteurs Kinect

 

Elle vise à permettre à l’enseignant d’ISN ou d’ICN de comprendre les étapes de programmation pour communiquer avec le capteur Kinect. On peut s’en servir pour montrer les possibilités du traitement de l’image (reconnaissance de silhouettes, de squelette …) ou comme brique de base pour un projet avec les meilleurs élèves d’ISN (ajouter un ballon virtuel sur la main du joueur …).

Matériel:

  • une Kinect de première génération (référence 1414 sous le pied) 30 euros d’occasion
  • un bloc d’alimentation car le port USB standard  d’un ordinateur ne délivre pas assez de courant 8 euros sur le web

La librairie utilisée est simpleOpenNI (par Max Rheiner)

Cette activité fait appel à la Programmation Orientée Objet Java sous Processing. Elle nécessite donc des notions de programmation objet: instanciation, utilisation d’une méthode.

/* Ce premier programme permet de vérifier la communication avec la Kinect
par l’intermédiaire du driver Microsoft Kinect for Windows  à installer avant connexion.
en utilisant la librairie SimpleOpenNI sous Processing 2 (à importer)

verif_install_kinect_PROF.pde
Laurent Rebuffie août 2016
*/

// 1_importer la librairie SimpleOpenNI qui doit être préalablement copiée dans
// C:\Users\nomSessionWindows\Documents\Processing\libraries

import SimpleOpenNI.*;

// 2_ créer un objet context de la classe SimpleOpenNI

SimpleOpenNI contexte;

// Exécuté une fois au lancement de l’application
void setup()
{
// dimensions de la fenêtre sous Processing
size(640 , 480);

// 3_ instancier contexte l’instance de la classe SimpleOpenNI
// –> Voir les différents constructeurs. « processing.core.PApplet parent »
// correspond à l’Applet Java lancée que l’on peut remplacer par le mot clé this
contexte = new SimpleOpenNI(0,this);

// 4_ vérification de la communication avec la Kinect
// la classe SimpleOpenNI hérite des méthodes de l’interface SimpleOpenNI.ContextWrapper
//utilisez la méthode isInit() pour savoir si la Kinect est correctement connectée (driver …)
if(contexte.isInit() == false)
{
println(« Impossible de communiquer avec la Kinect »);
exit(); // sortie du programme GC …
return;
}

else {
// 5_ valider le contexte visu caméra RGB en utilisant la méthode enableRGB
contexte.enableRGB();
}
}

// En boucle dans Processing
void draw()
{
// 6_ mise à jour du contexte en utilisant la méthode update
contexte.update();
/*
// 7_ affichage d’une image dans la fenêtre de l’appli Processing
img = loadImage(« Manchots.jpg »);
image(img,0,0);
*/

// 7_ affichage des collections d’images renvoyées par la méthode rgbImage du contexte
image(contexte.rgbImage(),0,0);

}

 

 

 

/* Ce deuxième programme permet d’afficher un squelette détecté par une Kinect 1414
par l’intermédiaire du driver Microsoft Kinect for Windows  à installer avant connexion.
en utilisant la librairie SimpleOpenNI sous Processing 2 (à importer)

squelette_kinect_PROF.pde
Laurent Rebuffie août 2016
*/

// importer la librairie SimpleOpenNI
import SimpleOpenNI.*;
// créer un objet context de la classe SimpleOpenNI
SimpleOpenNI contexte;

void setup()
{
// dimensions de la fenêtre sous Processing
size(640 , 480);

// instancier contexte l’instance de la classe SimpleOpenNI
contexte = new SimpleOpenNI(0,this);

// vérification de la communication avec la Kinect
if(contexte.isInit() == false)
{
println(« Impossible de communiquer avec la Kinect »);
exit(); // sortie du programme GC …
return;
}

else {
// 1_ valider le contexte visu caméra profondeur en utilisant la méthode enableDepth
contexte.enableDepth();

// 3_ valider le contexte skeleton generation for all joints en utilisant la méthode enableUser
contexte.enableUser();

}
}

 

// En boucle dans Processing
void draw()
{
// mise à jour du contexte en utilisant la méthode update
contexte.update();

// 2_ affichage des collections d’images renvoyées par la méthode depthImage du contexte
image(contexte.depthImage(),0,0);

// 4_ affichage des collections d’images renvoyées par la méthode userImage du contexte
// la silhouette d’une personne se présentant devant la caméra s’affiche en bleu (mode un seul joueur)
image(contexte.userImage(),0,0);

// 6_ on récupère le nombre d’utilisateurs détectés par le contexte sous forme d’un tableau d’entiers
// à l’aide de la méthode getUsers du contexte
int[] userList = contexte.getUsers();
// println(« userList[0] :  » + userList[i] );

// 7_ Tracer le squelette de chaque utilisateur (joueur) traqué –> méthode drawSkeleton
for(int i=0;i<userList.length;i++) {

if(contexte.isTrackingSkeleton(userList[i]))
{
// Tracer le squelette de l’utilisateur i
drawSkeleton(userList[i]);
println(« Tracé du squelette de :  » + userList[i] );

}

} // fin for

}

 

// dessin du squelette avec les différentes articulations
void drawSkeleton(int userId)
{
// couleur et épaisseur des traits dans Processing
stroke(255,0,0);
strokeWeight(5);

contexte.drawLimb(userId, SimpleOpenNI.SKEL_HEAD, SimpleOpenNI.SKEL_NECK);

contexte.drawLimb(userId, SimpleOpenNI.SKEL_NECK, SimpleOpenNI.SKEL_LEFT_SHOULDER);
contexte.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_SHOULDER, SimpleOpenNI.SKEL_LEFT_ELBOW);
contexte.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_ELBOW, SimpleOpenNI.SKEL_LEFT_HAND);

contexte.drawLimb(userId, SimpleOpenNI.SKEL_NECK, SimpleOpenNI.SKEL_RIGHT_SHOULDER);
// 7_complétez le tracé du squelette avec celui du bras droit
contexte.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_SHOULDER, SimpleOpenNI.SKEL_RIGHT_ELBOW);
contexte.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_ELBOW, SimpleOpenNI.SKEL_RIGHT_HAND);

contexte.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_SHOULDER, SimpleOpenNI.SKEL_TORSO);
contexte.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_SHOULDER, SimpleOpenNI.SKEL_TORSO);

contexte.drawLimb(userId, SimpleOpenNI.SKEL_TORSO, SimpleOpenNI.SKEL_LEFT_HIP);
contexte.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_HIP, SimpleOpenNI.SKEL_LEFT_KNEE);
contexte.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_KNEE, SimpleOpenNI.SKEL_LEFT_FOOT);

contexte.drawLimb(userId, SimpleOpenNI.SKEL_TORSO, SimpleOpenNI.SKEL_RIGHT_HIP);
contexte.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_HIP, SimpleOpenNI.SKEL_RIGHT_KNEE);
contexte.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_KNEE, SimpleOpenNI.SKEL_RIGHT_FOOT);

}

 

// —————————————————————————————-
// SimpleOpenNI events
// La méthode onNewUser se lance à chaque fois qu’un nouvel utilisateur est détecté sur l’image
// par le contexte. Un numéro d’identifiant est attribué à chaque utilisateur (joueur) 1,2 …

void onNewUser(SimpleOpenNI curContexte, int userId)
{
// 5_afficher le numéro des nouveaux utilisateurs dans la console
println(« Evt onNewUser() nouvel utilisateur détecté -> userId:  » + userId);

// 6_ lancer le tracking du squelette de cet utilisateur à l’aide de la méthode startTrackingSkeleton
println(« \tRecherche et tracking du squelette de  » + userId);
curContexte.startTrackingSkeleton(userId);
}

 

 

 Catégorie: News ! Processing

Articles similaires

Laisser une réponse