Les nouvelles technologies pour l’enseignement des mathématiques
Intégration des TICE dans l’enseignement des mathématiques

MathémaTICE, première revue en ligne destinée à promouvoir les TICE à travers l’enseignement des mathématiques.

SNT/NSI : création et manipulation de fichiers image pgm et ppm

Anne Héam propose, pour les sections SNT/NSI, quatre activités clés en main de création et de manipulation de fichiers d’images en formats pgm et ppm, jusqu’à cacher une image en noir et blanc dans une image en couleur.

Article mis en ligne le 24 janvier 2022
dernière modification le 26 mars 2022

par Anne Héam

Autres articles de traitement d’images dans MathémaTICE :

Autres articles d’Anne Héam (Les quatre premiers de la liste)

Les formats image pgm (en noir et blanc) et ppm (couleur) sont des formats non compressés où la couleur de chaque pixel est un nombre (pour le noir et blanc) ou trois nombres (pour la couleur) que l’on peut lire facilement dans le fichier. Ils permettent d’étayer le fait que toute donnée numérique est stockée sous la forme d’une suite de 0 et 1. On peut facilement obtenir un fichier pgm ou ppm à partir d’un format classique en utilisant gimp (comme je l’explique dans la dernière partie).

Cet article présente une suite de 4 activités sur les fichiers image pgm et ppm décomposées en 6 parties.

  • La première activité est accessible à tout élève de SNT, elle consiste à manipuler puis à créer à la main des fichiers pgm et ppm, elle s’inscrit dans le thème de la photographie numérique.
  • La deuxième activité est également accessible aux élèves de SNT, elle consiste à utiliser le langage Python pour générer des fichiers pgm et ppm. Seules les notions de fonctions, boucles for et conditionnelles sont nécessaires. Durant toutes ces activités, on n’utilise pas la notion de tableau. En effet, on traite les pixels indépendamment les uns des autres, on n’a pas besoin de désigner les pixels autour et dans les fichiers pgm et ppm, le fait qu’un pixel soit sur la même ligne ou sur la ligne suivante du pixel précédent n’apparaît pas quand les valeurs des pixels sont énumérées.
  • La troisième activité consiste, à partir d’un fichier pgm ou ppm, à obtenir un nouveau fichier image en utilisant le langage Python. Même si elle est accessible à des élèves de SNT, pour des raisons de temps, la plupart de mes élèves n’atteignent que les premières transformations (foncer ou éclaircir une image). Par contre la majorité de mes élèves de NSI la finisse.
  • La quatrième activité permet de cacher une image bicolore (noir et blanc) dans une image en couleur et donc de parler de stéganographie. Elle nécessite la manipulation de 3 fichiers, 2 en lecture, 1 en écriture. Les élèves de NSI qui, jusqu’ici, ont avancé avec une compréhension superficielle de ce qu’ils faisaient et une stratégie de répétition soutenue d’essais/erreurs, sont généralement bloqués. Mais ceux qui s’engagent davantage dans l’activité sont le plus souvent contents de déchiffrer les images crées par les autres et de partager les leurs.

1. Manipulation et création d’images pgm et ppm à la main

a. Énoncé

Créer un nouveau dossier Image pour accueillir tous les fichiers d’images.

I Images .pmg

Le format de fichier portable graymap (pgm) est un format de fichier graphique très simple. Il s’utilise pour des images en noir et blanc.
Nous allons nous servir de deux utilitaires pour lire les fichiers pgm :

  • Gimp qui permet de visualiser l’image sans correction.
  • Notepad ++ qui permet de voir le texte codant l’image.

Téléchargez le fichier gris.pgm.

gris.pgm.zip

En l’ouvrant avec Gimp, vous devez voir en zoomant (touche CTRL + molette de la souris) :

En l’ouvrant avec Notepad++, vous devez lire :

          P2
4 4
255
0
255
0
0
0
0
255
0
0
0
0
255
100
100
100
100
  • La première ligne P2 indique le format de l’image, cela permet aux logiciels d’interpréter correctement les lignes qui suivent afin d’afficher l’image correspondant au fichier.
  • La deuxième ligne indique le nombre de pixels sur la largeur et sur la hauteur
  • La troisième indique le nombre de nuances de gris (ici 255)
  • Les lignes suivantes donnent une à une les valeurs de gris de chacun des pixels.
    • La quatrième ligne (0) indique que le premier pixel de la première ligne en partant de la gauche est noir.
    • La cinquième ligne (255) indique que le deuxième pixel de la première ligne en partant de la gauche est blanc.
    • Ainsi de suite

Modifiez le fichier gris.pgm pour obtenir les images suivantes :

       

II Images .ppm

Le format de fichier pixmap (ppm) est un format de fichier graphique très simple. Il s’utilise pour des images en couleur.

Téléchargez le fichier damier.ppm.

damier.ppm.zip

En l’ouvrant avec Gimp, vous devez voir en zoomant (touche CTRL + molette de la souris) :

En l’ouvrant avec Notepad++, vous devez lire :

          P3
2 2
255
255
0
0
0
255
0
0
0
255
255
255
0
  • La première ligne P3 indique le format de l’image.
  • La deuxième ligne indique le nombre de pixels sur la largeur et sur la hauteur.
  • La troisième indique le nombre de nuances pour chaque couleur (ici 255)
  • Les lignes suivantes se lisent 3 par 3. Elles donnent la nuance de rouge, de vert et de bleu de chacun des pixels.
    • La quatrième ligne (255), la cinquième ligne (0) et la sixième ligne (0) indiquent que le premier pixel de la première ligne en partant de la gauche a comme couleur 255 0 0 ce qui correspond au rouge pur.
    • La septième ligne (0), la huitième ligne (255) et la neuvième ligne (0) indiquent que le deuxième pixel de la première ligne en partant de la gauche a comme couleur 0 255 0 ce qui correspond au vert pur.
    • Ainsi de suite

Modifiez le fichier damier.ppm pour obtenir l’une des images suivantes :

     

b. Commentaires

La visualisation de toutes petites images (ici au plus 25 pixels) pose un problème car beaucoup de logiciels extrapolent les pixels lorsqu’on agrandit l’image pour éviter l’effet « pixelisé ». Ce n’est pas le cas de gimp.

Je guide les élèves pour l’ouverture du fichier gris.pgm avec gimp et notepad++ en projetant l’écran de mon ordinateur. Je commente ensuite le contenu du fichier gris.pgm. À ce moment là, je propose aux élèves de modifier la valeur de l’un des pixels. Quand on actualise l’image dans gimp (rétablir), le fait que les nombres et l’image soient liés, prend sens. On voit l’intérêt des élèves croître d’un coup et ceux qui ne suivaient pas vraiment sont nettement plus attentifs si je leur propose de remplacer par la valeur de leur choix la nuance de gris d’un autre pixel.
C’est l’occasion d’insister sur le fait que la couleur est obtenue par de la lumière et donc, plus il y a de lumière (plus le nombre grand), plus le pixel est clair.

Dans cette partie, comme tout au long de ces 4 activités, les élèves oublient que la 3e ligne indique le nombre de nuances et non la valeur du premier pixel. C’est une source continue d’erreurs.

En NSI, certains élèves demandent si on ne pourrait pas automatiser l’écriture des fichiers avec un programme Python notamment lorsqu’ils créent le damier en noir et blanc. L’intérêt de l’activité suivante est alors évident. Il me semble toutefois indispensable qu’ils créent au moins un fichier pgm et un fichier ppm pour comprendre de quels éléments ceux-ci sont constitués.

Dans l’article les fichiers ppm et pgm sont compressés pour des raisons techniques, pour mes cours, je donne les fichiers non compressés afin de limiter les manipulations de fichiers qui sont toujours chronophages.

2. Écrire un fichier pgm ou ppm avec python

a. Énoncé

Il est fastidieux d’écrire à la main un fichier pgm ou ppm. On va utiliser un programme python pour écrire automatiquement un fichier pgm.

I Générer un fichier pgm

Commençons par écrire automatiquement un fichier pgm

Téléchargez le fichier ecrirepgm.py.

ecrirepgm.py.zip

Ce fichier est composé de 4 fonctions et pour chacune d’un appel (pour les trois derniers cet appel est en commentaire).

a) Créer une image de deux barres

Les premières lignes définissent la fonction cree_image_2barres qui est appelée par l’instruction

cree_image_2barres("resultat.pgm")

L’exécution de cette dernière instruction crée le fichier resultat.pgm qui est l’image :

Vous devez modifier la fonction cree_image_2barres là où sont situés les commentaires :

    """
écrire la valeur de chaque pixel manquant qui sont noirs par défaut
pour créer l'image avec 2 barres
"""

Pour que l’exécution de

cree_image_2barres("resultat.pgm")

crée le fichier resultat.pgm correspondant à :

b) Créer une image de huit barres

Commentez l’instruction

cree_image_2barres("resultat.pgm")

Modifiez ensuite la fonction cree_image_8barres et décommentez l’instruction

cree_image_8barres("resultat1.pgm")

Afin que resultat1.pgm corresponde à

c) Créer un dégradé

Commentez l’instruction

cree_image_8barres("resultat1.pgm")

Modifiez ensuite la fonction cree_image_degrade et décommentez l’instruction

cree_image_degrade("resultat2.pgm")

Afin que resultat2.pgm corresponde à

II Générer un fichier ppm

Commentez l’instruction

cree_image_degrade("resultat2.pgm")

Modifiez ensuite la fonction cree_image_degrade_couleur et décommentez l’instruction

cree_image_degrade_couleur("resultat2.ppm")

Afin que resultat2.ppm (c’est une image ppm donc en couleur pas en noir et blanc) corresponde à un dégradé de couleur tel que :

  ou  

b. Commentaires

Même si c’est précisé dans le fichier Python, les élèves oublient qu’en l’absence de valeur pour un pixel, gimp le fait apparaître en noir. L’apparition de pixels noirs en l’absence de valeur 0 peut alors les perturber et aller à l’encontre du but de ce TP à savoir que la numérisation des images est relativement simple à comprendre.

Je ne propose une explication construite de la manipulation de fichiers par l’intermédiaire de Python que dans la partie suivante.

La construction de l’image à 8 barres peut s’écrire de plusieurs façons où le nombre de passages dans une boucle for peut ne correspondre ni au nombre de lignes, ni au nombre de colonnes. C’est la création de dégradés qui amènent à faire des répétitions en fonction du nombre de lignes et du nombre de colonnes.

3. Manipulation de fichiers

a. Énoncé

Python permet de manipuler des fichiers, c’est-à-dire de lire un fichier ou d’écrire dans un fichier.

I Ouverture d’un fichier

Pour ouvrir le fichier exemple.txt dans le but de le lire on utilise l’instruction :

fichiersource = open("exemple.txt","r",encoding = "utf-8")

On manipule ensuite le fichier en utilisant la variable fichiersource (on peut donner le nom de variable de notre choix).

Pour ouvrir le fichier exemple.txt dans le but d’écrire dedans on utilise l’instruction :

fichierresultat = open("exemple.txt","w",encoding = "utf-8")

On manipule ensuite le fichier en utilisant la variable fichierresultat (on peut donner le nom de variable de notre choix).

L’argument « r » ou « w » distingue donc la lecture (read) et l’écriture (write).

II Fermeture d’un fichier

Quand on a fini d’utiliser un fichier on doit le fermer. Pour fermer le fichier associé à la variable fichierexemple, on utilise l’instruction :

fichierexemple.close()

III Écriture dans un fichier

Si un fichier est ouvert avec l’option « w », on peut écrire dedans. On commence à écrire sur la première ligne.

Pour écrire du texte, par exemple P2, puis 42 sur la deuxième ligne dans le fichier associé à la variable fichierexemple, on utilise l’instruction :

fichierexemple.write("P2\n")
fichierexemple.write("42\n")

« \n » fait aller à la ligne.

Pour écrire le contenu d’une variable associée à un nombre, par exemple le contenu de la variable a associée à 42, dans le fichier associé à la variable fichierexemple, on utilise l’instruction :

fichierexemple.write(str(a)+"\n")

Avec ces instructions, on écrit dans le fichier ligne à ligne sans jamais revenir en arrière, en sautant des lignes à chaque fois que l’on rencontre « \n ».

IV Lecture d’un fichier

Lorsque l’on ouvre un fichier, on pointe sur la première ligne du fichier.
L’instruction :

fichierexemple.readline()

Permet de passer à la ligne suivante sur laquelle on pointe désormais, dans le fichier associé à la variable fichierexemple.

L’instruction :

texte=fichierexemple.readline()

Permet de lire la ligne du fichier sur laquelle on pointe, de stocker ce contenu dans texte et de passer à la ligne suivante sur laquelle on pointe désormais dans le fichier associé à la variable fichierexemple.

La suite d’instructions :

texte=fichierexemple.readline() 
while texte != "":
Traitement
texte=fichiersource.readline()

Permet d’appliquer les instructions de traitement dans toutes les lignes du fichier, à la variable fichierexemple jusqu’à ce qu’il y ait une ligne vide : en effet la première instruction permet d’associer la variable texte à la ligne pointée du fichier et ensuite tant que on n’est pas arrivé à une ligne vide, on applique le traitement et on associe à texte le contenu de la ligne suivante.

b. Commentaires

J’ai un usage pragmatique de cette partie. Je n’en fais pas une lecture magistrale. Les élèves intéressés y trouvent des explications sur la manipulation de fichiers par Python.
Les autres les liront ou non quand ils en auront besoin.

4. Modifier une image

a. Énoncé

Nous allons voir maintenant des fonctions qui, à partir d’un fichier pgm ou ppm, créent un nouveau fichier.

On manipule donc deux fichiers :

  • le fichiersource qui est le fichier de départ qu’on va lire
  • le fichierresultat qui est le fichier d’arrivée qu’on va écrire petit à petit.

I À partir d’un fichier pgm

Téléchargez le fichier modifierNB.py et le fichier chiot.pgm.

modifiernb.py.zip

   

chiot.pgm.zip
a) Copie d’une image pgm

Testez la fonction copier en décommentant l’instruction

copier("chiot.pgm","resultat.pgm")

Vous devez obtenir un fichier resultat.pgm qui correspond à la même image que chiot.pgm :

Essayez de comprendre les différentes instruction de la fonction copier en vous aidant des commentaires.

Télécharger le fichier burano.pgm et faites-en une copie dans le fichier deuxieme.pgm.

burano.pgm.zip
b) Changer le contraste d’une image

Pour foncer une image, on élève au carré la valeur des pixels et on divise la valeur obtenue par 256. On obtient un nombre plus petit, donc correspondant à un gris plus foncé

Testez la fonction foncer, l’image obtenue est plus foncée :

Pour éclaircir une image, il faut que les nuances de gris soient des nombres plus grands que ceux de l’image source. On va donc multiplier la valeur des pixels par 255 puis en prendre la racine carrée (fonction sqrt de la bibliothèque math).

Complétez la fonction eclaircir et testez-la vous devriez obtenir :

c) Négatif d’une image

Complétez maintenant la fonction negatif qui crée le négatif d’une image. Testez-la aussi sur le fichier lena.pgm.

lena.pgm.zip

II À partir d’un fichier ppm

Télécharger le fichier modifiercouleur.py.

modifiercouleur.py.zip
a) Obtenir une version noir et blanc d’une image couleur

On souhaite passer d’une image en couleur (ppm P3) à une image en noir et blanc (pgm P2). Pour cela on fait la moyenne des trois lignes qui donnent la nuance de rouge, de vert et de bleu de chaque pixel.

Complétez la fonction couleurversNB. Attention :

  • on ne copie pas à l’identique les trois premières lignes du fichier source puisqu’on passe du format P3 au format P2
  • on va considérer les lignes suivantes 3 par 3 car il faut 3 lignes pour avoir la nuance de rouge, celle de vert et celle de bleu.

Voici la transformation de l’image burano.ppm.

burano.ppm.zip


b) Passer d’une image en couleur à une image sépia

Une image sépia est une image en couleur donc ppm.

La transformation est un peu compliquée : on fait une moyenne pondérée de la nuance de rouge, vert et bleu : moyenne=0.2126*rouge+0.7152*vert+0.0722*bleu

Puis on compare moyenne à 100 sachant que seuil=100 :

  • si la moyenne est inférieure à 100, les nouvelles nuances de rouge, vert et bleu sont obtenues par
    k=moyenne/seuil
        rouge=94*k
        vert=38*k
        bleu=18*k
  • sinon k=(moyenne-seuil)/(255-seuil)
         rouge=94+k*(255-94)
         vert=38+k*(255-38)
         bleu=18+k*(255-18)

Complétez la fonction couleurverssepia et testez-la

b. Commentaires

On peut faire remarquer que même si les fichiers manipulés ne comportent pas beaucoup de pixels pour des images, leur taille est conséquente ce qui explique l’utilisation de formats compressés. Gimp permet de facilement convertir les fichiers dans différents formats et ainsi de faire des comparaisons.

On pourrait utiliser des boucles for dans les fonctions en extrayant le nombre de lignes et de colonnes de la deuxième ligne des fichiers, mais j’ai préféré utiliser une boucle while.

Pour les images ppm (en couleur), il est difficile pour une partie des élèves de comprendre que chaque passage dans la boucle traite 3 lignes (la valeur du rouge, du vert et du bleu) pour n’en écrire qu’une pour le passage au noir et blanc et trois nouvelles pour le filtre sépia.
De plus beaucoup d’erreurs sont dûes au fait que les élèves prennent comme première couleur rouge, la troisième ligne qui est le nombre de nuances. Lorsque la fonction lit le fichier, la dernière ligne est donc associée à une couleur rouge mais elle ne trouve ni la valeur verte, ni la valeur bleue associées puique que le fichier n’a plus de ligne ce qui provoque une erreur.

5. Lena, une référence en traitement d’images

b. Commentaires

Cette partie est simplement un lien vers un article qui présente l’image la plus utilisée pour développer des logiciels de traitement de l’image depuis 1973.

Un élève m’a fait remarquer que cela montrait que Playboy était un bon journal. Je lui ai expliqué que j’en faisais une autre analyse. On peut en effet se demander si des équipes composées à parts égales d’hommes et de femmes auraient choisi la même image. Est-ce que les assistants vocaux comprendraient aussi bien les voix de femmes que celles d’hommes s’ils avaient été développées et testées par des équipes à parts égales d’hommes et de femmes ? Ou encore est-ce que les visages des minorités seraient aussi bien reconnus que ceux des blancs si les équipes de développement étaient plus diversifiées ?

6. Image secrète

a. Énoncé

On va maintenant voir une façon de cacher une image dans une image.

I Retrouver une image cachée

On dispose de deux fichiers ppm : le fichier original et le fichier reçu.
Pour connaître l’image cachée, il faut créer un fichier pgm. Dans ce fichier, un pixel sera blanc si la nuance de rouge de ce pixel est la même dans le fichier original et le fichier reçu, sinon ce pixel sera noir. L’image cachée est écrite noir sur blanc dans le fichier qui vient d’être créé.

Dans un nouveau fichier, créez un programme qui écrit le fichier pgm à partir du fichier original et du fichier reçu.
On dispose de deux jeux de fichiers pour les tests : glacier.ppm et glaciersecret.ppm d’une part, venise.ppm et venisesecret.ppm d’autre part.

glacier.ppm.zip
glaciersecret.ppm.zip
venise.ppm.zip
venisesecret.ppm.zip

II Coder un message

Pour coder un message, il faut :

  • sélectionner une image ppm
  • créer une autre image ppm de la même taille (même nombre de lignes et même de colonnes) dans laquelle le message sera écrit noir sur blanc.
  • créer une image ppm dont l’apparence sera la même que la première image mais dans laquelle sera caché le message secret.

Voici la marche à suivre pour obtenir ces 3 images :

  1. Pour l’image d’origine :
    1. Choisissez une image qui sera l’image d’origine
    2. Ouvrez-la avec gimp.
    3. Afin de limiter sa taille ouvrez l’onglet image/échelle et taille de l’image et choisissez 400 px comme largeur. Mémoriser la largeur 400 et la hauteur.
    4. Sauvez-la au format ppm, choisir ASCII. Pour cela onglet Fichier/exporter sous, donnez un nom .ppm
  2. Pour l’image en noir et blanc sur laquelle est écrit le message secret :
    1. onglet fichier/nouvelle image, choisissez la même largeur et la même hauteur.
    2. Faites un zoom (touche CTRL + molette de la souris)
    3. Pour écrire le message onglet Outils/outils de peinture/crayon
    4. Pour la sauvegarde onglet Fichier/exporter sous, donnez un nom .ppm, choisir ASCII
    5. Supprimer la seconde ligne # CREATOR ...
  3. Pour créer l’image à envoyer qui a l’apparence de l’image d’origine mais dans laquelle est cachée le message secret :
    On crée à l’aide d’un nouveau programme un nouveau fichier ppm dont les nuances de vert et bleu d’un pixel sont identiques à l’image originale et pour la nuance de rouge on ajoute 1 à celle de l’image originale si le pixel du message est noir et on garde la même sinon (attention si la nuance est 255, on passe à 254). À l’œil nu on ne voit pas la différence entre l’originale et l’image ainsi créée.

b. Commentaires

Manipuler 3 fichiers, deux en lecture et un en écriture s’avère réellement difficile pour les élèves. Il est crucial de comprendre que les têtes de lecture doivent avancer à la même vitesse donc être toutes en même temps à la 15e ligne ou à la 32e ligne de leur fichier respectif. Comme la seule façon proposée pour avancer la tête de lecture pour les fichiers en lecture est de lire la ligne, il arrive que le programme lise des lignes dont il ne fait aucun usage (comme les couleurs verte et bleue quand on recherche l’image secrète).

Dans cette activité l’image secrète est bicolore, une erreur faite par certains élèves est de prendre une image avec des nuances de gris là où on utilise une image avec seulement deux couleurs noir et blanc.


Dans le même numéro