SNT Photo Filtrage

Identification

Infoforall

4 - Filtrage d'une image


Nous allons voir comment modifier les pixels des photos pour obtenir différents effets.

Image contenant beaucoup de rouge
Image de base libre de droit : le Palais des congrès de Montréal

Mise en évidence d'une couleur, transformation en noir et blanc, détection de contour ...

Cela vous permettra de voir ce qu'on peut faire avec un langage de programmation comme Python.

Documents de cours : open document ou pdf

1 - Prise en main des images avec Python

RAPPEL

Thonny permet de travailler avec Python dans un environnement qui permet de voir le contenu des variables, et d'avoir accès au même endroit à :

  • la fenêtre de programmation où on tape des instructions qu'on pourra exécuter plusieurs fois. C'est la partie en haut à gauche ci-dessous qui contient les mots largeur et hauteur.
  • la console où on écrit des instructions qui seront exécutées immédiatement. C'est la partie en bas à gauche qui contient 3 chevrons >>>. Ces chevrons forment l'invite de commande : le système précise qu'il est prêt à exécuter ce qu'on va taper.
  • la zone de visualisation des variables à droite. Elle permet de voir ce qui est en mémoire, ou pas.
Thonny

Nous allons maintenant manipuler des images et changer les valeurs RGB des différents pixels.

Nous avons vu dans l'activité précédente qu'une image n'est qu'une succession de nombres.

Pour manipuler les images avec Python et Thonny, il faut possèder un module spécifique, qui gère les images : Pillow.

Introduction (1/3) INSTALLATION DE BASE

01-A (action)° Ouvrir Thonny. Dans le menu Affichage ou View, sélectionner variables.

Cela devrait ouvrir une zone à droite qui vous montrera les choses en mémoire.

Commençons par voir si vous disposez du module Pillow.

01-B (action)° Tapez ceci dans la console pour voir si cela déclenche une erreur.

>>> from PIL import Image

Si vous avez une erreur, vérifier d'abord que vous avez bien géré les majuscules / minuscules puis si on vous signale qu'il manque le module, lire et utiliser la note ci-dessous.

Installer un module avec Thonny

Si cela déclenche une erreur, c'est que vous n'avez pas installé la bibliothèque Pillow. Pour l'installer dans Thonny :

  • Ouvrir le menu Tool/Outils en haut vers la droite dans Thonny
  • Sélectionner Manage Packages/Gérer les Paquets
  • Faire une recherche sur Pillow puis installer la bibliothèque. Ca peut être un peu long.
Vue Manage Packages

01-C (action)° Réaliser les actions suivantes :

  • Créer un répertoire nommé SNT-photographie sur votre espace de travail.
  • Téléchargez une image de type .png ou .jpg sur le Web et placez la dans le répertoire nommé SNT-photographie. Choisissez une image possèdant pas mal de couleurs différentes si possible.

Par exemple, pour illustrer ce cours, j'ai choisi ceci :

Image contenant beaucoup de rouge
Image de base libre de droit : le Palais des congrès de Montréal

Introduction (2/3) AFFICHER DES INFORMATIONS SUR L'IMAGE

RAPPEL : profondeur
  • Image en nuance de gris uniquement : 1 couche donc 1 octet par pixel, ou 8 bits par pixel
  • Image en couleur : 3 couches RGB donc 3 octets par pixel, ou 24 bits par pixel
  • Image avec transparence : 4 couches RGBA donc 4 octets par pixel, ou 32 bits par pixel.

La couche A de transparence se nomme la couche ALPHA : à 0, ce pixel n'est absolument pas transparent. Avec 255, il est totalement transparent.

01-D° Réaliser les deux actions ci-dessous qui vont permettre à Python de vous donner certaines informations sur votre image.

  1. Enregistrer au même endroit que votre image le programme ci-dessous sous le nom gestion.py, donc dans le répertoire SNT-photographie.
  2. 📁 SNT-photographie

    📄 gestion.py

    📄 votre_image.png

  3. dans le programme Python, modifier la ligne 5 pour que la variable ref_image fasse référence aux bons nom et extension de votre fichier-image. RAPPEL : le nom doit être placé entre guillemets pour faire comprendre à Python qu'on lui transmet un string, une chaîne de caractère, un texte.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from PIL import Image # importation de Image, permettant de gérer... les images AFFICHAGE = True # Booléen True ou False. Si True, l'image apparait en fin de programme. ref_image = Image.open("image.jpeg") # ouverture et stockage dans ref_image de l'image nbr_colonnes = ref_image.width # width veut dire largeur en anglais nbr_lignes = ref_image.height # height veur dire hauteur en anglais couches = ref_image.getbands() # pour récupérer les couches nbr_couches = len(couches) # pour récupérer le nombre de couches (len pour length, longueur) print("Pixels en largeur : ", nbr_colonnes) print("Pixels en hauteur : ", nbr_lignes) print("Pixels au total : ", nbr_colonnes * nbr_lignes) print("Couches : ", couches) print("Nbr de couches : ", nbr_couches) if AFFICHAGE: ref_image.show()

Exemple de résultats pouvant s'afficher dans la console :

Pixels en largeur : 1024 Pixels en hauteur : 771 Pixels au total : 789504 Couches : ('R', 'G', 'B') Nbr de couches : 3

02° Lire le programme en totalité, ligne par ligne, même si vous ne comprennez pas tout pour le moment puis répondre aux question suivantes :

  1. Lors d'une affectation (comme sur les lignes 3, 7, 8, 9 et 10), va-t-on de la gauche vers la droite ou la droite vers la gauche ?
  2. En ligne 5, on stocke dans la variable ref_image les données de l'image. Comment se nomme la fonction qui permet à Python de mettre en mémoire votre fichier-image ?
  3. Dans quel cas va-t-on réaliser la ligne 19 indentée à droite au vu de la ligne 18 ?
  4. Lignes 03-18-19 : Comment se nomme la fonction qui permet d'afficher l'image ? Expliquer pourquoi l'image s'affiche et comment modifier le programme pour désactiver cet affichage avec la constante.

...CORRECTION...

  1. L3 : affectation de la droite vers la gauche. On va donc "remplir" ici la variable ref_image avec l'évaluation qu'on trouve du côté droit.
  2. L5 : la fonction d'ouverture se nomme open().
  3. On indente les instructions à réaliser si la condition évaluée est True (vraie). Ici, on réalise donc la L19 uniquement si la constante AFFICHAGE contient True.
  4. Demande d'affichage L19 avec ref_image.show(). Cette ligne s'exécute car AFFICHAGE contient True. Pour ne plus afficher l'image à chaque lancement, il suffit de modifier la constante en L3 en lui mettant False.

Introduction (3/3) PIXELISATION

Nous allons réaliser en deux actions une pixelisation de votre image :

  1. On commence par réduire la taille de l'image par 10, ce qui entraine une perte d'informations.
  2. On finit en redonnant la taille initiale à l'image réduite. La perte d'informations va alors clairement apparaître.

03° Utiliser ce nouveau programme puis répondre aux questions.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
from PIL import Image AFFICHAGE = True ref_image = Image.open("image.jpeg") nbr_colonnes = ref_image.width # width veut dire largeur en anglais nbr_lignes = ref_image.height # height veur dire hauteur en anglais if AFFICHAGE: ref_image.show() ref_image = ref_image.resize( (nbr_colonnes//10, nbr_lignes//10) ) # On divise la taille par 10 ref_image = ref_image.resize( (nbr_colonnes, nbr_lignes) ) # On remet la taille initiale if AFFICHAGE: ref_image.show() ref_image.save("image_pixelisée.jpg") # On sauvegarde l'image obtenue en modifiant le nom

Questions

  1. Sur quelle ligne divise-t-on la taille de l'image par 10 ? Comment se nomme la méthode permettant de modifier la taille d'une image ?
  2. Sur quelle ligne lui redonne-t-on sa taille initiale ?
  3. Pourquoi voit-on deux affichages ?
  4. Sur quelle ligne demande-t-on à Python de sauvegarder l'image ?

...CORRECTION...

  1. L13 avec la méthode resize().
  2. L15 avec ref_image = ref_image.resize( (nbr_colonnes, nbr_lignes) )
  3. Deux affichages car on lui demande d'afficher l'image avant modification en L11 puis après modification en L18.
  4. L20 avec ref_image.save("image_pixelisée.jpg")
Méthode ou fonction ?

Une méthode est comme une fonction un ensemble d'instructions qu'on demande d'exécuter et à qui on peut fournir des arguments entre parenthèses.

Lorsqu'on utilise une méthode sur un objet, la syntaxe impose de placer le nom de l'objet, un point et le nom de la méthode.

ref_image.save("image_pixelisée.jpg")

On indique ici qu'on veut agir sur ref_image en la sauvegardant sous le nom "image_pixelisée.jpg".

2 - Gestion des pixels avec Python

Nous allons maintenant changer les valeurs RGB des différents pixels.

Nous avons vu dans l'activité précédente qu'une image n'est qu'une succession de nombres.

OBTENIR LES COULEURS RGB D'UN PIXEL

04-A° Si ce n'est pas encore fait car vous reprennez l'activité, téléchargez une image de type .png ou jpg sur le Web et placez la dans un dossier nommé SNT-photographie. Choisissez une image possèdant pas mal de couleurs différentes si possible.

Par exemple, pour illustrer ce cours, j'ai choisi ceci :

Image contenant beaucoup de rouge
Image de base libre de droit : le Palais des congrès de Montréal

04-B° Réaliser les quatre actions ci-dessous.

  1. Lire le code ci-dessous dans sa totalité et appeler si certaines lignes vous sont incompréhensibles.
  2. Enregistrer avec Thonny le programme ci-dessous au même endroit que votre image, donc dans le répertoire SNT-photographie.
  3. 📁 SNT-photographie

    📄 votre_programme.py

    📄 votre_image.png

  4. Modifier la variable base en ligne 4 pour qu'il corresponde au vrai nom et extension de votre image.
  5. Lancer pour vérifier qu'on obtient bien les intensités du pixel (0, 0). Modifier ensuite les lignes 5-6 pour obtenir les intensités du pixel (10, 20) et (50, 300) par exemple.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
from PIL import Image base = "nom_a_modifier.png" # Nom du fichier-image x = 0 # Colonne du pixel voulu y = 0 # Ligne du pixel voulu ref_image = Image.open(base) # Référence Python de l'image de base couches = ref_image.getbands() # pour récupérer la ou les couches # Pour gérer les images en couleurs RGB (3 couches) if nbr_couches == 3: r, g, b = ref_image.getpixel( (x,y) ) # On récupère les 3 valeurs RGB du pixel print(r, "-", g, "-", b) # Pour gérer les images avec transparence RGBA (4 couches) elif nbr_couches == 4: r, g, b, a = ref_image.getpixel( (x,y) ) # On récupère les 4 valeurs RGBA du pixel print(r, "-", g, "-", b, , "-", a) # Si on arrive ici, c'est anormal else: print("Ni 3 ni 4 couches") ref_image_base.close() # Fermeture du lien entre Python et fichier

05° Création d'une fonction qui affiche les coordonnées. Pas très pratique de devoir relancer le programme à chaque fois qu'on veut un pixel. Nous allons donc mettre les lignes 9 à 23 dans une fonction affiche_un_pixel(). De cette façon, nous allons pouvoir lancer 5 appels et obtenir 5 intensités directement dans un seul programme sans avoir à faire trop de copier-coller.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
from PIL import Image base = "nom_a_modifier.png" # Nom du fichier-image ref_image_base = Image.open(base) # Référence Python de l'image de base def infos_pixel(ref_image, x, y): """Fonction qui renvoie un string contenant les intensité du pixel (x,y) de l'image""" couches = ref_image.getbands() # pour récupérer la ou les couches nbr_couches = len(couches) # nombre de couches txt = "Pixel en x=" + str(x) + " y=" + str(y) + " : " # Pour gérer les images en gris (1 couche) if nbr_couches == 1: intensite = ref_image.getpixel( (x,y) ) txt = txt + str(intensite) # Pour gérer les images en couleurs RGB (3 couches) elif nbr_couches == 3: r, g, b = ref_image.getpixel( (x,y) ) txt = txt + str(r) + " " + str(g) + " " + str(b) # Pour gérer les images avec transparence RGBA (4 couches) elif nbr_couches == 4: r, g, b, alpha = ref_image.getpixel( (x,y) ) txt = txt + str(r) + " " + str(g) + " " + str(b) + " " + str(alpha) # Si on arrive ici, c'est anormal else: txt = txt + "Problème, nombre étrange de couches." return txt # Programme principal print( infos_pixel(ref_image_base, 0, 0) ) print( infos_pixel(ref_image_base, 0, 1) ) print( infos_pixel(ref_image_base, 0, 2) ) ref_image_base.close() # Fermeture du lien entre Python et fichier
  1. En comparant l'appel en ligne 40 et la déclaration en ligne 7, dire dans quelles variables vont être stockées les valeurs ref_image_base, 0, 0 envoyées à la fonction lors de cet appel.
  2. 7 .. 40
    def infos_pixel(ref_image, x, y): print( infos_pixel(ref_image_base, 0, 0) )
  3. Quelles sont les trois lignes qui provoquent les trois affichages ?
  4. Sur la ligne 12 de la fonction infos_pixel(), pourquoi doit-on transformer en string les entiers x et y ? Pour répondre, pensez à ce qui se passerait si on demandait à Python "a" + 5...

...CORRECTION...

  1. Pour répondre, il faut comparer la ligne de la déclaration et la ligne de l'appel et associer place par place :
  2. 7 .. 40
    def infos_pixel(ref_image, x, y): print( infos_pixel(ref_image_base, 0, 0) )
    1. ref_image reçoit ref_image_base
    2. x reçoit 0
    3. y reçoit 0
  3. Trois affichages car nous avons trois print() correspondant à 3 appels.
  4. 40 41 42
    print( infos_pixel(ref_image_base, 0, 0) ) print( infos_pixel(ref_image_base, 0, 1) ) print( infos_pixel(ref_image_base, 0, 2) )
  5. Nous avons vu qu'on ne peut pas concatétener des strings et des entiers : cela provoque une erreur !
  6. >>> "A" + "2" 'A2' >>> "A" + 2 TypeError: can only concatenate str (not "int") to str >>> "A" + str(2) 'A2'

06° Etude de la fonction infos_pixel() :

  1. L10-L11 : que va contenir la variable nbr_couches si on a une image RGB ? Si on a une image en nuances de gris ?
  2. L15-20-25 : quel est le cas qui correspond à une image en nuances de gris ? En couleur ? En couleur avec gestion de la transparence ?
  3. L16-21-26 : comment se nomme la méthode permettant de récupérer les intensités lumineuses du pixel de coordonnées (x, y) ?
  4. L21 : combien y-a-t-il de couches sur ce pixel si on active ce bloc ? Combien a-t-on placé de variables à gauche pour récupérer les valeurs d'intensités du pixel ?
  5. L33 : quel est le type de la réponse envoyée par la fonction ?

...CORRECTION...

  1. L10-L11 : nbr_couches contient le nombre de couches sur chaque pixel de cette image : 3 pour du RGB, et 1 pour du GRIS.
  2. L15-20-25 : Une image en nuance de gris n'a qu'une couche donc L15. Une image en couleur RGB possède 3 couches donc ligne 20. Avec la transparence, on atteint 4 couches, donc L25.
  3. Elle se nomme visiblement getpixel()
  4. L21 : si on atteint la ligne 21, c'est qu'on a 3 couches sur cette image. On a donc placé trois variables du côté gauche pour récupérer les trois valeurs RGB du pixel.
  5. r, g, b = ref_image.getpixel( (x,y) )

  6. La fonction renvoie un string.

07° Rajout de la fonction afficher_les_pixels() avec un S : affichons les valeurs des pixels un par un. Il va donc falloir faire varier x progressivement de 0 jusqu'à la dernière valeur possible en x. Ensuite, il faudra passer à la ligne y suivante et recommencer à faire varier x.

  1. Remplacer intégralement votre programme par celui qui se trouve ci-dessous qui contient toujours la fonction infos_pixel() mais également une fonction afficher_les_pixels().
  2. Constater qu'on parvient bien à lire les pixels un par un avec notre double boucle (un for imbriqué dans un for) puis couper le programme en appuyant sur STOP une fois que vous avez bien constaté qu'il affiche les pixels en faisant d'abord varier la colonne puisque la boucle x est la boucle interne.
  3. L52 : quelle est la seule instruction de ce programme ?
  4. L39-47 : commenter les instructions de cette fonction de façon à comprendre ce qu'elle réalise. En cas de doute, faire appel à l'enseignant.
  5. Comment faire si on voulait d'abord afficher tous les pixels de la première colonne puis tous ceux de la deuxième colonne...,  ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
from PIL import Image base = "nom_a_modifier.png" # Nom du fichier-image def infos_pixel(ref_image, x, y): """Fonction qui renvoie un string contenant les intensité du pixel (x,y) de l'image""" couches = ref_image.getbands() # pour récupérer la ou les couches nbr_couches = len(couches) # nombre de couches txt = "Pixel en x=" + str(x) + " y=" + str(y) + " : " # Pour gérer les images en gris (1 couche) if nbr_couches == 1: intensite = ref_image.getpixel( (x,y) ) txt = txt + str(intensite) # Pour gérer les images en couleurs RGB (3 couches) elif nbr_couches == 3: r, g, b = ref_image.getpixel( (x,y) ) txt = txt + str(r) + " " + str(g) + " " + str(b) # Pour gérer les images avec transparence RGBA (4 couches) elif nbr_couches == 4: r, g, b, alpha = ref_image.getpixel( (x,y) ) txt = txt + str(r) + " " + str(g) + " " + str(b) + " " + str(alpha) # Si on arrive ici, c'est anormal else: txt = txt + "Problème, nombre étrange de couches." return txt def afficher_les_pixels(nom_image): """Affiche toutes les valeurs des pixels""" ref_image = Image.open(nom_image) # Référence Python de l'image voulue nbr_colonnes = ref_image.width nbr_lignes = ref_image.height for y in range(nbr_lignes): for x in range(nbr_colonnes): print( infos_pixel(ref_image, x, y) ) ref_image.close() # Fermeture du lien entre Python et fichier # Programme principal afficher_les_pixels(base)

...CORRECTION...

  1. On appelle simplement la fonction afficher_les_images() en lui envoyant le nom de notre fichier.
  2. Voici les commentaires possibles :
  3. 36 37 38 39 40 41 42 43 44 45 46 47
    def afficher_les_pixels(nom_image): """Affiche toutes les valeurs des pixels""" ref_image = Image.open(nom_image) # Référence Python de l'image voulue nbr_colonnes = ref_image.width # on cherche le nombre de pixels en largeur nbr_lignes = ref_image.height # on cherche le nombre de pixels en hauteur for y in range(nbr_lignes): # pour chaque ligne y de l'image for x in range(nbr_colonnes): # pour chaque colonne x de cette ligne print( infos_pixel(ref_image, x, y) ) # affiche la réponse de la fonction infos_pixels() ref_image.close() # Fermeture du lien entre Python et fichier
  4. Il suffit d'inverser les deux boucles des lignes 41 et 42 : la boucle interne doit être celle qui fait varier x.

Passons maintenant au filtrage des couleurs.

08° Lancer ce nouveau programme. Si une erreur apparaît (en rouge), lire le message.

Souvent :

  • soit vous n'avez pas installé le module Pillow !
  • soit vous n'avez pas modifié le nom associé à la variable base
  • soit vous n'avez pas mis votre image et votre fichier Python dans le même répertoire

Si vous bloquez, faire appel à l'enseignant.

Vous devriez avoir une image à l'écran, mais une image où les intensités bleu et le rouge ont été inversées : voir les lignes suivantes

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
from PIL import Image base = "photo-montreal-palais-des-congres.jpeg" # Nom du fichier-image original sauvegarde = "modification.png" # Nom voulu pour l'image après modification def filtrer_image(nom_image): """Fonction qui renvoie un objet-image après l'avoir filtré pixel par pixel""" ref_image = Image.open(nom_image) # Création de l'objet-image propre à Python nbr_colonnes = ref_image.width # Recherche de la largeur de l'image nbr_lignes = ref_image.height # Recherche de la hauteur de l'image couches = ref_image.getbands() # pour récupérer la ou les couches nbr_couches = len(couches) # nombre de couches # Pour gérer les images en couleurs RGB (3 couches) if nbr_couches == 3: for y in range(nbr_lignes): # Pour chaque ligne y for x in range(nbr_colonnes): # Pour chaque colonne x de cette ligne # 1 - Récupération du pixel RGB r, g, b = ref_image.getpixel( (x,y) ) # 2 - Calcul des nouvelles valeurs RGB r, g, b = filtrage(r, g, b) # 3 - Mise à jour des valeurs RGB ref_image.putpixel( (x, y) , (r, g, b) ) # Pour gérer les images avec transparence RGBA (4 couches) if len(ref_image.getbands()) == 4: for y in range(nbr_lignes): for x in range(nbr_colonnes): # 1 - Récupération du pixel RGBA r, g, b, alpha = ref_image.getpixel( (x,y) ) # 2 - Calcul des nouvelles valeurs RGB r, g, b = filtrage(r, g, b) # 3 - Mise à jour des valeurs RGBA ref_image.putpixel( (x,y), (r, g, b, alpha) ) return ref_image def filtrage(ancien_r, ancien_g, ancien_b): """Fonction qui renvoie des valeurs RGB après les avoir modifiées""" r = ancien_b # On place la valeur B dans rouge g = ancien_g # On laisse la valeur G dans vert b = ancien_r # On place la valeur R dans bleu return (r, g, b) # Programme principal ref_image_filtree = filtrer_image(base) ref_image_filtree.show() ref_image_filtree.save(sauvegarde) ref_image_filtree.close()

Exemple avec une image contenant beaucoup de rouge et d'orange :

Image contenant beaucoup de rouge
Image de base libre de droit : le Palais des congrès de Montréal

Et qui devient une image contenant beaucoup de bleu et de cyan :

Image contenant beaucoup de bleu
Même image en intervertissant Bleu et Rouge

09° Expliquer ce que renvoie la fonction filtrage() lorsqu'elle reçoit les trois paramètres ancien_r ancien_g ancien_b.

41 42 43 44 45 46 47 48
def filtrage(ancien_r, ancien_g, ancien_b): """Fonction qui renvoie des valeurs RGB après les avoir modifiées""" r = ancien_b # On place la valeur b dans rouge g = ancien_g # On laisse la valeur g dans vert b = ancien_r # On place la valeur r dans bleu return (r, g, b)

...CORRECTION...

Si on lit le code, on peut se rendre compte qu'elle renvoit le triplet de valeurs mais en intervertissant le rouge et le bleu.

31 32 33 34 35 36 37 38
def filtrage(ancien_r, ancien_g, ancien_b): """Fonction qui renvoie des valeurs RGB après les avoir modifiées""" r = ancien_b # On place la valeur b dans rouge g = ancien_g # On laisse la valeur g dans vert b = ancien_r # On place la valeur r dans bleu return (r, v, b)

Sur ce pixel, les intensités du bleu et du rouge sont donc inversées.

10° Lire rapidement les lignes 18 à 26 de la fonction filter_image(), puis répondre à ces deux questions ?

  • comment se nomme la méthode permettant de récupérer les valeurs d'un pixel ?
  • Comment se nomme la méthode qui permet de modifier les valeurs d'un pixel ?

...CORRECTION...

18 19 20 21 22 23 24 25 26
if nbr_couches == 3: for y in range(nbr_lignes): # Pour chaque ligne y for x in range(nbr_colonnes): # Pour chaque colonne x de cette ligne # 1 - Récupération du pixel RGB r, g, b = ref_image.getpixel( (x,y) ) # 2 - Calcul des nouvelles valeurs RGB r, g, b = filtrage(r, g, b) # 3 - Mise à jour des valeurs RGB ref_image.putpixel( (x, y) , (r, g, b) )
  • L22 -> On récupère avec getpixel()
  • L26 -> On modifie avec putpixel()

11° Lire l'intégralité de la fonction filter_image() et appeler si l'une des lignes vous semble incompréhensible.

La fonction filtrage()  inverse les valeurs des intensités R et B.

Regardons comment nous pourrions l'utiliser différemment.

3 - Filtrage

Filtrer les couleurs veut dire en laisser passer certaines et pas d'autres.

Pour l'instant, la fonction filtrage() ne provoque qu'une intervertion de couleurs.

12° CREER UN FILTRE ROUGE : cela veut dire que la fonction filtrage ne doit renvoyer que la bonne intensité rouge de départ et mettre les autres à 0.

Image contenant beaucoup de rouge Image avec uniquement la couche Rouge

...CORRECTION...

31 32 33 34 35 36 37 38
def filtrage(ancien_r, ancien_g, ancien_b): """Fonction qui renvoie des valeurs RGB après les avoir modifiées""" r = ancien_r # On laisse le rouge g = 0 # On supprime le vert b = 0 # On supprime le bleu return (r, g, b)

13° CREER UN FILTRE BLEU : cela veut dire que la fonction filtrage() ne doit renvoyer que la bonne intensité bleue de départ et mettre les autres à 0.

Image contenant beaucoup de rouge Image avec uniquement la couche Bleue

...CORRECTION...

31 32 33 34 35 36 37 38
def filtrage(ancien_r, ancien_g, ancien_b): """Fonction qui renvoie des valeurs RGB après les avoir modifiées""" r = 0 # On supprime le rouge g = 0 # On supprime le vert b = ancien_b # On laisse le bleu return (r, g, b)

14° CREER UN FILTRE VERT : cela veut dire que la fonction filtrage() ne doit renvoyer que la bonne intensité verte de départ et mettre les autres à 0.

Image contenant beaucoup de rouge Image avec uniquement la couche Verte

...CORRECTION...

31 32 33 34 35 36 37 38
def filtrage(ancien_r, ancien_g, ancien_b): """Fonction qui renvoie des valeurs RGB après les avoir modifiées""" r = 0 # On supprime le rouge g = ancien_g # On laisse le vert b = 0 # On supprime le bleu return (r, g, b)

15° IMAGE GRISE : Remplacer les trois intensités R, G et B par la moyenne des trois. On pourra utiliser la division euclidienne en Python en utilisant // plutôt que simplement /.

Par exemple rouge = (r+g+b) // 3

Si les trois intensités RGB ont la même valeur, votre oeil percevra du gris.

Image contenant beaucoup de rouge Image grise

...CORRECTION...

31 32 33 34 35 36 37 38
def filtrage(ancien_r, ancien_g, ancien_b): """Fonction qui renvoie des valeurs RGB après les avoir modifiées""" r = (ancien_r + ancien_g + ancien_b) // 3 g = (ancien_r + ancien_g + ancien_b) // 3 b = (ancien_r + ancien_g + ancien_b) // 3 return (r, g, b)

Si on veut transformer une image en couleur en réelle perception grisée pour un oeil humain, il faut utiliser des formules particulières pour avoir un rendu correct car nos yeux ne sont pas sensibles de la même manière à la lumière rouge, verte ou bleue. ils sont beaucoup plus sensibles à la lumière verte qu'aux lumières bleues et rouges.

16° IMAGE GRISE HUMAINE : Remplacer les trois intensités R, G et B par :

red = (21*r + 71*g + 8*b) // 100

La nouvelle version grise à gauche, la moyenne pure à droite :

Image grise version 2 Image grise

...CORRECTION...

31 32 33 34 35 36 37 38
def filtrage(ancien_r, ancien_g, ancien_b): """Fonction qui renvoie des valeurs RGB après les avoir modifiées""" r = (21*ancien_r + 71*ancien_g + 8*ancien_b) // 100 g = (21*ancien_r + 71*ancien_g + 8*ancien_b) // 100 b = (21*ancien_r + 71*ancien_g + 8*ancien_b) // 100 return (r, g, b)

17 (en équipe)° Tâche finale complexe :

  1. choisir une image sur le Web et à l'aide d'un logiciel de dessin, placer un fond totalement VERT (0, 255,0) sur le fond de votre image.
  2. Sauvegarder cette image en .png (c'est important).
  3. Sélectionner sur le web une autre image d'un paysage quelconque.
  4. Créer maintenant un programme qui :
    1. Place chacune de vos deux images dans une variable différente.
    2. Redimensionne les images pour qu'elles aient les mêmes dimensions.
    3. Pour chaque ligne y et chaque colonne x, si le fond de l'image 1 est vert, alors on la modifie en y placant la valeur du pixel de l'image 2.
    4. On sauvegarde la nouvelle image.

4 - FAQ

Pas de question pour le moment

Comme vous pouvez le voir, il est assez facile de modifier les couleurs d'une image.

Dans d'autres activités, nous verrons qu'on peut en tirer d'autres informations et même qu'il est parfois possible d'y laisser votre nom ou vos coordonnées GPS. C'est dire ...

Prochaine activité : nous allons voir comment trouver les contours d'une image.

Comme une image n'est qu'une suite de nombres, une IA peut assez facilement les générer, les modifier.

Activité publiée le 02 12 2019
Dernière modification : 08 12 2019
Auteur : ows. h.