Aller au contenu

Manipulation d'image avec Python

Le code suivant permet de télécharger une image et de l'afficher dans Basthon.

Par défaut, l'image sélectionnée est celle-ci :

image de travail

Elle est issue de pexels.

lien_image="https://images.pexels.com/photos/39899/rose-red-tea-rose-regatta-39899.jpeg"


from PIL import Image
import requests
from io import BytesIO

response = requests.get(lien_image)
img = Image.open(BytesIO(response.content))
img.show()

Essayez d'executer ce code. Il doit normalement afficher l'image, après une seconde ou deux, dans la partie graphique de basthon, accessible en cliquant sur le bouton 1. Vous pouvez revenir à la console en cliquant sur le bouton 2.

basthon vue graphique

Dans la suite, nous allons travailler avec le code ci-dessous qui vous est fourni, et qui vous permet d'appliquer une transformation à chaque pixel.

lien_image="https://images.pexels.com/photos/39899/rose-red-tea-rose-regatta-39899.jpeg"

def rouge(pixel):
    return pixel[0]

def vert(pixel):
    return pixel[1]

def bleu(pixel):
    return pixel[2]

def pixel(r, v, b):
    return (r, v, b)

# Cette fonction est à modifier
def transformation(p):
    r = rouge(p)
    v = vert(p)
    b = bleu(p)
    return pixel(r, v, b)


from PIL import Image
import requests
from io import BytesIO

response = requests.get(lien_image)
img = Image.open(BytesIO(response.content))

ratio = max(500/img.width, 500/img.height)

img.resize((int(img.width * ratio), int(img.height * ratio)), Image.Resampling.NEAREST)

for x in range(img.width):
    for y in range(img.height):
        px = img.getpixel((x, y))
        r = transformation(px)
        img.putpixel((x,y), r)

img.show()

La fonction transformation prends en paramètre un pixel p, et retourne la nouvelle valeur de p à mettre dans l'image.

Les fonctions rouge, vert,et bleu prennent en paramètre un pixel et retournent la valeur de son canal rouge, vert et bleu respectivement.

La fonction pixel prends en paramètre les valeurs des canaux rouge, vert, et bleu d'un pixel et retournent la valeur du pixel.

La transformation actuelle :

# Cette fonction est à modifier
def transformation(p):
    r = rouge(p)
    v = vert(p)
    b = bleu(p)
    return pixel(r, v, b)

Ne fait aucun changement sur le pixel.

Essayons de changer la ligne

return pixel(r, v, b)

en

return pixel(r, b, v)

Ce qui inverse les valeurs des canaux bleu et vert de chaque pixel de l'image. Observez le résultat.

Seuillage selectif

On va essayer de ne garder que la rose, et de passer le reste de l'image en noir.

Dans un premier temps, on va passer tous les pixels en noir.

Activité

Modifiez la transformation pour qu'elle passe tous les pixels en noir.

Rappel : le noir est une couleur dont les canaux rouge, vert, et bleu sont tous à 0.

def transformation(p):
    r = rouge(p)
    v = vert(p)
    b = bleu(p)
    return pixel(0, 0, 0)

Maintenant, essayons de rendre noirs le pixels qui n'appartiennent pas à la rose, c'est à dire qui ne sont pas rose.

Activité

Modifiez la transformation pour qu'elle passe tous les pixels en noir, sauf ceux qui appartiennent à la rose.

Dans notre image, la rose est la seule partie qui a un canal rouge avec une valeur supérieure à 145.

Il vous faut utiliser un If, et vérifier que le canal rouge est au dessus de la valeur minimale.

def transformation(p):
    r = rouge(p)
    v = vert(p)
    b = bleu(p)
    if r > 145:
        return pixel(r, v, b)
    else :
        return pixel(0, 0, 0)

Désaturation ...

La désaturation consiste à transformer les couleurs en nuances de gris, sous forme d'une valeur de luminosité qui sera la même pour chaque canal.

Pour calculer cette valeur, on peut commencer par faire la moyenne des des canaux rouge, vert, et bleu.

Activité

Modifiez la transformation pour qu'elle passe les pixels en nuances de gris.

n'oubliez pas de transtyper la valeur en entier int(lavaleur) avant de l'ajouter aux canaux.

def transformation(p):
    r = rouge(p)
    v = vert(p)
    b = bleu(p)
    g = int(r + v + b / 3)
    return pixel(g, g, g)

On peut voir que certains pixels, en particulier ceux de la rose, apparaissent trop lumineux. Pour corriger ça, on va pondérer chaque canal dans le calcul de la moyenne.

Activité

Modifiez la transformation pour qu'elle passe les pixels en nuances de gris, en utilisant une moyenne pondérée.

Par exemple, vous pouvez utiliser : - 0.3 pour le rouge - 0.6 pour le vert - 0.1 pour le bleu

N'hésitez pas à changer ces trois valeurs pour voir ce qui change dans le résultat.

Attention, en fonction de comment vous choisissez les poids de votre moyenne, à bien tout ramener à une valeur entre 0 et 255.

def transformation(p):
    r = rouge(p)
    v = vert(p)
    b = bleu(p)
    g = int(r * 0.3 + v * 0.6 + b * 0.1)
    return pixel(g, g, g)

... sauf la rose

Activité

Modifiez la transformation pour qu'elle passe les pixels en nuances de gris, en utilisant une moyenne pondérée, tout en préservant la couleur originale de la rose.

def transformation(p):
    r = rouge(p)
    v = vert(p)
    b = bleu(p)
    if r > 145:
        return pixel(r, v, b)
    else :
        g = int(r * 0.3 + v * 0.6 + b * 0.1)
        return pixel(g, g, g)

Extension

  • Essayez de colorer aléatoirement certains pixels. C'est ce que l'on appelle du bruit.
  • Essayez d'appliquer des traitements similaires à d'autres images.
  • (Difficile !) Essayez de modifier le code de façon à ce que la fonction transformation reçoive les dimensions (hauteur et largeur) de l'image et les coordonnées du pixel en plus de sa valeur. Trouvez un traitement qui utilise ces informations.