Outils pour utilisateurs

Outils du site


wiki:projets:processing-dsaa1-2017:thomas-leloup

EFFETS SUR WEBCAM

  • Porteur(s) du projet : Thomas Leloup
  • Date : Mars 2017
  • Contexte : Cours de programmation

Ce programme réalisé sur Processing propose différents filtres à appliquer sur sa webcam pour ensuite prendre en photo.Pour ce programme la bibliothèque vidéo de processing sera nécessaire.La bibliothèque controlP5 utilisé pour la création de boutons n'est pas nécessaire ici car les boutons sont réalisés dans une classe nommée bouton. Pour se prendre en photo, il faut appuyer sur la touche ENTRÉE. Les 8 filtres ont chacun leur particularités :

  • Saturation
  • Déformation
  • Pong
  • Pluie
  • Trame
  • Neige
  • Noir & blanc
  • Négatif


Code principale du programme

/*

  Thomas Leloup
  Programme webcam/boutons/applications de filtres
  À améliorer = l'ergonomie des boutons et les filtres
  
*/

//importation librairie vidéo
import processing.video.*;

//attribut balle pong
ArrayList collectionBalle;
int Nballes = 100; // nombre de balles pour l'effet balle 

//tableau des boutons
button[] ton;

//attribut boolean pour bouton
boolean overBox = false;
boolean locked = false;
boolean singlePress = false;

//boîte de particules de pluie
Drop[] drops = new Drop[500];

//attribut pour trame de points  
ArrayList<Circle> circles;
int space;

//attribut pour la création de neige
PVector xx, yy, fcx, fcy, sx, sy;
int seed = 0, cell = 15;
Boolean randomized = true;

//attribut typographie
PFont font;

//déclaration de la caméra  
Capture cam;

///////////////////////////////////////////////////////////////////////////////////

void setup() {
  
  //taille zone de travail
  size(1280, 760);
    //on attribue la webcam à la caméra puis démarrage
    cam = new Capture(this, width, height-40);
    cam.start(); 
  //initialisation de l'effet neige
  Boolean randomized = true;
  initialize();
  //mode de couleur RVB
  colorMode(RGB);
  
  // initialisation du tableau de boutton
  ton = new button[8];
  
  //initialisation des boutons 
  for (int i=0;i<8;i++){
    ton[i] = new button();
  }
      
//les balles ont une nouvelle boîte
collectionBalle = new ArrayList();
//pour i compris entre 0 et nombre de balles
for(int i = 0; i<Nballes; i++){
   
   // création du vecteur position
   PVector p = new PVector(floor(random(50,width-50)), // x
                           floor(random(50,height-50))); //y
                           
  // création du vecteur position
   PVector d = new PVector(floor(random(-8,8)), //dx
                       floor(random(-8,8))) ; //dy
   
   //instanciation d'une nouvelle balle de classe balle
   balle nouvelleBalle = new balle(
                       p,// vecteur position
                       color(random(0,255),random(0,255),random(0,255)),
                       floor(random(5,30)), //20,  // d
                       d// vecteur déplacement
                        );
    //ajouter la nouvelleballe à la collection                   
    collectionBalle.add(nouvelleBalle);
 }
  //pour i compris entre 0 et taille du drop(chute d'eau)
  for (int i = 0; i < drops.length; i++) {
    //chute des gouttes i prend les valeurs de la classe drop
    drops[i] = new Drop(); // instanciation de la ième "drop"
  }
  
  //pointes de trame
  circles = new ArrayList();
    //distance entre les points
    space = 60;
    
    //ajout de points dans la zone de travail en fonction de l'espace entre les balles et les balles
    for (int i = -2 * space ; i <= (width) + space; i += space) {
        for (int j = -2 * space ; j <= (height) + space; j += space) {
            circles.add(new Circle(i, j));
        }
    }
  
}

///////////////////////////////////////////////////////////////////////////////////

// initialisation des flocons de neige
void initialize() {
  seed += frameCount;
  randomSeed((int)random(1000) + frameCount);
  //coordonnées pour les flocons de neige
  xx = new PVector(random(10, 110), random(10, 110));
  yy = new PVector(random(10, 110), random(10, 110));
  sx = new PVector(random(30, 70), random(30, 70));
  sy = new PVector(random(30, 70), random(30, 70));
  fcx = new PVector(random(20, 70), random(20, 70));
  fcy = new PVector(random(20, 70), random(20, 70));
}

///////////////////////////////////////////////////////////////////////////////////

void draw() {
  
  //30 images par seconde
  frameRate(30);
  
    //fond noir
    background(0);
    
     //si caméra est disponible, la lire
     if (cam.available() == true) {
    cam.read();
  }
  
  //la zone de travail est rempli par la caméra
  image(cam, 0,0);
  
 //dessin des boutons (couleurs et positions)
 
  for (int i=0; i<8; i ++){
  
    ton[i].draw(i*width/8,height-40,width/8,40);
  
  }
   
  //définition typographie et placement sur la zone de travail
  pushStyle();
  font = createFont("Montserrat-SemiBold.ttf", 14);
  textFont(font);
  fill(255);
  text("Saturation", 0*width/8 +44, height-15);
  text("Déformation", 1*width/8 +38, height-15);
  text("Pong", 2*width/8 +63, height-15);
  text("Pluie", 3*width/8 +63, height-15);
  text("Trame", 4*width/8 +60, height-15);
  text("Neige", 5*width/8 +60, height-15);
  text("Noir & Blanc", 6*width/8 +38, height-15);
  text("Négatif", 7*width/8 +58, height-15);
  popStyle();
  
///////////////////////////////////////////////////////////////////////////////////  
  
  //BOUTON 1 SATURATION
  if(ton[0].clicked()){ //au clic (voir class bouton)
     bouton1();
  
} 

///////////////////////////////////////////////////////////////////////////////////

  //BOUTON 2  DÉFORMATION
  else if(ton[1].clicked()){
      for (int i = 0; i < width; i = i+10) {
  for (int j = 0; j < height-40; j = j+10) {
    pushStyle();
    stroke(cam.get(i, j));
    fill(cam.get(i, j));  // rempli de la caméra
    ellipse(i, j, 10,10); // sur des ellipses
    popStyle();  
}}
    fill(255,50); //bouton déformation rempli
    rect(1*width/8,height-40,width/8,40);
  
} 

///////////////////////////////////////////////////////////////////////////////////  
  
  //BOUTON 3  PONG
  else if(ton[2].clicked()){
    
 //pour i compris entre 0 et la taille de la collection   
 for(int i=0;i<collectionBalle.size();i++){ 
   pushStyle();
   noStroke();
   fill(cam.get(0,height)*4); //les balles prennent les couleurs de la caméra
   //selectionner la balle i du arraylist
    balle b = (balle) collectionBalle.get(i);
    
    // affiche la balle
    b.affiche();   
    // deplaclement de la balle
    b.deplacement();  
    // collision
    b.collision();
    popStyle();
  }

    fill(255,50); //remplissage bouton pong
    rect(2*width/8,height-40,width/8,40);
  }
  
///////////////////////////////////////////////////////////////////////////////////
  
    //BOUTON 4  PLUIE
    else if(ton[3].clicked()){
      pushStyle();
      for (int i = 0; i < drops.length; i++) {
      drops[i].fall(); //afficher tombée
      drops[i].show(); //afficher goutte
      }
      popStyle();
      
    fill(255,50); //bouton pluie
    rect(3*width/8,height-40,width/8,40);
    
    }
    
///////////////////////////////////////////////////////////////////////////////////    
    
    //BOUTON 5  TRAME
    else if(ton[4].clicked()){
    

    for (Circle c : circles) {
        c.update(); //afficher boucle
        c.draw();  //afficher dessin cercle
    }
     
      fill(255,50); //bouton trame
    rect(4*width/8,height-40,width/8,40);

    }
    
///////////////////////////////////////////////////////////////////////////////////    
    
    //BOUTON 6  NEIGE
    else if(ton[5].clicked()){
    pushStyle();
      noStroke();
  fill(45, 23);
  rect(0, 0, width, height);

  randomSeed(seed);

  float fc = float(frameCount);
  strokeWeight(3);
  stroke(255);
  float x, y, maxx, minx, maxy, miny;
  for (float i = 0; i < width; i += cell)
  {
    for (float j = 0; j < height-40; j += cell)
    {
      //fonction aléatoire sur la largeur de travail pour x => i
      x = randomized ? random(width) : i; 
      //fonction aléatoire sur la hauteur de travail pour y => j
      y = randomized ? random(height-40) : j;
      
    //hauteur de vague (cycle ondulatoire) maximale sur x et y
      //max x = coordonnées de X x X x coefficient de rotation en fontion de X + largeur
      maxx =  xx.x * (1 + sin(y/sx.x + fc/fcx.x)) + width; 
      //min x = coordonnées de -X x Y x coefficient de rotation en fonction de y
      minx = -xx.y * (1 + sin(y/sx.y + fc/fcx.y)); 
      x = map(x, 0, width, minx, maxx); //remappage de x 0=> minx et de width => maxx
      if (x > 0 && x < width) { //pour x compris entre 0 et largeur
        maxy =  yy.x * (1 + sin(x/sy.x + fc/fcy.x)) + height;
        miny = -yy.y * (1 + sin(x/sy.y + fc/fcy.y));
        y = map(y, 0, height, miny, maxy); //remappage de y 0=> miny et de width => maxy
        if (y > 0 && y < height-40){ //pour x compris entre 0 et largeur
          point(x,y);
      }
    }
  }}
  
    popStyle();
    fill(255,50); //bouton neige
    rect(5*width/8,height-40,width/8,40);
    
    }
   
///////////////////////////////////////////////////////////////////////////////////    
    
    //BOUTON 7  NOIR & BLANC
    else if(ton[6].clicked()){
    
    pushStyle();
    image(cam, 0,0); 
    filter(GRAY); //filtre noir et blanc
    popStyle();
    
     
    fill(255,50); //bouton N&B
    rect(6*width/8,height-40,width/8,40);
    }
    
///////////////////////////////////////////////////////////////////////////////////    
    
    //BOUTON 8  NÉGATIF
    else if(ton[7].clicked()){
    
    pushStyle();
    image(cam, 0,0);  
    filter(INVERT); //filtre inversion 
    
    popStyle();
    
     
    fill(255,50); //bouton négatif
    rect(7*width/8,height-40,width/8,40);
    }
    
///////////////////////////////////////////////////////////////////////////////////    
   
   else {
       image(cam, 0,0); //si il n'y a plus d'effet on reprend la caméra

  }
}

///////////////////////////////////////////////////////////////////////////////////

void keyPressed() {
  randomized = !randomized;
  if (key == ENTER) { //prendre une photo avec le bouton ENTRÉE
   
    saveFrame("image-"+hour()+minute()+second()+".png");
    //img.save("image-"+hour()+minute()+second()+".png");
  }
}


void mousePressed() {
  initialize();
}

// FIN DU PROGRAMME PRINCIPAL //

Classe bouton

class button{
 //couleurs
  int Red; 
  int Gre;
  int Blu;
 //coordonnées des boutons
  int x;
  int y;
  int si1;
  int si2;
 
 
 button(){
   Red =40;
   Gre =39;
   Blu = 45;
 
 }
 
  //méthode pour remplir les boutons 
  void setFill(int R, int G, int B){
    Red = R;
    Gre = G;
    Blu = B;
  }
   
  //méthode pour dessiner les boutons
  void draw(int x1, int y1, int s1, int s2){
      x = x1;
      y = y1;
      si1 = s1;
      si2 = s2;
      stroke(0);
      fill(Red,Gre,Blu);
      rect(x1, y1, s1, s2);
  }
  
  //États fonction du bouton 
  boolean clicked(){
    if(mouseX > x && mouseX < (x+si1) && mouseY > y && mouseY < (y+si2) ){
        overBox = true;  
    if(!locked) { 
          return true;
        }
    }
    overBox = false;
    return false;
  }
   
}

Classe balle (pour PONG)

class balle{
  // attributs (paramètre) de la balle
  PVector pos; // vecteur position de du centre de la balle
  color c ; // couleur
  int r; // rayon de la balle
  PVector dep; // vecteur deplacement
  
  // constructeur
  balle(PVector _pos, color _c,  int _r, PVector _dep){
 
    pos = _pos;
    c = _c;
    r = _r;  
    dep = _dep;
    
  }

  // méthodes
  // méthode pour afficher la balle
  void affiche(){
    // dessin de la balle
    fill(c);
    ellipse(pos.x,pos.y,2*r,2*r);
  }
  
  //méthode pour déplacer la balle
  void deplacement(){
    //déplacement
    pos.x = pos.x+dep.x;
    pos.y = pos.y+dep.y;
  }
  
  // méthode de collision
  void collision(){ 
    // test de collision suivant x
    if ((pos.x+r>=width) || (pos.x-r<=0)) {
      dep.x = dep.x * (-1);
      
      c = color(random(255),random(255),random(255));
     
      
    }
    // test de collision suivant y
    if ((pos.y+r >= height-40) || ((pos.y-r<=0) )){
          dep.y = dep.y * (-1);

      c = color(random(360),100,100);
      
    } 
  
  }
}

Classe circle (pour TRAME)

class Circle {
  //variables ellipse
    float cx, cy;
    float rx, ry;
    //variable temps
    float rT;
    //variable position des ellipses
    float offset;
    //variable taille des ellipses
    float size;
    
    // constructeur ellipse
    Circle(float x, float y) {
        this.cx = x;
        this.cy = y;
        
        this.rT = 400;
        this.offset = random(-PI/4, PI/8);
        this.size = 50;
    }
    
    //méthode pour remettre à jour les ellipses
    void update() {
      //t => temps en millisecondes
        float t = millis()/rT;
        
        //t += (cx/400)*PI;
        //t += (cy/400)*PI;
        
        t += cos(abs(1-(cx/(width/2))))*TWO_PI;
        t += cos(abs(1-(cy/(height/2))))*TWO_PI;
        t += offset;
        
        //rx = abs((cos(t))*(((cx)/25)+10))-4;
        rx = sin(t)*size;
        ry = rx;
    }
    
    //méthode pour dessiner les points
    void draw() {
      
        if (rx > 0 && ry > 0 && cy < height-40) {
            
          noStroke();
            fill(255,200);
            ellipse(cx, cy, rx/2, ry/2);
        }
    }
}

Classe drop (pour PLUIE)

class Drop {
  //variables chute
  float x;
  float y;
  float z;
  float len;
  float yspeed;
  
  //constructeur
  Drop() {
    x  = random(width);
    y  = random(-500, -50);
    z  = random(0, 20);
    len = map(z, 0, 20, 10, 20);
    yspeed  = map(z, 0, 20, 1, 40);
  }

  //méthode chute
  void fall() {
    y = y + yspeed;
    float grav = map(z, 0, 20, 0, 0.2);
    yspeed = yspeed + grav;

    if (y > height-60) {
      y = random(-500, -100);
      yspeed = map(z, 0, 20, 4, 5.8);
    }
  }
  
  //méthode afficher
  void show() {
    float thick = map(z, 0, 20, 1, 3);
    strokeWeight(thick*2);
    stroke(255,random(100,200));
    line(x, y, x, y+len);
  }
}

Références

Pour l'effet pluie voici le tutoriel :

Pour l'effet trame : https://www.openprocessing.org/sketch/155107

wiki/projets/processing-dsaa1-2017/thomas-leloup.txt · Dernière modification: 2017/05/22 15:06 (modification externe)