tracking

Tracking

Tra­cking – cours tech­nique n°1

Créez votre chien vir­tuel !”, nous invite une publi­cité. Ani­maux vir­tuels, ami vir­tuel, man­ne­quin vir­tuel, pays vir­tuel… la foi­son­nante vir­tua­lité fri­vole de la toile exige de repen­ser le mot vir­tuel. Dans le Petit Robert, son éty­mo­lo­gie remonte à 1503, ses ori­gines à la sco­las­tique du Moyen Âge, mais son uti­li­sa­tion est repé­rée au XVIIe siècle, déri­vant du latin vir­tus, vertu, force, puis­sance : “Qui n’est tel qu’en puis­sance, qui est à l’état de simple pos­si­bi­lité”. Syno­nymes : pos­sible, poten­tiel (par exemple : can­di­dat vir­tuel à la présidence).

Ce texte de Maria Maïla est inté­res­sant dans la mesure où il contre­dit le contre­sens usuel que nous fai­sons en employons le mot ‘vir­tuel’. Nous l’opposons faci­le­ment au réél. Le vir­tuel est avant tout un poten­tiel. Est vir­tuel ce qui tient de l’hypothèse, comme une idée que l’on peut avoir en tant que desi­gner, artiste, créa­teur qui n’est pas encore réa­li­sée.

Notions

Tra­cking

Tra­cking dans le film Roco­cop (Paul Verhoe­ven , 1987)

Le tra­cking a été popu­la­risé par les films de science-fiction, comme étant le sys­tème gérant la vision de robots. Exemples les plus connus : Robo­cop, Ter­mi­na­tor. Le motion tra­cking extrait d’une image en mou­ve­ment cer­taines par­ties de l’image et per­met de récu­pé­rér un cer­tain nombre de variables telles que coor­don­nées ayant pour réfé­rence le cadre de l’image.

Blobs

The blob, jaquette DVD (Chuck Rus­sell, 1988)

Les blobs ne sont pas, dans le domaine du “com­pu­ter vision”, des masses vis­queuses comme dans ce (bon) film de série Z, remake des années 80 d’un film de 1958. En ce qui nous concerne, les blobs sont des points, des régions d’une image détec­tés par un pro­gramme et qui se carac­té­risent par des pro­prié­tés par­ti­cu­lières de clarté, de cou­leur par rap­port au reste de l’image.

Dans notre cas, ça res­semble plu­tôt à ce genre de chose :

Blobs détec­tés grâce à un sketch processing

Les blobs, dans ce cas sont les contours déter­mi­nant les sur­face plus fon­cées de l’image.

3D Le terme 3D se réfère de manière assez confuse dans le lan­gage cou­rant à plu­sieurs pra­tiques. La 3D est à la fois de la modé­li­sa­tion, de l’image de syn­thèse, de l’animation

Modé­li­sa­tion La modé­li­sa­tion décrit le pro­cédé de des­sin de la forme d’un objet.

Ani­ma­tionAvant d’être ren­dus, les objets modé­li­sés en 3D doivent être pla­cés dans une scène. Un scène est un espace en trois dimen­sions géo­mé­trique déter­mi­nés selon 3 axes. L’animation prend place dans cet espace et dans le temps.

Exemples d’utilisation de ces fonctions

Tra­cking + face detect Face­Pong

La camera suit le visage du spec­ta­teur pour faire dépla­cer un volume dans un jeu video clas­sique revi­sité, Pong. C’est un tra­cking par­ti­cu­lier appelé face-detect.

Tra­cking / Par­ti­cules / per­for­mance Dan­cing With Swar­ming Par­ticles Onceu­po­na­byte Le tra­cking est ici appli­qué à un sys­tème de par­ti­cules.

Ani­ma­tion dans l’espace + tra­cking Rubans vir­tuels

Kinect + tra­cking + des­sin dans l’espace Graf­fiti tool Jean-Christophe Naour

Pro­jec­tion / Archi­tec­ture / volume Gra­vity 2roqs

3D + des­sin + pro­jec­tion YJAFJALLAJÖKULL AntiVJ (regar­der plus pré­ci­sé­ment à 2:20)

Volume + pro­jec­tion Light Sculp­tures AntiVJ

Ins­tal­la­tion + pro­jec­tion + synes­thé­sie 3D des­truct AntiVJ

Ins­tal­la­tion / archi­tec­ture Pablo Val­buena Para-Site

Volumes + pro­jec­tion Pablo Val­buena Aug­men­ted sculptures

Exer­cices techniques

Com­men­çons main­te­nant les exer­cices et tech­niques de base.

Avant toute chose nous allons avoir besoin, comme à chaque usage spé­ci­fique de Pro­ces­sing, devoir télé­char­ger une biblio­thèque par­ti­cu­lière : Pour MAC : openCV La réfé­rence de la biblio­thèque Opencv pour connaitre toutes ses fonctions

Pour MAC + PC : Blob­De­tec­tion La réfé­rence de la biblio­thèque blob­De­tec­tion pour connaitre toutes ses fonctions

Exemple de tra­cking com­menté pour MAC + PC

À par­tir des exemples de la biblio­thèque OpenCV, et plus par­ti­cu­liè­re­ment de blobs, voici le code com­menté de base qui va nous pemettre de détec­ter des blobs de manière dyna­mique et en temps réel :

Code com­plet commenté

// on importe la bibliotheque opencv
import hypermedia.video.*;
import java.awt.*;

// on créée un objet opencv
OpenCV opencv;

// on créée des variables pour faciliter la mosaique des images de captation pour plus tard
int w = 320;
int h = 240;
// on créée une variable pour initiliser la valeur de contraste de l'image en bas à droite
int threshold = 80;

// on crée une variable booléenne
boolean find=true;

// on créée une variable police de caractère pour afficher les valeurs (tailles, surfaces, centre de gravité...) des blobs
PFont font;

void setup() {
  // on détermine la taille de notre sketch à partir de celles des différents écrans
  size( w*2+30, h*2+30 );

  // on initialise l'objet OpenCV
  opencv = new OpenCV( this );
  // on créée la fenêtre de capture
  opencv.capture(w, h);

  // je charge la police de caracteres associees à la variable font
  font = loadFont( "AndaleMono.vlw" );
  // je détermine comme la variable font comme police de caractères par défaut
  textFont( font );

  // j'imprime dans la console de debuggage les instructions suivantes :
  println( "Drag mouse inside sketch window to change threshold" );
  println( "Press space bar to record background image" );
}

void draw() {
  //je détermine ma couleur de fond (noir)
  background(0);
  //je lance la lecture de ce que capte la camera
  opencv.read();
  // je desactive la fonction mirroir d'affichage
  //opencv.flip( OpenCV.FLIP_HORIZONTAL );

  // ma fenêtre de capture en haut à gauche (poisition X : 10, position Y : 10)
  image( opencv.image(), 10, 10 );	            // RGB image
  // ma fenêtre de capture en haut à droite 
  image( opencv.image(OpenCV.GRAY), 20+w, 10 );   // GRAY image
  // ma fenêtre snapshot. ne s'affiche que lorsque que je fais un instantané en appuyant sur la barre espace du clavier
  image( opencv.image(OpenCV.MEMORY), 10, 20+h ); // image in memory

  //
  opencv.absDiff();
  //j'active la fonction de contraste et lui attribue la valeur de la variable 'treshold'
  opencv.threshold(threshold);
  // Pour comparer notre instantané avec la fenêtre 
  image( opencv.image(OpenCV.GRAY), 20+w, 20+h ); // absolute difference image

  // on lance la detection de blobs sous forme de liste.
  // les paramètres de opencv.blobs()
  Blob[] blobs = opencv.blobs( 100, w*h/3, 20, true );

  // on desactive le remplissage de toutes les formes qui vont suivre dans le programme
  noFill();

  pushMatrix();
  //on déplace notre 'calque' de contour de blob pour 
  //le faire se superposer avec notre fenetre de captation 
  //de camera en bas à droite
  translate(20+w, 20+h);

  //on créée un boucle d'itération pour détecter de manière 
  //dynamique TOUTES les surafces les plus claires 
  //de la captation de la webcam
  for ( int i=0; i<blobs.length; i++ ) {

    //on initialise la fonction de la bibliothèque opencv
    // qui s'appelle Rectangle et qui permet de
    //dessiner les rectangle autour de nos blobs
    Rectangle bounding_rect	= blobs[i].rectangle;
    //on créée une variable nommée 'area'
   // à laquelle on donne la valeur de la surface de nos blobs grâce 
   //à la fonction '.area'
   //de la bibliothèque opencv
    float area = blobs[i].area;
    //on créée un objet pour récupérér la valeur de la surface des blobs
    float circumference = blobs[i].length;
    // à chaque blobs, on active la fonction .centroid
    // de la bibliothèque OpenCV
    //ça va nous permettre de récupérer les positions X et Y
    // des centres de gravité de nos blobs
    Point centroid = blobs[i].centroid;
    Point[] points = blobs[i].points;

    // Dessins des rectangles autour de nos blobs
    // on désactive la fonction de remplissage
    noFill();
    //on dessine un contour en demandant à la bibliothèque opencv
    // par la fonction .isHole : on s'assure que c'est ou non un blob dans un autre blob
    stroke( blobs[i].isHole ? 128 : 64 );
    //on dessine les rectangles en recuperant les coordonnées par
    //les variables bounding_rect.x et bounding_rect.y
   // et la hauteur et la largeur par les variables bounding_rect.width et bounding_rect.height
    rect( bounding_rect.x, bounding_rect.y, bounding_rect.width, bounding_rect.height );

      // CENTROID / CENTRES DE GRAVITÉ
      //on créée un contour de couleur rouge
    stroke(0, 0, 255);
    //on dessine la ligne vhorizontale de la croix
    // qui indique le centre de gravité du blob
    // cendroid.x : position X Y du centre de gravité du blob
    // centroid.y : position Y du centre de gravité du blob
    line( centroid.x-5, centroid.y, centroid.x+5, centroid.y );
    //on dessine la ligne vhorizontale de la croix
    // qui indique le centre de gravité du blob
    // cendroid.x : position X Y du centre de gravité du blob
    // centroid.y : position Y du centre de gravité du blob
    line( centroid.x, centroid.y-5, centroid.x, centroid.y+5 );
    // on desactive les contours
    noStroke();
    //on active une nouvelle couleur de remplissage
    fill(0, 0, 255);
    // on écrit la valeur de la surface (variable area) du blob, 
    // à coté de notre croix
    //grâce aux positions du centre de gravité
    // position X : centroid.x
    // position Y : centroid.y
    text( area, centroid.x+5, centroid.y+5 );

    // couleur de remplissage des dessins des formes de blobs
    fill(255, 0, 255, 64);
    // couleur de contours des dessins des formes de blobs
    stroke(255, 0, 255);
    // début des dessins de formes de blobs
    if ( points.length>0 ) {
      beginShape();
      for ( int j=0; j<points.length; j++ ) {
        vertex( points[j].x, points[j].y );
      }
      endShape(CLOSE);
      // fin des dessins de formes de blobs
    }

// on desactive le dessin des contours
    noStroke();
    //on choisit une nouvelle couleur de remplissage
    fill(255, 0, 255);
    // on ecrit les textes d'information en récupérant les valeurs
    // circumference : taille du périmètre du contour
    // en les plaçant à coté du curseur
    // grace au coordonnées des points de gravité (centroid.x, entroid.y)
    text( circumference, centroid.x+5, centroid.y+15 );
  }
  popMatrix();
}

void keyPressed() {
  // quand on appuie sur la barre espace du clavier, on lance la fonction opencv.remember de la bibliothèque Opencv
  if ( key==' ' ) opencv.remember();
}

void mouseDragged() {
  // quand on déplace la souris, on change la valeur du contraste 
  threshold = int( map(mouseX, 0, width, 0, 255) );
}

public void stop() {
  // une fonction qui arrête tous les processus en cours lors de l'extinction de notre sketch
  opencv.stop();
  super.stop();
}

Code sim­pli­fié com­menté (détec­tion de blob et affec­ta­tion d’un cercle rouge)

Acne sur un top model en temps réél grâce à Processing

// on importe la bibliotheque opencv
import hypermedia.video.*;
import java.awt.*;

// on créée un objet opencv
OpenCV opencv;

// on créée une variable pour initiliser la valeur de contraste de l'image en bas à droite
int threshold = 80;

// on crée une variable booléenne
boolean find=true;

void setup() {
  // on détermine la taille de notre sketch
  size( 800, 600 );

  // on initialise l'objet OpenCV
  opencv = new OpenCV( this );
  // on créée la fenêtre de capture de la largeur et la hauteur de notre sketch
  opencv.capture(width, height);
}

void draw() {
  //je lance la lecture de ce que capte la camera
  opencv.read();
  // je desactive la fonction mirroir d'affichage
  //opencv.flip( OpenCV.FLIP_HORIZONTAL );

  // ma fenêtre de capture en haut à gauche (poisition X : 10, position Y : 10)
  image( opencv.image(), 0, 0 );

  //opencv.absDiff();
  //j'active la fonction de contraste et lui attribue la valeur de la variable 'treshold'
  opencv.threshold(threshold);

  // on lance la detection de blobs sous forme de liste.
  // les paramètres de opencv.blobs()
  Blob[] blobs = opencv.blobs( 100, width*height/3, 20, true );

  // on desactive le remplissage de toutes les formes qui vont suivre dans le programme
  noFill();

  pushMatrix();

  //on créée un boucle d'itération pour détecter de manière 
  //dynamique TOUTES les surafces les plus claires 
  //de la captation de la webcam
  for ( inti=0;
i<blobs.length
; i++ ) {

    // à chaque blobs, on active la fonction .centroid
    // de la bibliothèque OpenCV
    //ça va nous permettre de récupérer les positions X et Y
    // des centres de gravité de nos blobs
    Point centroid = blobs[i].centroid;

    //on dessine un contour en demandant à la bibliothèque opencv
    // par la fonction .isHole : on s'assure que c'est ou non un blob dans un autre blob
    stroke( blobs[i].isHole ? 128 : 64 );

    // CENTROID / CENTRES DE GRAVITÉ
    noStroke();
    //on active une nouvelle couleur de remplissage
    fill(255, 0, 0);
    //on dessine notre cercle en prenant les coordonnées de nos centres de gravités
    // comme coordonnées des centres de nos cercles
    ellipse(centroid.x, centroid.y, 10, 10);
  }
  popMatrix();
}

//FONCTION RÉGLAGE DE CONTRASTE GRACE A NOTRE CURSEUR DE SOURIS

void mouseDragged() {
  // quand on déplace la souris, on change la valeur du contraste 
  threshold = int( map(mouseX, 0, width, 0, 255) );
}

public void stop() {
  // une fonction qui arrête tous les processus en cours lors de l'extinction de notre sketch
  opencv.stop();
  super.stop();
}

Télé­char­ge­ments des 2 fichiers de codes commentés

Exer­cice pour le pro­chain cours À par­tir du code de blob_simple_cerclerouge.pde, vous choi­si­rez un texte et une image de votre choix qui feront sens l’un par rap­port à l’autre et aussi par rap­port au choix d’un objet/sujet capté par la webcam.

rap­pel : Inté­grer une image Police de carac­tères et texte

pour les plus aven­tu­reux, vous pou­vez même incor­po­rer des ani­ma­tions (gif), ou des mini-films.

Com­plé­ment de cours

En com­plé­ment du cours pré­cé­dent, voici un exemple qui per­met de tra­cker 2 cou­leurs par­ti­cu­lières dans le champ de vision de la camera : colour_detection.

0