PYTHON
TRAITER LES IMAGES - 1ère partie

Objectif

Il existe de nombreuses bibliothèques pour traiter les images en Python :

Nous mettons en œuvre ici la bibliothèque Pillow, pour modifier les couleurs et les positions des pixels.

Comprendre

Dessiner une première image

Nous utilisons le module Image de la bibliothèque Pillow :

from PIL import Image
img=Image.new("RGB",(300,200))

for x in range(0,300) :
  for y in range(0,200) :
    img.putpixel((x,y),(0,255,0))

for x in range(100,150) :
  for y in range(50,150) :
    img.putpixel((x,y),(200,60,60))

for x in range(60,240) :
  for y in range(100,120) :
    img.putpixel((x,y),(80,80,200))

img.save("dessin.png")
img.show()

Résultat :

Insérer une image dans une photographie

Les images de tournage vidéo peuvent être réalisées devant un fond vert. En post-production, ces pixels verts sont remplacés par des pixels d’une photographie, donnant une implantation du personnage dans un nouveau décor. Le but est de réaliser une opération similaire en insérant l'image d'un chat dans un paysage.

Téléchargez les deux images ci-dessous, nommées chat.png et paysage.jpg, placez-les dans le même dossier que celui choisi pour sauvegarder votre code.

   

Identifier un pixel

Testez le code ci-dessous permettant de connaître la valeur attribuée à un pixel.

from PIL import Image
img=Image.open("chat.png")

print(img.format)   # png, gif...
print(img.mode)

print(img.size)
print(img.size[0])  # largeur de l'image en pixels
print(img.size[1])  # hauteur de l'image en pixels

p=img.getpixel((1,1))
print(p)
print(p[0])         # quantité de rouge
print(p[1])         # quantité de vert
print(p[2])         # quantité de bleu

Testez le code ci-dessous permettant de connaître la couleur d'un pixel. Modifiez les coordonnées du pixel pour afficher : Le pixel n'est pas vert.

from PIL import Image
img=Image.open("chat.png")

p=img.getpixel((50,50))

if p==(0,255,0) :
  print("Le pixel est vert")
else :
  print("Le pixel n'est pas vert")

Insérer l'image

Le programme passe en revue chaque pixel de la première image. S'il n'est pas vert, alors il l'insère dans la deuxième image.

from PIL import Image
img1=Image.open("chat.png")
img2=Image.open("paysage.jpg")

for x in range(0,300) :
  for y in range(0,200) :
    p=img1.getpixel((x,y))
    if p!=(0,255,0) :
      img2.putpixel((x,y),p)

img2.save("insertion.jpg")
img2.show()

Pratiquer

Dessiner le drapeau français

En adaptant le code de la première image, sauriez-vous dessiner le drapeau français?

Placer le chat devant le drapeau

En adaptant le code ci-dessus, sauriez-vous dessiner le petit chat devant le drapeau français?

Centrer le chat

Le chat se positionne en ajoutant ou en retranchant des valeurs aux coordonnées x et y. Par exemple :

p=img1.getpixel((x,y))
if p!=(0,255,0) :
  img2.putpixel((x-70,y-20),p)

Attention aux limites! Ci-dessous, pour déplacer le chat vers le bas, la valeur verticale se limite à 199 sous peine de générer une erreur.

p=img1.getpixel((x,y))
if p!=(0,255,0) :
  img2.putpixel((x,min(y+30,199)),p)

Sauriez-vous dessiner le petit chat centré devant le drapeau français?

Réduire la taille du chat

Les dimensions du chat se modifient en multipliant les coordonnées x et y par la même valeur. La fonction round() retourne l'entier le plus proche.

p=img1.getpixel((x,y))
if p!=(0,255,0) :
  img2.putpixel((round(x*0.6),round(y*0.6)),p)

Sauriez-vous dessiner le petit chat devant le drapeau français, en en diminuant la taille?

Améliorer le rendu

Le détourage réalisé reste imparfait. Des pixels verts bordent le contour du chat. Améliorez le résultat en apportant une plus grande tolérance au test :

p=img1.getpixel((x,y))
if p[0]>60 or p[1]<195 or p[2]>60 :
  img2.putpixel((x,y),p)

Agrandissements des rendus avec les pixels comparés aux verts pur et tolérancé :

   

Approfondir

Des dégradés

Les quantités de rouge, vert ou bleu se calculent en fonction des coordonnées x et y. Il faut juste veiller à ce qu'elles soient des entiers compris entre 0 et 255.

Dégradé horizontal

from PIL import Image
img=Image.new("RGB",(300,200))

for x in range(0,300) :
  for y in range(0,200) :
    img.putpixel((x,y),(0,int(x*255/300),0))

img.save("dessin.png")
img.show()

Dégradé vertical

from PIL import Image
img=Image.new("RGB",(300,200))

for x in range(0,300) :
  for y in range(0,200) :
    img.putpixel((x,y),(0,int(y*255/200),0))

img.save("dessin.png")
img.show()

Dégradé multiple

from PIL import Image
img=Image.new("RGB",(300,200))

for x in range(0,300) :
  for y in range(0,200) :
    img.putpixel((x,y),(int(x*255/300),int(y*255/200),0))

img.save("dessin.png")
img.show()

Fusionner des images

Il existe une infinité de solutions pour fusionner deux images et obtenir une sorte de fantôme. Dans l'exemple ci-dessous, on prend les valeurs moyennes des couleurs.

from PIL import Image

img1=Image.open("chat.png")
img2=Image.open("paysage.jpg")

for x in range(0,300) :
  for y in range(0,200) :
    p=img1.getpixel((x,y))
    q=img2.getpixel((x,y))
    if p[0]>60 or p[1]<195 or p[2]>60 :
      img2.putpixel((x,y),(int((p[0]+q[0])/2),int((p[1]+q[1])/2),int((p[2]+q[2])/2)))

img2.save("insertionter.png")
img2.show()

On obtient un résultat similaire en écrivant :

img2.putpixel((x,y),(max(p[0],q[0]),max(p[1],q[1]),max(p[2],q[2])))

Ou encore :

img2.putpixel((x,y),(min(p[0],q[0]),min(p[1],q[1]),min(p[2],q[2])))