Nous allons utiliser le langage de programmation Pythonafin de directement travailler sur les pixels d'une image. Par travailler sur les pixels, il faut déterminer la valeur du canal rouge, la valeur du canal et la valeur du canal bleu pour un pixel donné ou bien encore modifier carrément la couleur d'un pixel.
Avant de commencer à écrire un programme qui nous permettra de travailler sur les pixels d'une image, il est nécessaire de préciser que chaque pixel a des coordonnées $x$, $y$.
Sont présentés ici plusieurs algorithmes, qui permettent de :
On peut demander, sans se compliquer les choses, les effets suivants :
Les programmes présentés n'auront qu'à être adaptés: sur cette page, on se contente d'oberver les effets, puis de voir quel modification du programme a permis ces effets.
Comme vous pouvez le constater sur le schéma ci-dessus, le pixel de coordonnées (0,0) se trouve en haut à gauche de l'image. Si l'image fait 800 pixels de large et 600 pixels de haut, le pixel ayant pour coordonnées (400,300) sera au milieu de l'image.
Pillow est une bibliothèque de traitement d’image, qui est un fork et successeur du projet PIL (Python Imaging Library). Elle est conçue de manière à offrir un accès rapide aux données contenues dans une image, et offre un support pour différents formats de fichiers tels que PPM, PNG, JPEG, GIF, TIFF et BMP.
Pillow dispose de capacités de traitement d’images relativement puissantes, et a pour but d’offrir une solide base à toute application générale de traitement d’images.
from PIL import Image image=Image.open("meduses.png") # on recupere les dimensions de l image longueur,largeur=image.size image2=Image.new(’RGB’,(longueur,largeur)) for y in range(largeur): for x in range(longueur): p=image.getpixel((x,y)) # on accede a l information de chaque pixel rouge=p[0] vert=p[1] bleu=0 # on regle la composante bleu a 0 image2.putpixel((x,y),(rouge,vert,bleu)) image2.save("image2.png") image2.show()
Voici une analyse ligne par ligne du programme ci-dessus :
from PIL from PIL import Image
: pour travailler sur les images nous avons besoin d'une extension de Python (appelé bibliothèque). Cette bibliothèque se nomme PIL.image = Image.open("meduses.png")
: c'est grâce à cette ligne que nous précisons que nous allons travailler avec l'image meduses.png
. Pour travailler avec une autre image, il suffit de remplacer meduses.png
par un autre nom (attention, votre fichier image devra se trouver dans le même dossier que le ficher de votre programme Python).image.size
permet d'accéder aux dimensions de l'image ; ainsi la double affectation longueur,largeurimage.size
mémorise dans les variables longueur
et largeur
les valeurs 400 et 300 (par exemple...).image2=Image.new(’RGB’,(longueur,largeur))
crée une image image2
, en mode RGB (image en couleurs), aux dimensions longueur
et largeur
préalablement définies.p=img.getpixel((x,y))
: cette ligne récupère les valeurs du canal rouge , du canal vert et du canal bleu du pixel de coordonnées ($x$,$y$) ; ce triplet est enregistré dans la variable p
. Dans la suite du programme, p[0]
correspondra à la valeur du canal rouge, p[1]
correspondra à la valeur du canal vert et p[2]
correspondra à la valeur du canal bleu.image2.putpixel((x,y),(rouge,vert,bleu))
: cette ligne affecte les valeurs rouge
, vert
et bleu
au pixel de coordonnées ($x$,$y$) dans l'image image2
Pour commencer, transformons notre image en niveaux de gris.
A noter, notre oeil n'est pas sensible de la même façon aux différentes couleurs. La formule $\text{Gris}=0.2126\times \text{ Rouge } + 0.7152\times \text{ Vert } + 0.0722\times \text{ Bleu }$ rend compte de la manière dont l’œil humain perçoit les trois composantes, rouge, vert et bleu, de la lumière : on remarquera la forte inégalité entre ceux-ci : une lumière verte apparaît plus claire qu'une lumière rouge, et encore plus qu'une lumière bleue.
Plier/Déplier la solution :
from PIL import Image image=Image.open("meduses.png") # on recupere les dimensions de l image longueur,largeur=image.size image2=Image.new(’RGB’,(longueur,largeur)) for y in range(largeur): for x in range(longueur): p=image.getpixel((x,y)) # on accede a l information de chaque pixel rouge=p[0] vert=p[1] bleu=p[2] moyenne=0.2126*rouge+0.7152*vert+0.0722*bleu image2.putpixel((x,y),(moyenne,moyenne,moyenne)) image2.save("image2.png") image2.show()
Eclaircir l'image revient à ajouter une valeur fixe à chacune des composantes Rouge, Vert et Bleu.
Plier/Déplier la solution :
from PIL import Image ajout=50 image=Image.open("meduses.png") # on recupere les dimensions de l image longueur,largeur=image.size image2=Image.new(’RGB’,(longueur,largeur)) for y in range(largeur): for x in range(longueur): p=image.getpixel((x,y)) # on accede a l information de chaque pixel rouge=p[0]+ajout vert=p[1]+ajout bleu=p[2]+ajout image2.putpixel((x,y),(rouge,vert,bleu)) image2.save("image2.png") image2.show()
Appliquer un seuil à une image est simple aussi : il suffit de comparer le niveau de gris à une valeur seuil fixée, et passer en Noir ou Blanc selon le résultat de cette comparaison.
Plier/Déplier la solution :
from PIL import Image seuil=100 image=Image.open("meduses.png") # on recupere les dimensions de l image longueur,largeur=image.size image2=Image.new(’RGB’,(longueur,largeur)) for y in range(largeur): for x in range(longueur): p=image.getpixel((x,y)) # on accede a l information de chaque pixel rouge=p[0] vert=p[1] bleu=p[2] moyenne=0.2126*rouge+0.7152*vert+0.0722*bleu if moyenne<seuil: image2.putpixel((x,y),(255,255,255)) else: image2.putpixel((x,y),(0,0,0)) image2.save("image2.png") image2.show()
En photographie, le sépia est une qualité de tirage qui ressemble au noir et blanc, mais avec des variations de brun, et non de gris. La couleur sépia dans le système RVB est S(94, 38, 18).
Dans la transformation d'une image couleur en une image en nuances de sépia, on tient compte d'un seuil (0 < $\text{seuil}$ < 255), qui sépare le sépia assombri et le sépia éclairci. La transformation se fait alors pixel par pixel en deux temps. Pour chaque pixel, on calcule d'abord un niveau de gris qui est la moyenne $m$ des intensités de rouge, vert et bleu. Puis, si le gris obtenu est foncé ($m$ < $\text{seuil}$), on le remplace par une couleur du segment $\text{NS}$, couleur d'autant plus proche du noir que $m$ est petit. Si le gris est plus clair ($m$ > $\text{seuil}$), il est remplacé par une couleur du segment $\text{SB}$, couleur d'autant plus proche du blanc B que $m$ est grand.
Plier/Déplier la solution :
from PIL import Image seuil=100 image=Image.open("meduses.png") # on recupere les dimensions de l image longueur,largeur=image.size image2=Image.new(’RGB’,(longueur,largeur)) for y in range(largeur): for x in range(longueur): p=image.getpixel((x,y)) # on accede a l information de chaque pixel moyenne=0.2126*rouge+0.7152*vert+0.0722*bleu if moyenne<seuil: k=moyenne/seuil rouge=94*k vert=38*k bleu=18*k else: k=(moyenne-seuil)/(255-seuil) rouge=94+k*(255-94) vert=38+k*(255-38) bleu=18+k*(255-18) image2.putpixel((x,y),(rouge,vert,bleu)) image2.save("image2.png") image2.show()