Outils pour utilisateurs

Outils du site


wiki:projets:path:path

OEUVRE INTERACTIVE "PATH"

  • Porteur du projet : PAPAZIAN Sévan
  • Date : Janvier 2019
  • Contexte :Réalisation d'un programme Processing incluant l'utilisation d'une librairie et d'une classe

Intention :

J'ai voulus questionner au travers de mon projet la matérialisation d'un mouvement dans espace numérique. J'ai donc imaginé une installation muséale / oeuvre interactive traduisant un mouvement dans l'espace en un champ vectoriel.

Outils :

La kinect:

La kinect grace à sa caméra infrarouge ma permis de pouvoir capter la profondeur de l'image capté pour mieux appréhender le mouvement du spectateur.

Processing:

Processing est un outil de programmation qui vas me permettre d'exploiter la Kinect, je me suis notamment appuyer sur des programmes déjà developper par Daniel Shiffman qui utilise la Kinect et plus particulièrement la librairie Kinect.

Programme :

Class : KinectTracker

Cette classe crée par Daniel S permet de créer un traqueur, ce traqueur définie une zone la plus proche détectée à l'aide du “treshold” le seuil de profondeur. Cette zone sert à définir deux points, celui qui m'intéresse et le second, c'est celui qui définie le barycentre de la zone détectée. Il est le point de référence a partir du quelle la traduction du mouvement capté vas se faire.

Barycentre : c'est un point qui est définie en interpolant l'ensemble des coordonnées d'une zone ( dans notre cas celles de la zone détectée la plus proche du seuil de profondeur

Constructeur:

  1. KinectTracker : Créer le tracker il utilise les variables display , loc , lerped loc

Attributs:

  1. Loc (Pvector): Position brute
  2. LerpedLoc (Pvector): Interpolation de la position
  3. Deph (entier): Donnée de profondeur
  4. display (Pimage): Ce que le spectateur vas voir
  5. Threshold (entier): Seuil de profondeur

Méthodes:

  1. Track: Défini une zone en fonction de la profondeur et lui attribut un point à l'aide du barycentre
  2. Display: Permet d'afficher ce que capte la kinect
  3. SetTreshold: Permet de controller le seuil de profondeur
// Daniel Shiffman
// Tracking the average location beyond a given depth threshold
// Thanks to Dan O'Sullivan

// https://github.com/shiffman/OpenKinect-for-Processing
// http://shiffman.net/p5/kinect/

class KinectTracker {

  // Seuil de profondeur
  int threshold = 745;

  // position brute( vague) 
  PVector loc;

  // interpolation de la position 
  PVector lerpedLoc;

  // Donnée de profondeur
  int[] depth;
  
  // Ce que le spectateur vas voir 
  PImage display;
   
  KinectTracker() {
    // This is an awkard use of a global variable here
    // But doing it this way for simplicity
    kinect.initDepth();
    kinect.enableMirror(true);
    // Make a blank image
    display = createImage(kinect.width, kinect.height, RGB);
    // Set up the vectors
    loc = new PVector(0, 0);
    lerpedLoc = new PVector(0, 0);
  }

  void track() {
    // definie la profondeur brute dans un tableau d'entier 
    depth = kinect.getRawDepth();

    // faire attention ici 
    if (depth == null) return;

    float sumX = 0;
    float sumY = 0;
    float count = 0;

    for (int x = 0; x < kinect.width; x++) {
      for (int y = 0; y < kinect.height; y++) {
        
        int offset =  x + y*kinect.width;
        // Grabbing the raw depth
        int rawDepth = depth[offset];

        // Test le seuil de profondeur 
        if (rawDepth < threshold) {
          sumX += x;
          sumY += y;
          count++;
        }
      }
    }
    // tant que l'on touve quelque chose 
    if (count != 0) {
      loc = new PVector(sumX/count, sumY/count);
    }

    //inerpole la position, le fait arbitrirement pour l'instant 
    lerpedLoc.x = PApplet.lerp(lerpedLoc.x, loc.x, 0.3f);
    lerpedLoc.y = PApplet.lerp(lerpedLoc.y, loc.y, 0.3f);
  }

  PVector getLerpedPos() {
    return lerpedLoc;
  }

  PVector getPos() {
    return loc;
  }

  void display() {
    PImage img = kinect.getDepthImage();

    // Being overly cautious here
    if (depth == null || img == null) return;

    // Going to rewrite the depth image to show which pixels are in threshold
    // A lot of this is redundant, but this is just for demonstration purposes
    display.loadPixels();
    for (int x = 0; x < kinect.width; x++) {
      for (int y = 0; y < kinect.height; y++) {

        int offset = x + y * kinect.width;
        // Raw depth
        int rawDepth = depth[offset];
        int pix = x + y * display.width;
        if (rawDepth < threshold) {
          // A red color instead
          display.pixels[pix] = color(#FF2739);
        } else {
          display.pixels[pix] = img.pixels[offset];
        }
      }
    }
    display.updatePixels();

    // mise en place de l'image 
    image(display,790, 94, 401,400);
  }

  int getThreshold() {
    return threshold;
  }

  void setThreshold(int t) {
    threshold =  t;
  }
}

Mon programme

Mon programme permet en utilisant la classe KinecTracker de capter une zone à partir d'un certain seuil de profondeur de cette zone le programme interpole grace au barycente une position sur laquelle elle viens placer un point de couleur bleu ce point bleu définie une position qui est reliée par un vecteur à l'origine de l'image en 0,0 ( en haut à droite ) de cette façon quand la zone détecté se déplace le point et le vecteur se déplace traduisant ainsi le mouvement de la zone détecté en un champ de vecteur et de point

//Sévan PAPAZIAN
//DSAA1 MARSEILLE
//Projet d'oeuvre interractive "PATH"
//Tonerkebab.fr

//Basé sur le programme de: Daniel Shiffman:
// https://github.com/shiffman/OpenKinect-for-Processing
// http://shiffman.net/p5/kinect/


import org.openkinect.freenect.*;
import org.openkinect.processing.*;


PImage img;
float offset = 0;
float easing = 0.05;
int time;
// La programmation de la kinect en elle meme se passe dans les classes suivantes
KinectTracker tracker;
Kinect kinect;

// tableau dynamique pour la mémorisation de la position des points
ArrayList<PVector> dessin;

boolean colorDepth = false;



void setup() {
  size(1400, 700);
   img = loadImage("grille1.png");

  kinect = new Kinect(this);
  tracker = new KinectTracker();

  // initialisation de la liste vise
  dessin = new ArrayList<PVector>();
  
    //Mode de représentation de la profondeur en couleur
  kinect.enableColorDepth(colorDepth);

}

void draw() {
 fill(#FF2739);
  noStroke(); 
     rect(0, 650, 6400, 50);
     
  timer();
  // Demarre l'analyse du tracking
  tracker.track();
  // Montre l'image
  tracker.display();
  

  // Dessine un point la localisation interpolé (barycentre) de la zonne la plus proche du seuil de profondeur 
  PVector v1 = tracker.getPos();
  fill(50, 100, 250, 200);
  noStroke();
  ellipse(v1.x, v1.y, 20, 20);

  // Dessine un vecteur de la zone interpolée (le barycentre) de la zone la plus proche du seuil de profondeur à l'origine du schémas   
  PVector v2 = tracker.getLerpedPos();
  dessin.add(v2);
  stroke(#FF2739);
  line(v2.x, v2.y, 20, 20);
 
  // petite fonctionalité suplémentaire permettant de tracer une ligne avec la souris
  if (mousePressed == true) {
  stroke(#FF2739);
    line(mouseX, mouseY, pmouseX, pmouseY);
  }

  
  
  // permet d'affficher des info comme le seuil de profondeur 
  int t = tracker.getThreshold();
  fill(0);
  text("threshold: " + t + "    " +  "framerate: " + int(frameRate) + "    " + 
    "UP augmente le seuil , DOWN descend le seuil", 10, 680);
 
  }
 
// Permet d'ajuster le seuil de profondeur " treshold" avec les fleches 
void keyPressed() {
  int t = tracker.getThreshold();
  if (key == CODED) {
    if (keyCode == UP) {
      t+=5;
      tracker.setThreshold(t);
    } else if (keyCode == DOWN) {
      t-=5;
      tracker.setThreshold(t);
        
    }
    // Permet de changer le mode de représentation (couleur ou pas ) du display 
    else if (keyCode == LEFT) {
    colorDepth = !colorDepth;
    kinect.enableColorDepth(colorDepth);
  }
  }
}
// timer qui permet de reset le background tout les 500 
void timer() {
  time++;
  if (time>500) {
    time = 0;
    // saveframe() permet de faire une capture d'écran et de l'enregister dans le dossier parent du programme 
    saveFrame();
    background(250);
    image(img,0,0,1280,650);
  }
}

Paramètre muséaux

Le timer() permet de reset background éffaçant ainsi le dessin fait et de permettre à un autre spectateur de tester l'installation.

Saveframe() permet de faire une capture de l'image avant le reset permettant au spectateur d'avoir une trace de son mouvement.

Le background() est une image masque qui permet de créer un univers qui alimente mon propos.

void timer() {
  time++;
  if (time>500) {
    time = 0;
    // saveframe() permet de faire une capture d'écran et de l'enregister dans le dossier parent du programme 
    saveFrame();
    background(250);
    image(img,0,0,1280,650);

keyPressed(), Treshold, colorDepth Dans cette partie du programme on permet de calibrer le seuil de profondeur et le mode de représentation du display ( en couleur ou pas) .Ainsi l'installation peut s'adapter à n'importe lieu d'exposition et vas dans la continuité de ma démarche de créer une oeuvre muséale pouvant être déplacée d'un endroit à un autre.

void keyPressed() {
  int t = tracker.getThreshold();
  if (key == CODED) {
    if (keyCode == UP) {
      t+=5;
      tracker.setThreshold(t);
    } else if (keyCode == DOWN) {
      t-=5;
      tracker.setThreshold(t);
 int t = tracker.getThreshold();
  fill(0);
  text("threshold: " + t + "    " +  "framerate: " + int(frameRate) + "    " + 
    "UP augmente le seuil , DOWN descend le seuil", 10, 680);
    

// Permet de changer le mode de représentation (couleur ou pas ) du display 
    else if (keyCode == LEFT) {
    colorDepth = !colorDepth;
    kinect.enableColorDepth(colorDepth);
  }

mousePressed()

Cette fonctionnalité n'est pas obligatoire a l'installation elle permet de pouvoir signer son mouvement si le lieu d'installation le permet à l'oeuvre.

if (mousePressed == true) {
    line(mouseX, mouseY, pmouseX, pmouseY);
  }

Ressources :

Sources :

wiki/projets/path/path.txt · Dernière modification: 2019/01/21 15:36 (modification externe)