Imagetutorial de programmation |
|
La Trahison des images, René Margritte 1929 |
Dans ce tutorial, nous allons aborder l'image. A part le simple affichage d'image, nous allons regarder l'image de plus près pour comprendre qu'est ce que c'est un image numérique. René Margritte au début du 20ème siècle s'est interrogé sur la dialectique de la peinture et sa représentation. Nous allons décortiquer l'image numérique et ses possibles transformations. Car enfin de compte, une image numérique est simplement un liste de points colorés.Ces différents formes de transformation d'image s'appelle image processing (traitement d'image - rien avoir avec Processing)
Wikipedia: Image processing
Wikipedia: traitement d'image
Processing exemple du traitement d'image(voir également les exemples suivants)
Afin d'afficher une image, il faut d'abord déclarer une variable de type image. Contrairement au variable de type primitif (int float, boolean..) ici il s'agit d'une variable d'objet, il existe donc une class de ce nom. Notre class s'appelle PImage (on remarque la majuscule pour un class). Le reste est comme d'habitude, on lui donne un nom.
Ensuite il faut d'abord mettre un image dans le dossier du sketch, le mieux dans un sous-dossier"data" (Pour ouvrir le dossier du sketch, on passe par le menu "Sketch"-> Show Sketch Folder. Un autre manière plus rapide est de glisser le photo dans la fenêtre de Processing, et Processing se charge de créer le dossier ainsi le copie de l'image.
L'étape suivant est de charger la photo dans la mémoire avec la méthode loadImage. Cela on fait d'avantage au setup sinon le photo sera charger à chaque frame. Et enfin on l'affiche avec la méthode image() et comme argument la variable de l'image ainsi que sa position x, y.
PImage monImage;
void setup(){
size
(300,209);
monImage=loadImage("margritte.jpg")
image(monImage, 0,0);
}
Un autre méthode est d'afficher l'image avec la méthode background. Ceci est intéressant quand on affiche quelque chose dynamique sur le photo. Attention, la taille du photo doit avoir la même taille que la fenêtre
PImage monImage;
int taille;
void setup(){
size(300,209);
monImage = loadImage("margritte.jpg");
noFill();
;
void draw(){
background(monImage);
taille=(taille+1)%60;
println(taille);
ellipse(280,160, taille*1.5, taille);
}
Comme toutes les class, PImage a aussi un certaine nombre de méthodes propre. Dans la référence de Processing sous PImage vous trouverez l'ensemble de ces méthodes. Une fois nous avons crée une instance de la class PImage, on peut utiliser ces méthodes comme de n'importe quelle autre class. Par exemple si on veut connaître la largeur de notre image, nous allons utiliser la méthode width de la class PImage. Après avoir que l'image est 'loadé', nous accédons à sa largeur par nomDuObjet.width. Le code suivant permet que la taille de la fenêtre s'adapte automatiquement à la taille de l'image.
PImage img;
void setup(){
img =loadImage("margritte.jpg");
int w = img.width;
int h = img.height;
size(w, h);
image(img, 0,0);
}
Les listes ou array peuvent stocker n'import quel type de donnée, aussi donc des objets. Ainsi on peut programmer un slideshow ou des images défilent successivement. Nous déclarons d'abord notre liste du type PImage pour 4 photos.
PImage[] img= new PImage[4];
int counter, counter1; // deux variables qui permet de modifier la fréquence de //changement d'images ainsi que l'index d'image.
Ensuite nous définissons la taille de la fenêtre à la taille de nos images et chargeons les images dans le mémoire avec un boucle. Chaque liste à un variable qui s'appelle lenght qui stocke les nombres des emplacements dans un liste. Pour accéder à cette variable on écrit nom_de_la_liste[ point]lenght.
void setup(){
size(600, 400);
for(int i=0; i<img.length; i++){
img[i]=loadImage("pic"+i+".jpg");
}
}
Il faut évidement penser à mettre le quatre photos avec le nom pic0.jpg, pic1.jpg, pic2.jpg, pic3.jpg
Et enfin on affiche les images avec une cadence de tous les 50 frames
void draw(){
count1++;
if (count1>50){
count1=0;
count++;
if (count>2) count=0;
}
image(img[count],0, 0, width, height);
}
Si on veut changer une image pixel par pixel, il y a deux possibilités, soit on passe par la matrice de deux dimensions soit en passe par un liste. Nous aborderons les deux approches.
Traitement d'image par boucle imbriqué |
Une fois, nous avons chargé l'image, nous créons un boucle imbriqué et on récupère la couleur de chaque pixel. Ensuite on va invertir la valeur de rouge avec le vert et du bleu
for (int y=0; y<height; y++){
for(int x=0; x<width; x++){
color c = get(x, y);// prend la couleur de chaque pixel
float r=red(c);// decompose la couleur dans ces composants rgb
float g=green(c);
float b=blue(c);
color invert_c= color(g,b,r);// inverti les couleur
set( x,y,invert_c); // remet les pixels avec la couleur inverti
}
}
Traitement d'image avec pixels[ ] |
Un autre méthode plus rapide est de faire recours à l'array qui fait partie de la class PImage. La liste pixels[ ] stocke les couleurs de chaque pixels qui est dans la matrice. La différence fondamentale par rapport à la procédure avec la boucle imbriqué est que les couleurs sont stocké dans un liste 1D comme on le voit dans la graphique en haut. C'est à dire que le nombre des emplacement dans la liste pixels[ ] correspond à width*height. Au lieu d'écrire width*height on peut aussi faire recours à la variable length.
Pour pouvoir utiliser pixels[] il faut utiliser les méthodes loadPixels() et après le traitement updatePixels( );
Le traitement suivant est simplement la transformation d'une photo en couleur en une photo en noir et blanc. Pour faire cela on additionne tous les valeurs de rgb d'un pixel et ensuite en le divise la somme en 3 qui donne la valeur de gris.
PImage img;
void setup(){
size(400,312);
img=loadImage("camel.jpg");
image(img, 0, 0);
loadPixels();
for (int i=0; i<pixels.length; i++){// pixels.length=width*height
float r= red(pixels[i]);
float g= green(pixels[i]);
float b= blue(pixels[i]);
color gris = color ((r+g+b)/3);//
pixels[i]=gris;
}
updatePixels();
}
Parfois on est amené à utiliser la matrice et le pixels[] pour le même pixel. La conversion de l'un à l'autre est simple. L'equivalent d'un position x,y dans l'array est
pixels[int]=y*width+x;
et l'array au matrice:
x=pixels[int]%width;
y=(pixels[int]-x)/width;
Nous avons vu dans le cours sur la couleur comment prendre la couleur d'un pixels. Au lieu d'un seul pixel, on peut aussi utiliser la méthode get( ) pour prendre une surface. La valeur de retour est cette fois-ci évidement pas une couleur mais une image. Les paramètres de ce get() est sa position x et y, et la largeur et hauteur, comme pour le rect().
PImage img;// une variable de type image pour l'image et pour l'extrait
PImage oeil;
int x;
void setup(){
size(400,312);
img=loadImage("camel.jpg");
oeil= get(250, 120, 70,50);// je copie l'image à la position 250,120 avec une largeur et hauteur de 70 et 50.
}
void draw(){
background(img); // j'affiche le premier image en background
image(oeil, ++x % width, 120);// le deuxième image fait le scan, x++ et ++x seulement l'ordre est différent.
}.