Page précédente


Algorithmique et traitement de l'image

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.

Manipulations sur les pixels à l'aide de Python

Présentation

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.

L'image de départ

Manipuler les pixels avec le module PIL de Python

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 :

Exécuter des filtres simples

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()