SNT Photo Filtrage

Identification

Infoforall

4 - Filtrage d'une image


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

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.

1 - Prise en main de Thonny

Thonny permet de travailler avec Python dans un environnement qui permet de voir le contenu des variables, et d'avoir dans la même fenêtre la Console (le mode commande interactive en direct) et la fenêtre de programmation (celle où on tape du code pour l'enregistrer).

Thonny

01° Ouvrir Thonny.

Dans le menu View, sélectionner variables.

02° Taper le code suivant dans la partie programme (celle du haut, sans les trois chevrons >>>).

1 2
largeur = 1000 hauteur = 250

Nous venons de créer deux variables : on pourra maintenant récupérer les valeurs stockées en tapant simplement les noms des variables.

03° Sauvegarder le programme dans votre répertoire et lancer le programme en appuyant sur la flèche verte.

Il ne devrait rien se passer sauf la création des deux variables dans la fenêtre de gauche.

Thonny et variables

04° Tapez les instructions suivantes dans la Console (la partie avec les trois chevrons >>>).

>>> largeur 1000 >>> hauteur 250 >>> pixels = largeur * hauteur >>> pixels 250000

Vous pourrez voir également le contenu de pixels dans la partie variables à partir du moment où la variable est déclarée.

Thonny et Shell

L'intérêt de Python par rapport à Scratch ? La création de fonction. Dans Scratch, s'il n'existe pas de bloc capable de faire ce que vous voulez faire, vous ne pourrez pas réaliser le programme de vos rêves.

Avec les langages de programmation, il suffit de créer une fonction :

  • On lui envoie des ENTREES qu'on récupère dans des variables (qu'on nomme les paramètres)
  • On calcule ce qu'on veut à partir des entrées et on renvoie la SORTIE (le résultat) avec le mot-clé return
  • On pourra stocker le résultat de la fonction dans une variable si on le désire
1 2 3 4
def calculer_taille(lar, hau): '''Renvoie la taille en pixels d'une image dont on connait la largeur et la hauteur en pixels''' taille = lar * hau return taille

05° Modifier la partie programme puis enregistrer le.

Il ne devrait rien se passer SAUF qu'une nouvelle variable est apparue dans l'onglet VARIABLE : celle qui porte le nom de la fonction calculer_taille.

1 2 3 4
def calculer_taille(lar, hau): '''Renvoie la taille en pixels d'une image dont on connait la largeur et la hauteur en pixels''' taille = lar * hau return taille
Thonny et fonction

06° Tapez les instructions suivantes dans la Console (la partie avec les trois chevrons >>>).

>>> calculer_taille(1000, 250) 250000

La Console vous montre la réponse mais est-elle mémorisée dans la partie variable ?

Réponse dans le Shell

07° Pour mémoriser le résultat de façon à le réutiliser plus tard, il suffit de placer la réponse de la fonction dasn ... une variable. Tapez instructions suivantes dans la Console (la partie avec les trois chevrons >>>).

>>> reponse = calculer_taille(1000, 250) >>> reponse 250000

Une variable reponse contient maintenant la valeur stockée.

Réponse stockée

2 - Gestion des images avec Python

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.

Commençons par voir si vous avez le module.

08° Tapez ceci dans la Console pour voir si cela déclenche une erreur.

>>> from PIL import Image

Si c'est le cas :

  • 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

09° 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.

10° Enregistrer le programme ci-dessous (après avoir lu la remarque ATTENTION) avec Thonny en le plaçant dans le même répertoire SNT-photographie que votre image. ATTENTION : il faudra modifier le nom du fichier stocké dans la variable base de façon à ce qu'il corresponde à celui de votre fichier-image.

📁 SNT-photographie

📄 votre_programme.py

📄 votre_image.png

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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
from PIL import Image as Img # Nom du fichier-image original base = "nom_a_modifier.png" # Nom du fichier-image modifié sauvegarde = "modification.png" def pixel(nom, x, y): '''Fonction qui renvoie les intensité d'un pixel (x,y) d'une image''' # Création de l'objet-image propre à Python ref_image = Img.open(nom) # Si image avec 3 couches : R G B if len(ref_image.getbands()) == 3 : # On récupère les valeurs RGB du pixel de coordonnées (x,y) rouge, vert, bleu = ref_image.getpixel( (x,y) ) return(f"Pixel de coordonnées ({x}, {y}) : R = {rouge} - G = {vert} - B = {bleu}") # Si image avec 4 couches : R G B et transparence (alpha) if len(ref_image.getbands()) == 4 : # On récupère les valeurs RGB du pixel de coordonnées (x,y) rouge, vert, bleu, alpha = ref_image.getpixel( (x,y) ) return(f"Pixel de coordonnées ({x}, {y}) : R = {rouge} - G = {vert} - B = {bleu} - A = {alpha}") # Si image grise avec 1 couche : if len(ref_image.getbands()) == 1 : # On récupère la valeur du pixel de coordonnées (x,y) intensite = ref_image.getpixel( (x,y) ) return(f"Pixel de coordonnées ({x}, {y}) : Intensité = {intensite}") def filtrer_image(nom): '''Fonction qui renvoie un objet-image après l'avoir filtré pixel par pixel''' # Création de l'objet-image propre à Python ref_image = Img.open(nom) # Lecture et action sur les pixels, un par un largeur, hauteur = ref_image.size # Si image avec 3 couches : R G B if len(ref_image.getbands()) == 3 : for x in range(largeur): for y in range(hauteur): # On récupère les valeurs RGB du pixel de coordonnées (x,y) rouge, vert, bleu = ref_image.getpixel( (x,y) ) # On transforme les valeurs RGB avec la fonction de filtrage rouge, vert, bleu = filtrage(rouge, vert, bleu) # On transforme l'image-Python en mémoire ref_image.putpixel( (x, y) , (rouge, vert, bleu) ) # Sinon, si image avec 4 couches : R G B + Transparence(alpha) if len(ref_image.getbands()) == 4 : for x in range(largeur): for y in range(hauteur): # On récupère les valeurs RGB du pixel de coordonnées (x,y) rouge, vert, bleu, alpha = ref_image.getpixel( (x,y) ) # On transforme les valeurs RGB avec la fonction de filtrage rouge, vert, bleu = filtrage(rouge, vert, bleu) # On transforme l'image-Python en mémoire ref_image.putpixel( (x,y), (rouge, vert, bleu, alpha) ) return ref_image def filtrage(r, g, b): '''Fonction qui renvoie des valeurs r, g, b après les avoir modifiées''' rouge = b # On place la valeur b dans rouge vert = g # On laisse la valeur g dans vert bleu = r # On place la valeur r dans bleu return (rouge, vert, bleu) # Création d'une nouvelle image à partir de la source originale nouvelle = filtrer_image(base) # Affichage de l'objet-image Python à l'écran nouvelle.show() # Sauvegarde de l'image dans un nouveau fichier-image nouvelle.save(sauvegarde)

Vous n'aurez qu'à apporter des modifications sur ces parties du programme (notamment le nom du fichier image de base) :

1 2 3 4 5 6 .. 64 65 66 67 68 69
from PIL import Image as Img # Nom du fichier-image original base = "maisons.jpg" # Nom du fichier-image modifié sauvegarde = "modification.jpg" def filtrage(r, g, b): '''Fonction qui renvoie des valeurs r, g, b après les avoir modifiées''' rouge = b # On place la valeur b dans rouge vert = g # On laisse la valeur g dans vert bleu = r # On place la valeur r dans bleu return (rouge, vert, bleu)

11° Lancer votre 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

66 67 68
rouge = b # On place la valeur b dans rouge vert = g # On laisse la valeur g dans vert bleu = r # On place la valeur r dans bleu

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 intervertisant Bleu et Rouge

Bon et comment vérifier que ça marche autrement qu'en regardant les images ? En utilisant la fonction pixel qu'on vous offre ligne 8.

12° Utiliser les commandes suivantes dans la Console (le Shell dans la version anglaise) pour voir les valeurs des intensités R, G et B sur le pixel en x=50 et y = 100 par exemple.

>>> pixel(base, 50, 100) 'Pixel de coordonnées (50, 100) : R = 160 - G = 174 - B = 3' >>> pixel(sauvegarde, 50, 100) 'Pixel de coordonnées (50, 100) : R = 3 - G = 174 - B = 160'

Visualiser que le programme est bien parvenu à intervertir les deux valeurs sur ce pixel.

Image JPEG : les images JPEG prennent moins de place en mémoire car on réduit le nombre de couleurs disponibles. Il est donc possible que les deux valeurs interverties ne soient pas exactement les mêmes si vous avez utilisé ce format.

13° Comparer l'appel à la fonction et la déclaration de la fonction (son prototype)

L'appel :

>>> pixel(base, 50, 100)

La déclaration :

8
def pixel(nom, x, y):

Questions

  • Dans quelle variable va se stocker la variable base ?
  • Dans quelle variable va se stocker la valeur 50 ?
  • Dans quelle variable va se stocker la valeur 100 ?

...CORRECTION...

Il faut associer place par place :

On voit donc qu'on stocke base dans nom, 50 dans x et 100 dans y.

C'est comme si cet appel précis avait été fait en notant ceci en début de la fonction :

  1. nom = base
  2. x = 50
  3. y = 100

14° Comparer l'appel à la fonction et la déclaration de la fonction (son prototype)

L'appel :

>>> pixel(sauvegarde, 300, 40)

La déclaration :

8
def pixel(nom, x, y):

...CORRECTION...

C'est comme si cet appel précis avait été fait en notant ceci en début de la fonction :

  1. nom = sauvegarde
  2. x = 300
  3. y = 40

Que fait la fonction filtrage ? Pour l'instant, elle inverse les valeurs des intensités R et B.

Regardons comment nous pourrions l'utiliser.

3 - Filtrage

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

Pour l'instant, nous intervertissons le rouge et le bleu sur chaque pixel dans la fonction filtrage :

64 65 66 67 68 69
def filtrage(r, g, b): '''Fonction qui renvoie des valeurs r, g, b après les avoir modifiées''' rouge = b # On place la valeur b dans rouge vert = g # On laisse la valeur g dans vert bleu = r # On place la valeur r dans bleu return (rouge, vert, bleu)

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

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

Et qui devient une image ne contenant que les intensités rouges :

Image avec uniquement la couche Rouge
La couche Rouge

L'une à côté de l'autre :

Image contenant beaucoup de rouge Image avec uniquement la couche Rouge

...CORRECTION...

64 65 66 67 68 69
def filtrage(r, g, b): '''Fonction qui renvoie des valeurs r, g, b après les avoir modifiées''' rouge = r vert = 0 bleu = 0 return (rouge, vert, bleu)

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

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

Et qui devient une image ne contenant que les intensités bleues :

Image avec uniquement la couche Bleue
La couche Bleue

L'une à côté de l'autre :

Image contenant beaucoup de rouge Image avec uniquement la couche Bleue

...CORRECTION...

64 65 66 67 68 69
def filtrage(r, g, b): '''Fonction qui renvoie des valeurs r, g, b après les avoir modifiées''' rouge = r vert = 0 bleu = 0 return (rouge, vert, bleu)

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

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

Et qui devient une image ne contenant que les intensités vertes :

Image avec uniquement la couche Verte
La couche Verte

L'une à côté de l'autre :

Image contenant beaucoup de rouge Image avec uniquement la couche Verte

...CORRECTION...

64 65 66 67 68 69
def filtrage(r, g, b): '''Fonction qui renvoie des valeurs r, g, b après les avoir modifiées''' rouge = 0 vert = g bleu = 0 return (rouge, vert, bleu)

17° 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 ont la même valeur, votre oeil percevra du gris.

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

Et qui devient une image grise :

Image grise
Image grise

L'une à côté de l'autre :

Image contenant beaucoup de rouge Image grise

...CORRECTION...

64 65 66 67 68 69
def filtrage(r, g, b): '''Fonction qui renvoie des valeurs r, g, b après les avoir modifiées''' rouge = (r + g + b) // 3 vert = (r + g + b) // 3 bleu = (r + g + b) // 3 return (rouge, vert, bleu)

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.

18° IMAGE GRISE HUMAINE : Remplacer les trois intensités R, G et B par red = (21*r + 71*g + 8*b) // 100.

Image grise
Nouvelle version

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

Image grise version 2 Image grise

...CORRECTION...

64 65 66 67 68 69
def filtrage(r, g, b): '''Fonction qui renvoie des valeurs r, g, b après les avoir modifiées''' rouge = (21*r + 71*g + 8*b) // 100 vert = (21*r + 71*g + 8*b) // 100 bleu = (21*r + 71*g + 8*b) // 100 return (rouge, vert, bleu)

4 - FAQ

Pas de question pour le moment

Comme vous pouvez le voir, il est assez facile de modifier les couleurs d'une image ou d'en tirer des informations supplémentaires.

Dans une prochaine activité, nous verrons 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.

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