Les images
Notre espace de travail
On travaille avec Processing en mode Python et/ou avec EduPython
Une image c'est quoi ?
Nous travaillerons dans un premier temps avec cette image | ![]() |
Une fois téléchargée, un clic droit dessus pour accéder aux propriétés.
Il est indiquée que ses dimensions sont de
pixels.
pixel : De l'anglais pixel, mot forgé (1969) à partir de pix (variante de pics, pluriel de pic, abréviation de picture « image ») et de el(ement) (« élément »), littéralement « élément d'image ».
Cela signifie que cette image est constituée de
pixels qui contiennent chacun une couleur.
Une couleur étant une combinaison des trois couleurs fondamentales : le rouge, le vert et le bleu.
On considère donc qu'une image est un tableau de pixels qui contiennent des couleurs.
Simulation : Faire afficher une image
Dans Processing en mode Python, il suffit de glisser-déposer l'image dans le sketch ( celle-ci sera automatiquement mise dans un dossier 'data')
Glissez-déposez l'image de la Joconde dans le sketch. vérifiez dans l'onglet "sketch" / "Afficher le dossier" que l'image s'y trouve bien.. |
On crée une fenêtre d'affichage aux dimensions de cette image, on charge l'image dans une variable, puis on l'affiche
size(408,320)
img=loadImage("data/joconde.png")
image(img,0,0)
L'instruction : image(img,0,0)
signifie : afficher l'image se trouvant dans ' img' aux coordonnées (0,0) ( il s'agit du coin supérieur gauche de l'image que l'on place aux coordonnées (0,0))
On peut modifier la taille de l'image à l'affichage : en complétant l'instruction : image(img,0,0,largeur, hauteur)
Testez ce programme :
size(408,320)
img=loadImage("data/joconde.png")
image(img,0,0,102,80)
image(img,102,0,102,80)
Faites en sorte qu'il y ait 16 images de la Joconde affichées dans la fenêtre.
Il faut obtenir ce résultat : | ![]() |
Complément : Faire afficher une image dans Edupython
Dans EduPython l'affichage d'une image dans une fenêtre, nécessite l'utilisation de bibliothèques ( il y en a plusieurs : Matplotlib, Pygame, Pylab, etc... )
La manipulation d'images se fera avec la bibliothèque 'pillow'
Dans un dossier qui contient notre image de la Joconde enregistrez et exécutez le programme suivant
# Créé par vstep, le 31/01/2019 en Python 3.4
from PIL import Image
from pylab import *
# chargement de l'image
img=Image.open("joconde.png")
# affichage
# non affichage des axes
xticks([]), yticks([])
title('La joconde')
plt.imshow(img)
show()
Accès aux pixels d'une image (Processing)
Lorsque l'on charge une image, les pixels sont automatiquement enregistrés dans une liste.
Prenons l'exemple d'une image de
Par exemple : le pixel d'index 65 à pour coordonnées ( 5 ; 6) Notez bien que : La 1ère ligne est la ligne 0 et la 1ère colonne est la colonne 0 |
Lors du chargement de l'image ce tableau est enregistré en liste...
Comment obtenir l'index d'un pixel à partir de ses coordonnées ?
Par exemple : la case de coordonnées (5,6) donne l'index 65.
La formule permettant de passer des coordonnées à l'index est : (abscisse) +(ordonnée *largeur de l'image)
65=5+6*10
Dans une image de
|
Le programme ci-dessous affiche les composantes (r,g,b) du pixel de coordonnées ( 80 ; 150) de l'image de la Joconde et une petite ellipse pour le localiser sur l'image
size(408,320)#taille de la fenêtre
img=loadImage("data/joconde.png")#chargement de l'image
image(img,0,0)#affichage de l'image
index=80+150*408# calcul de l'index
r=red(img.pixels[index])#composante rouge du pixel
g=green(img.pixels[index])
b=blue(img.pixels[index])
noFill()#pas de remplissage
stroke(255,255,255)#bord blanc
ellipse(80,150,5,5)#ellipse
print(r,g,b)#affichage dans la console de la couleur(r,g,b)
Lecture de l'instruction : r=red(img.pixels[index])
Mettre dans la variable 'r' la composante rouge(red) du pixel de l'image se trouvant dans la variable 'img' à l'index (80+150*408)
Faites afficher la couleur du pixel de coordonnées ( 400 ; 200)
Simulation : Modification des pixels d'une image (Processing)
Dans cet exemple nous allons modifier tous les pixels rouge de l'image, (on les mets tous à 255)
On va également délocaliser le calcul de l'index dans une fonction.
On va également créer une image vide, que l'on remplira avec les pixels modifiés de l'image de la Joconde.
On affichera les deux images.
def calculindex(x,y):#le calcul de l'index
return x+y*408
def setup():
size(408,320)# taille de la fenêtre
img=loadImage("data/joconde.png")#chargement de l'image
img2=createImage(408,320,RGB)# création d'une image vide
for x in range(0,408,1):# pour tous les pixels de l'image
for y in range(0,320,1):
index=calculindex(x,y)# calcul de l'index
r=red(img.pixels[index])#composante rouge du pixel de l'image
g=green(img.pixels[index])
b=blue(img.pixels[index])
img2.pixels[index]=color(255,g,b)# remplissage de l'image vide
image(img2,0,0)# affichage des images
image(img,0,0,102,80)
Faites de même avec les pixels vert
Et les bleus
Complément : Modification des pixels d'une image ( EduPython)
La bibliothèque 'pillow' permet de s'affranchir de la recherche de l'index d'un pixel dans la liste.
Pour atteindre la couleur ( r, v, b) d'un pixel, il suffit d'utiliser la commande :
r,v,b,a=img.getpixel((x,y))
Cette commande stocke dans les variables r,v
et b
les composantes rouge, verte et bleue du pixel de coordonnées (x, y).
Il y a cependant, une contrainte : les pixels de notre image possède une valeur "a" ( le taux d'opacité de l'image ) également codé de 0 (totalement opaque) à 255 sans opacité.
Dans un dossier qui contient notre image de la Joconde enregistrez et exécutez le programme suivant
# Créé par vstep, le 31/01/2019 en Python 3.4
from PIL import Image
from pylab import *
# chargement des images
img=Image.open("joconde.png")
largeur,hauteur=img.size
#création d'une image vide
img2=Image.new('RGB',(largeur,hauteur))
#traitement
for y in range(hauteur):
for x in range(largeur):
r,v,b,a=img.getpixel((x,y))
img2.putpixel((x,y),(255,v,b))
#affichage, deux images dans la même fenêtre( l'originale et la modifiée)
subplot(1,2,1)
xticks([]), yticks([])
title('La joconde')
plt.imshow(img)
subplot(1,2,2)
xticks([]), yticks([])
title('La joconde(filtre rouge)')
plt.imshow(img2)
show()
Faites de même avec les pixels vert
Et les bleus
Simulation : Mettre une image en niveau de gris (Processing)
Toutes les nuances de gris s'obtiennent par des couleurs de la forme ( c , c , c) c'est à dire que les composantes rouge, verte et bleue ont la même valeur.
Du blanc : (255,255,255) jusqu'au noir (0,0,0).
Pour mettre une image en niveau de gris, il suffit donc de remplacer les composantes (r ,g , b) de chaque pixels par leur moyenne :
.
Modifiez le programme précédent pour qu'il affiche la Joconde en niveau de gris.
Complément : Mettre une image en niveau de gris (Edupython)
Réalisez le programme dans EduPython
Simulation : Mettre une image en noir et blanc (Processing)
Pour mettre une image en noir et blanc, il faut partir d'une image en niveau de gris, puis si la valeur calculée est supérieure à un certain seuil ( par exemple 127) alors on la met en blanc (255) sinon on la met en noir (0)
En notant c la moyenne calculée dans le programme précédent, il faudra rajouter dans le programme :
if c>127:
c=255
else:
c=0
Complément : Mettre une image en noir et blanc (EduPython)
On utilisera le programme du niveau de gris (EduPython) auquel on rajoutera les modifications nécessaires
Complément : Travail à faire
Réalisez un programme qui transforme chaque pixel de l'image en son complément à 255.
C'est à dire : ( r,v,b) ---> (255-r, 255-v , 255-b )
Simulation : Filtrage par seuil (Processing)
Le filtrage par seuil consiste, pour chaque pixel d'une image, d'imposer une valeur à l'une des composantes si celle-ci est inférieure(ou supérieure) à un seuil que l'on aura fixé.
Par exemple le programme ci-dessous met à zéro les composantes rouges si elles sont inférieures à 127 et à 255 sinon (sans toucher aux autres composantes)
def calculindex(x,y):#le calcul de l'index
return x+y*408
def setup():
size(408,320)# taille de la fenêtre
img=loadImage("data/joconde.png")#chargement de l'image
img2=createImage(408,320,RGB)# création d'une image vide
for x in range(0,408,1):# pour tous les pixels de l'image
for y in range(0,320,1):
index=calculindex(x,y)# calcul de l'index
r=red(img.pixels[index])#composante rouge du pixel de l'image
g=green(img.pixels[index])
b=blue(img.pixels[index])
if r<127:
r=0
else:
r=255
img2.pixels[index]=color(r,g,b)# remplissage de l'image vide
image(img2,0,0)# affichage des images
image(img,0,0,102,80)
Réalisez d'autres filtrages par seuil
Complément : Filtrage par seuil (Edupython)
Le programme précédent adapté :
# Créé par vstep, le 31/01/2019 en Python 3.4
from PIL import Image
from pylab import *
# chargement des images
img=Image.open("joconde.png")
largeur,hauteur=img.size
#création d'une image vide
img2=Image.new('RGB',(largeur,hauteur))
#traitement
for y in range(hauteur):
for x in range(largeur):
r,v,b,a=img.getpixel((x,y))
if r>127:
r=255
else:
r=0
img2.putpixel((x,y),(r,v,b))
#affichage
subplot(1,2,1)
xticks([]), yticks([])
title('La joconde')
plt.imshow(img)
subplot(1,2,2)
xticks([]), yticks([])
title('La joconde(filtre par seuil)')
plt.imshow(img2)
show()
Réalisez d'autres filtrages par seuil
Définition : Modification par convolution (Processing)
Modifier une image par convolution consiste à remplacer les composantes de chaque pixel par une combinaison des valeurs des composantes des pixels voisins et de lui-même (tout un programme ...)
On ne prendra en compte que les pixels qui ont 8 voisins :
Par exemple : On va appliquer la modification suivante : (filtre passe haut)
Voici le programme :
#fonction qui renvoie l'index
def calculindex(x,y):
return x+y*408
def setup():
size(408,320)
img=loadImage("data/joconde.png")#chargement de l'image
img2=createImage(408,320,RGB)#création d'une image vide
for x in range(1,407,1):# pour tous les pixels (sauf ceux des bords qui n'ont pas 8 voisins)
for y in range(1,319,1):
index1=calculindex(x-1,y-1)#calculs des index
index2=calculindex(x,y-1)
index3=calculindex(x+1,y-1)
index4=calculindex(x-1,y)
index5=calculindex(x,y)
index6=calculindex(x+1,y)
index7=calculindex(x-1,y+1)
index8=calculindex(x,y+1)
index9=calculindex(x+1,y+1)
#modification des pixels
r=-red(img.pixels[index2])-red(img.pixels[index4])+5*red(img.pixels[index5])-red(img.pixels[index6])-red(img.pixels[index8])
g=-green(img.pixels[index2])-green(img.pixels[index4])+5*green(img.pixels[index5])-green(img.pixels[index6])-green(img.pixels[index8])
b=-blue(img.pixels[index2])-blue(img.pixels[index4])+5*blue(img.pixels[index5])-blue(img.pixels[index6])-blue(img.pixels[index8])
img2.pixels[index5]=color(r,g,b)#remplissage de l'image vide
image(img2,0,0)#affichage des images
image(img,0,0,102,80)
Complément : Modification par convolution (Edupython)
Le même avec Edupython
# Créé par vstep, le 01/02/2019 en Python 3.4
from PIL import Image
from pylab import *
# chargement des images
img=Image.open("joconde.png")
largeur,hauteur=img.size
#création d'une image vide
img2=Image.new('RGB',(largeur,hauteur))
#traitement
for y in range(1,hauteur-1,1):
for x in range(1,largeur-1,1):
r1,v1,b1,a1=img.getpixel((x-1,y-1))
r2,v2,b2,a2=img.getpixel((x,y-1))
r3,v3,b3,a3=img.getpixel((x+1,y-1))
r4,v4,b4,a4=img.getpixel((x-1,y))
r5,v5,b5,a5=img.getpixel((x,y))
r6,v6,b6,a6=img.getpixel((x+1,y))
r7,v7,b7,a7=img.getpixel((x-1,y+1))
r8,v8,b8,a8=img.getpixel((x,y+1))
r9,v9,b9,a9=img.getpixel((x+1,y+1))
#modification des pixels
r=-r2-r4+5*r5-r6-r8
v=-v2-v4+5*v5-v6-v8
b=-b2-b4+5*b5-b6-b8
img2.putpixel((x,y),(r,v,b))
#affichage
subplot(1,2,1)
xticks([]), yticks([])
title('La joconde')
plt.imshow(img)
subplot(1,2,2)
xticks([]), yticks([])
title('La joconde filtre passe haut')
plt.imshow(img2)
show()
Simulation : Réaliser un flou par convolution
Complément :
Réalisez une autre transformation avec la matrice :
Simulation : Détection des contours
Il s'agit encore d'une modification par convolution à réaliser avec cette image et cette matrice :
Complément : Soyez créatifs
Inventez une transformation par convolution...
Simulation : Extraction de contours
from PIL import Image
from pylab import *
# chargement des images
img=Image.open("port.png")
largeur,hauteur=img.size
#création d'une image vide
img2=Image.new('RGB',(largeur,hauteur))
def distance(a,b,c,e,f,g):
return (a-e)**2+(b-f)**2+(c-g)**2
#traitement
for y in range(1,hauteur-1,1):
for x in range(1,largeur-1,1):
r1,v1,b1,a1=img.getpixel((x-1,y-1))
r2,v2,b2,a2=img.getpixel((x,y-1))
r3,v3,b3,a3=img.getpixel((x+1,y-1))
r4,v4,b4,a4=img.getpixel((x-1,y))
r5,v5,b5,a5=img.getpixel((x,y))
r6,v6,b6,a6=img.getpixel((x+1,y))
r7,v7,b7,a7=img.getpixel((x-1,y+1))
r8,v8,b8,a8=img.getpixel((x,y+1))
r9,v9,b9,a9=img.getpixel((x+1,y+1))
moyenne=distance(r5,v5,b5,r1,v1,b1) + distance(r5,v5,b5,r2,v2,b2)+distance(r5,v5,b5,r3,v3,b3)+distance(r5,v5,b5,r4,v4,b4)+distance(r5,v5,b5,r6,v6,b6)+distance(r5,v5,b5,r7,v7,b7)+distance(r5,v5,b5,r8,v8,b8)+distance(r5,v5,b5,r9,v9,b9)
moyenne=moyenne//8
if moyenne>250:
img2.putpixel((x,y),(0,0,0))
else:
img2.putpixel((x,y),(255,255,255))
#affichage
subplot(1,2,1)
xticks([]), yticks([])
title('l\'originale')
plt.imshow(img)
subplot(1,2,2)
xticks([]), yticks([])
title('Ses contours')
plt.imshow(img2)
show()
Simulation : Modifications géométriques
Voici un programme qui 'renverse' la Joconde...
Processing
def calculindex(x,y):#le calcul de l'index
return x+y*408
def setup():
size(408,320)
img=loadImage("data/joconde.png")
img2=createImage(408,320,RGB)
for x in range(0,408,1):
for y in range(0,160,1):
index1=calculindex(x,y)# calcul des index des pixels à inverser
index2=calculindex(x,319-y)
img2.pixels[index1]=img.pixels[index2]
img2.pixels[index2]=img.pixels[index1]
image(img2,0,0)
image(img,0,0,102,80)
EduPython
# Créé par vstep, le 01/02/2019 en Python 3.4
from PIL import Image
from pylab import *
# chargement des images
img=Image.open("joconde.png")
largeur,hauteur=img.size
#création d'une image vide
img2=Image.new('RGB',(largeur,hauteur))
#traitement
for y in range(0,hauteur//2,1):
for x in range(0,largeur,1):
r1,v1,b1,a1=img.getpixel((x,y))
r2,v2,b2,a2=img.getpixel((x,319-y))
img2.putpixel((x,y),(r2,v2,b2))
img2.putpixel((x,319-y),(r1,v1,b1))
#affichage
subplot(1,2,1)
xticks([]), yticks([])
title('La joconde')
plt.imshow(img)
subplot(1,2,2)
xticks([]), yticks([])
title('La joconde à l'envers')
plt.imshow(img2)
show()
Complément : Élimination du 'bruit' dans une image
Pour éliminer le bruit on parcourt l'image et on remplace chaque pixel par la médiane de ce pixel et de ses 8 voisins.
C'est ce qu'on appelle un filtre médian.
Comme c'est une image en niveaux de gris, il suffit de le faire pour l'une des composantes ( par exemple le rouge)
On chargera les composantes rouges du pixel et de ses 8 voisins dans une liste.
On ordonnera cette liste, la médiane sera donc le 5ème élément (voir le cours de maths..)
Voilà le programme : (attention au nom de l'image téléchargée qui peut être différent de celle du programme..)
Processing
def calculindex(x,y):
return x+y*256
def setup():
size(512,256)
img=loadImage("data/image-lena.png")
img2=createImage(256,256,RGB)
for x in range(1,255,1):
for y in range(1,255,1):
liste=[]#création de la liste
index1=calculindex(x-1,y-1)
index2=calculindex(x,y-1)
index3=calculindex(x+1,y-1)
index4=calculindex(x-1,y)
index5=calculindex(x,y)
index6=calculindex(x+1,y)
index7=calculindex(x-1,y+1)
index8=calculindex(x,y+1)
index9=calculindex(x+1,y+1)
liste.append(red(img.pixels[index1]))
liste.append(red(img.pixels[index2]))
liste.append(red(img.pixels[index3]))
liste.append(red(img.pixels[index4]))
liste.append(red(img.pixels[index5]))
liste.append(red(img.pixels[index6]))
liste.append(red(img.pixels[index7]))
liste.append(red(img.pixels[index8]))
liste.append(red(img.pixels[index9]))
liste.sort()#tri de la liste
r=liste[4]# on récupère le 5ème élément
img2.pixels[index5]=color(r,r,r)
image(img,0,0)
image(img2,256,0)
EduPython
# Créé par vstep, le 01/02/2019 en Python 3.4
from PIL import Image
from pylab import *
# chargement des images
img=Image.open("lenna.png").convert("RGB")
largeur,hauteur=img.size
#création d'une image vide
img2=Image.new('RGB',(largeur,hauteur))
print(largeur)
#traitement
for y in range(1,hauteur-1,1):
for x in range(1,largeur-1,1):
liste=[]
r1,v1,b1=img.getpixel((x-1,y-1))
liste.append(r1)
r2,v2,b2=img.getpixel((x,y-1))
liste.append(r2)
r3,v3,b3=img.getpixel((x+1,y-1))
liste.append(r3)
r4,v4,b4=img.getpixel((x-1,y))
liste.append(r4)
r5,v5,b5=img.getpixel((x,y))
liste.append(r5)
r6,v6,b6=img.getpixel((x+1,y))
liste.append(r6)
r7,v7,b7=img.getpixel((x-1,y+1))
liste.append(r7)
r8,v8,b8=img.getpixel((x,y+1))
liste.append(r8)
r9,v9,b9=img.getpixel((x+1,y+1))
liste.append(r9)
liste.sort()
r=liste[4]
img2.putpixel((x,y),(r,r,r))
#affichage
subplot(1,2,1)
xticks([]), yticks([])
title('Lenna')
plt.imshow(img)
subplot(1,2,2)
xticks([]), yticks([])
title('Lenna_filtre médian')
plt.imshow(img2)
show()
Comment faire pour améliorer le résultat...