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 le Shell (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 en plus du Shell.

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 le Shell (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 le Shell (la partie avec les trois chevrons >>>).

>>> calculer_taille(1000, 250) 250000

Le Shell 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 le Shell (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 le Shell pour voir si cela déclenche une erreur.

>>> from PIL import Image

Si c'est le cas :

  • Ouvrir le menu Tool
  • Sélectionner Manage Packages
  • 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 votre dossier de travail. Choisissez une image possèdant pas mal de couleurs différentes si possible.

10° Enregistrer le programme ci-dessous avec Thonny en le plaçant dans le même répertoire que votre image. 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
from PIL import Image as Img # Nom du fichier-image original base = "votre_image.png" # Nom du fichier-image modifié sauvegarde = "modification.jpg" def filtrer_image(nom) : '''Fonction qui renvoie un objet-image après l'avoir filtrer 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 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) ) return ref_image def filtrage(r, g, b) : '''Fonction qui renvoie des valeurs r,g,b après les avoir modifiées''' red = g green = b blue = r return (red, green, blue) # 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 :

1 2 3 4 5 6 7 8 9 10 11 12 13
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''' red = g green = b blue = r return (red, green, blue)

Il faudra parfois changer les noms d'ouverture et d'enregistrement.

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

11° Tester le programme sur votre image.

FILTRE ROUGE : Modifier maintenant le programme : on veut maintenant ne garder que l'intensité R identique à l'image originale et mettre les autres à 0.

12° FILTRE BLEU : Idem mais avec l'intensité bleue uniquement.

13° 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 red = (r+g+b) // 3

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

Si on veut transformer une image en couleur, 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 bleus et rouges.

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

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

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

1 2 3 4 5 6 7 8 9 10 11 12 13
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''' red = (21*r + 71*g + 8*b) // 100 green = (21*r + 71*g + 8*b) // 100 blue = (21*r + 71*g + 8*b) // 100 return (red, green, blue)

3 - Image en noir et blanc

Si on veut du noir (RBG = (0,0,0)) ou du blanc (RGB = (255,255,255)), il faut utiliser une nouvelle notion : le test conditionnelle.

En gros, on calcule l'intensité de gris du pixel (comme à la question 14) et on décide d'un seuil.

Si l'intensité est supérieure au seuil, on place un pixel blanc.

Si l'intensité est inférieure ou égale au seuil, on place du noir.

1 2 3 4 5 6 7 8
def filtrage(r, g, b) : '''Fonction qui renvoie des valeurs r,g,b après les avoir modifiées''' gris = (21*r + 71*g + 8*b) // 100 seuil = 100 if gris > seuil : return (255, 255, 255) else : return (0,0,0)

15° Tester cette fonction avec différentes avec différents seuils.

4 - Détection de contour

Pour détecter un contour, nous avons besoin d'une image noir et blanc. C'est l'objet de la question précédente.

Nous avons besoin de pouvoir connaitre les 8 pixels qui entourent le pixel étudié.

On obtient ainsi une zone de 9 pixels.

Si entre 3 à 6 pixels ont la même couleur, on considère qu'on est proche d'un contour : on dessine les pixels en noir.

Sinon, on dessine les pixels en blanc : on est loin d'un contour.

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 79 80 81 82 83 84 85 86 87 88
from PIL import Image as Img # Nom du fichier image original base = "clair.jpg" # Nom du fichier image modifié sauvegarde = "m_rouge.jpg" def filtrer_image_3x3(nom) : '''Fonction qui renvoie un objet-image après l'avoir filtrer 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 for x in range(1, largeur-1, 3) : for y in range(1, hauteur-1, 3) : # On crée les 9 coordonnées des pixels à surveiller px1 = (x-1,y-1) px2 = (x-1,y) px3 = (x-1,y+1) px4 = (x,y-1) px5 = (x,y) px6 = (x, y+1) px7 = (x+1,y-1) px8 = (x+1,y) px9 = (x+1,y+1) # On récupère les 9 valeurs RGB du pixel de coordonnées (x,y) r1, g1, b1 = ref_image.getpixel( px1 ) r2, g2, b2 = ref_image.getpixel( px2 ) r3, g3, b3 = ref_image.getpixel( px3 ) r4, g4, b4 = ref_image.getpixel( px4 ) r5, g5, b5 = ref_image.getpixel( px5 ) r6, g6, b6 = ref_image.getpixel( px6 ) r7, g7, b7 = ref_image.getpixel( px7 ) r8, g8, b8 = ref_image.getpixel( px8 ) r9, g9, b9 = ref_image.getpixel( px9 ) # On transforme les pixels en noir ou blanc avec la fonction filtrage r1, g1, b1 = filtrage(r1, g1, b1) r2, g2, b2 = filtrage(r2, g2, b2) r3, g3, b3 = filtrage(r3, g3, b3) r4, g4, b4 = filtrage(r4, g4, b4) r5, g5, b5 = filtrage(r5, g5, b5) r6, g6, b6 = filtrage(r6, g6, b6) r7, g7, b7 = filtrage(r7, g7, b7) r8, g8, b8 = filtrage(r8, g8, b8) r9, g9, b9 = filtrage(r9, g9, b9) # On transforme l'image-Python en mémoire nbr_noir = compter(r1,r2,r3,r4,r5,r6,r7,r8,r9) if nbr_noir > 6 : rgb = (255, 255, 255) elif nbr_noir < 3 : rgb = (255, 255, 255) else : rgb = (0, 0, 0) # On modifie l'image en mettant les 9 pixels en noir OU en blanc ref_image.putpixel( (x-1,y-1) , rgb ) ref_image.putpixel( (x-1,y) , rgb ) ref_image.putpixel( (x-1,y+1) , rgb ) ref_image.putpixel( (x,y-1) , rgb ) ref_image.putpixel( (x,y) , rgb ) ref_image.putpixel( (x,y+1) , rgb ) ref_image.putpixel( (x+1,y-1) , rgb ) ref_image.putpixel( (x+1,y) , rgb ) ref_image.putpixel( (x+1,y+1) , rgb ) return ref_image def compter(r1,r2,r3,r4,r5,r6,r7,r8,r9) : return (r1+r2+r3+r4+r5+r6+r7+r8+r9) // 255 def filtrage(r, g, b) : '''Fonction qui renvoie des valeurs r,g,b après les avoir modifiées''' gris = (21*r + 71*g + 8*b) // 100 seuil = 75 if gris > seuil : return (255, 255, 255) else : return (0,0,0) # Création d'une nouvelle image à partir de la source originale nouvelle = filtrer_image_3x3(base) # Affichage de l'objet-image Python à l'écran nouvelle.show() # Sauvegarde de l'image dans un nouveau fichier-image nouvelle.save(sauvegarde)

16° Tester ce programme avec une image sur laquelle des formes sont assez clairement détectables. Conclusion ?

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 la prochaine activités, nous verrons même qu'il est parfois possible d'y laisser votre nom ou vos coordonnées GPS. C'est dire ...

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