====== Coopération Humains-Machines / Humain-Humain ====== ===== Codes des prototypes ===== * Porteur du projet : Thomas Leloup * Date : 20/02/2018 * Contexte : Mémoire DSAA * Lien : http://thomasleloup.fr/ ===== Handtracking ===== ==== Code principal ==== import kinect4WinSDK.*; //importer bibliothèque Kinect pour windows SDK import KinectPV2.KJoint; //importer bibliothèque KinectPV2.KJoint import KinectPV2.*; //importer bibliothèque KinectPV2 KinectPV2 kinect; //créer un attribut KinectPV2 nommé kinect //attribut couleur en dégradé 1 int r = 255; int g = 0; int b = 0; //boîte de particules de la classe Particle ArrayList allParticles = new ArrayList(); float currentHue = 0; //teinte actuelle = 0 ParticleSystem ps; //attribut nommé ps de la classe ParticleSystem PVector target; //vecteur nommé target PVector[] points; //boîte de vecteurs nommé points float x, y, angle, ease = 0.5; //introduire x, y, angle et ease = 0.5 boolean easing = true; //booléen nommé easing en vrai //num => nombre de particules (cercles) lors du tracking //frames => nombre d’images int num=70, frames=165; PImage main; //créer une image nommé main PImage main1; //créer une image nommé main1 void setup() { fullScreen(P3D); //affichage plein écran de la zone de travail (zone en 3D) frameRate(30); //nombre d’images par seconde //l’attribut nommé kinect devient une zone de capture de la Kinect kinect = new KinectPV2(this); kinect.enableSkeletonColorMap(true); //autorisation détection du squelette kinect.enableColorImg(true); //autorisation de la colorisation de l’image de la kinect kinect.init(); //démarrage de la kinect main = loadImage(«main.png»); // l’image main télécharge le fichier main.png main1 = loadImage(«main1.png»); // l’image main1 télécharge le fichier main1.png //ps ps = new ParticleSystem(new PVector(width/2, 50)); background(255); //fond blanc sur la zone de travail points = new PVector[num]; for (int i=0; i skeletonArray = kinect.getSkeletonColorMap(); //pour toutes jointures comprises dans la boîte de valeurs du squelette for (int i = 0; i < skeletonArray.size(); i++) { //skeleton de classe KSkeleton prend toutes valeurs i de la boîte du squelette KSkeleton skeleton = (KSkeleton) skeletonArray.get(i); if (skeleton.isTracked()) { //si il y a tracking du squelette //chaque jointures de classe KJoint prends les jointures du squelette KJoint[] joints = skeleton.getJoints(); background(0); //fond noir sur la zone de travail //nouvelle couleur nommé col prend les couleurs indexées du squelette color col = skeleton.getIndexColor(); fill(col); //remplir avec la couleur col stroke(col); //contours avec la couleur col //détection seulement de la main gauche drawHandState(joints[KinectPV2.JointType_HandLeft]); } } } //lorsqu’il y a tracking de la main gauche void drawHandState(KJoint joint) { noStroke(); //pas de contours pushMatrix(); //début zone restreinte tint(r,b,g); //teinture par r,g,b imageMode(CENTER); //mode image centré main.resize(0,80); //redimension image main (80px) //image main aux coordonnées de la position de la main gauche image(main,joint.getX(), joint.getY()); popMatrix(); //fin zone restreinte //ajout de particules ps aux coordonnées de la position de la main gauche ps.addParticle(joint.getX(), joint.getY()); //fonctionnement et actualisation des particules ps ps.run(); programme de transition des couleurs r,g,b if(g < 255 && b == 0) { g = g + 5; } //Yellow to green if (g == 255 && b == 0) { if(r >= 0) { r = r - 5; } } //Green to cyan if (r == 0 && g == 255) { if(b < 255) { b = b + 5; } } //cyan to blue if (b == 255 && r == 0) { if(g > 0) { g = g - 5; } } //Purple to magenta if (b == 255 && g == 0) { if(r < 255) { r = r + 5; } } //magenta to red if(r == 255 && g == 0) { if(b > 0) { b = b - 5; } } } \\ ==== Classe Système de Particule ==== class Particle { //création attributs des particules PVector location; //positions PVector location1; PVector location2; PVector location3; PVector velocity; //vitesse de déplacement des particules PVector acceleration; //accélération de leur vitesse float lifespan; Particle(float x, float y) { acceleration = new PVector(0, 0.05); //random => valeur aléatoire entre deux chiffres velocity = new PVector(random(-1, 1), random(-2, 0)); location = new PVector(x, y); location1 = new PVector(x+random(-10, 8), y+random(-8, 30)); location2 = new PVector(x+random(-30, 5), y+random(-1, 10)); location3 = new PVector(x+random(-20, 6), y+random(-20, 4)); lifespan = 255.0; } //méthode pour afficher les deux autres méthodes void run() { update(); display(); } //Méthode pour mettre à jour la position void update() { velocity.add(acceleration); location.add(velocity); lifespan -= 3; } //Méthode pour lire les particules void display() { noStroke(); //stroke(255, lifespan); fill(r,g,b, 205-lifespan/2); ellipse(location.x, location.y, 20, 20); ellipse(location1.x, location1.y, 20, 20); ellipse(location2.x, location2.y, 20, 20); ellipse(location3.x, location3.y, 20, 20); } //Booléen en fonction de l’opacité des particules (au=dessus) boolean isDead() { if (lifespan < 100.0) { return true; } else { return false; } } } \\ ==== Classe Particule ==== // Classe pour décrire le groupe de Particules // Un ArrayList est utilisé pour organiser la liste des Particules class ParticleSystem { ArrayList particles; PVector origin; ParticleSystem(PVector location) { origin = location.get(); //origin prend les valeurs de location (voir autre classe) particles = new ArrayList(); //ajout de particules dans la boîte } //méthode d’ajout de particules sur la zone de travail void addParticle(float x, float y) { particles.add(new Particle(x,y)); } //méthode pour afficher les particules dans la zone de travail void run() { for (int i = particles.size()-1; i >= 0; i--) { Particle p = particles.get(i); p.run(); if (p.isDead()) { //voir booléen de l’autre classe particles.remove(i); } } } } \\ \\ \\ \\ ---- ===== Shake it up ===== ==== Code principal ==== import gab.opencv.*; //importer la bibliothèque opencv import KinectPV2.*; //importer la bibliothèque Kinect //attribut couleur en dégradé 1 int r = 255; int g = 0; int b = 0; //attribut couleur en dégradé 2 int r1 = 0; int g1 = 255; int b1 = 255; KinectPV2 kinect; //créer un attribut KinectPV2 nommé kinect OpenCV opencv; //créer un attribut OpenCV nommé opencv float polygonFactor = 1; //facteur de résolution du corps int threshold = 10; //seuil de détection int maxD = 1800; //Distance max de captation 1.8m int minD = 50; //Distance min de captation 50cm boolean contourBodyIndex = false; //booléen pour la détection du contour du corps void setup() { size(1920, 1080, P3D); //taille de la zone de travail avec 3D //l’attribut nommé opencv devient une zone de capture de la bibliothèque opencv opencv = new OpenCV(this, 512, 424); //l’attribut nommé kinect devient une zone de capture de la Kinect kinect = new KinectPV2(this); kinect.enableDepthImg(true); //autorisation profondeur de l’image kinect kinect.enableBodyTrackImg(true); //autorisation du tracking du corps kinect.enablePointCloud(true); //autorisation d’un nuage de point de l’image kinect kinect.init(); //démarrage de la kinect } void draw() { //remplir avec les valeurs de couleurs r,g,b définies auparavant (opacité réduite : 10) pour toutes formes situées à la suite fill(r,g,b,10); rect(0,0,width,height); //rectangle de la taille de zone de travail noFill(); //pas de remplissage pour toutes formes situées à la suite strokeWeight(1);//taille des contours 1px scale(3.75,2.45,5);//redimensionnement de la capture qui suit if (contourBodyIndex) { //si il détecte un corps opencv.loadImage(kinect.getBodyTrackImage()); //alors chargement de l’image du tracking de la kinect //PImage dst = opencv.getOutput(); } else { //sinon opencv.loadImage(kinect.getPointCloudDepthImage()); //chargement de l’image de profondeur de la kinect //PImage dst = opencv.getOutput(); } //tableau qui utilise la classe Contour de la bibliothèque où contours prend les valeurs de détection de contours de opencv ArrayList contours = opencv.findContours(false, false); if (contours.size() > 0) { //si la taille de countours est supérieur à 0 for (Contour contour : contours) { //pour tout contour de classe Contour prenant la valeurs de contours //faire une approximation de la résolution grâce au facteur de résolution définis au départ (en haut) contour.setPolygonApproximationFactor(polygonFactor); if (contour.numPoints() > 50) { //si le nombre de points de contour dépasse 50 noStroke(); //pas de contours pour toutes formes situées à la suite beginShape(); //début de forme //remplir avec les valeurs de couleurs r1,g1,b1 définies auparavant pour toutes formes situées à la suite fill(r1,g1,b1); //pour tout point prenant les valeurs d’approximation définies par contour for (PVector point : contour.getPolygonApproximation ().getPoints()) { vertex(point.x, point.y); //faire des sommets avec comme coordonnées chaque pixel capté dans la zone de captation } endShape(); //fin de forme } } //programme de transition des couleurs r,g,b if(g < 255 && b == 0) { g = g + 5; } //Yellow to green if (g == 255 && b == 0) { if(r >= 0) { r = r - 5; } } //Green to cyan if (r == 0 && g == 255) { if(b < 255) { b = b + 5; } } //cyan to blue if (b == 255 && r == 0) { if(g > 0) { g = g - 5; } } //Purple to magenta if (b == 255 && g == 0) { if(r < 255) { r = r + 5; } } //magenta to red if(r == 255 && g == 0) { if(b > 0) { b = b - 5; } } //programme de transition des couleurs r1,g1,b1 if(g1 < 255 && b1 == 0) { g1 = g1 + 5; } //Yellow to green if (g1 == 255 && b1 == 0) { if(r1 >= 0) { r1 = r1 - 5; } } //Green to cyan if (r1 == 0 && g1 == 255) { if(b1 < 255) { b1 = b1 + 5; } } //cyan to blue if (b1 == 255 && r1 == 0) { if(g1 > 0) { g1 = g1 - 5; } } //Purple to magenta if (b1 == 255 && g1 == 0) { if(r1 < 255) { r1 = r1 + 5; } } //magenta to red if(r1 == 255 && g1 == 0) { if(b1 > 0) { b1 = b1 - 5; } } } kinect.setLowThresholdPC(minD); //faire un seuil minimale pour la distance minimale de captation kinect.setHighThresholdPC(maxD); //faire un seuil maximale pour la distance maximale de captation }