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 :
/* 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 //
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; } }
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); } } }
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); } } }
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); } }
Pour l'effet pluie voici le tutoriel :
Pour l'effet trame : https://www.openprocessing.org/sketch/155107