Tous les articles par Erika Follien

Programmation du traitement d’image avec python

Dans la section précédente, vous avez utilisé un logiciel de traitement d’image (Photofiltre) qui contient différents algorithmes permettant de modifier automatiquement des images. Dans un appareil photo ou un smartphone, il y a aussi de tels types d’algorithmes. Ici, vous allez programmer vous-mêmes en Python différents algorithmes permettant de modifier des images.

INDISPENSABLE : Pour travailler avec Python, il faut créer un répertoire (par exemple travail) dans lequel vous enregistrerez à la fois vos fichiers Python (format .py) et vos images (format .png)

A la fin de la section, vous zipperez (= clic droit > compresser) ce répertoire contenant l’intégralité des fichiers .py et .png pour nous le rendre avec votre compte-rendu.

A faire vous-même 0 : Configurer le logiciel Thonny dans lequel on va programmer en Python

Ouvrez le logiciel Thonny (faire une recherche avec la loupe)

Une boite de dialogue apparaît avec le message suivant : « Can’t find backend ‘LocalCPython’. Please select another backend from options »

  • ouvrir le menu Outils > Options > Onglet Interpéteur
  • choisir l’option par défaut : « Le même interpréteur qui exécute Thonny »

Ensuite, il est nécessaire d’importer la librairie PILLOW (Python Imaging Library) qui fournit les outils nécessaires pour les manipulations d’images :

  • de nouveau, ouvrir le Menu Outil > Gérer les paquets…
  • écrire « Pillow » dans la barre de recherche et cliquer sur rechercher
  • Cliquer sur le lien « pillow » dans la liste obtenue

A faire vous-même 1 : Créer une image avec Python

Voici un script qui génère deux images en couleurs RVB (=RGB en anglais) de dimension 100 x 100.

Tapez-le dans l’éditeur de script de Thonny (fenêtre du haut) et enregistrez-le sous le nom afvm1.py dans votre dossier de travail créé précédemment.

Exécutez le script (icône « lecture »)

from PIL import Image
im=Image.new("RGB", (100, 100)) 
im2= Image.new("RGB", (100, 100), (255,255,255))
im.save("afvm1_1.png")
im2.save("afvm1_2.png") 
  • Vérifiez que vous avez 2 images créées dans le dossier de travail (sinon demander de l’aide)
  • Lancez le logiciel Photofiltre et ouvrez les 2 images créées
  • Expliquez la couleur de l’image afvm1_1.png

Pour modifier la couleur de l’image, il suffit de modifier la couleur de chaque pixel.

On va utiliser la commande putpixel((x,y), (a, b, c)) qui permet de colorer le pixel de coordonnées (x, y) avec la couleur RVB (a, b, c) où a, b et c sont les valeurs de luminance de chaque canal, comprises entre 0 et 255.

Remarque : x est le n° de colonne et y est le n° de ligne. Le 1er pixel en haut à gauche a pour coordonnées (0,0)

A faire vous-même 2 : mettre de la couleur

Dans l’éditeur Thonny, modifiez le script précédent en ajoutant la boucle « for » suivante.

Attention  !

  • respectez l’indentation qui délimite les blocs de code (Elle se fait avec la touche de tabulation « tab »)
  • n’oubliez pas les « deux-points » : à la fin de la ligne for
from PIL import Image
im=Image.new("RGB", (100, 100))
for x in range (100):
    for y in range(100):
        im.putpixel((x,y),(0,255,0))
im.save("afvm2.png")
  • Expliquez ce que produit la boucle ajoutée sur l’image.
  • Remplacez la boucle par celle donnée ci-dessous et expliquez le résultat.
for x in range (50):
    for y in range (50,100):
        im.putpixel((x,y),(0,255,0))  

A faire vous-même 3 : coder des drapeaux

Le script suivant permet de produire le drapeau français sous forme d’une image de dimension 120×100 pixels. Une première boucle « for » permet de parcourir les lignes de l’image. Les boucles for imbriquées (attention aux indentations) parcourent les colonnes dans un rectangle donné et y affectent une couleur.

from PIL import Image
col=120
lgn=100
im=Image.new("RGB", (col,lgn))
#il y a 3 bandes verticales, on définit la variable bande :
bande=col//3
for y in range (100):
    for x in range (bande):
        im.putpixel((x,y),(0,0,255))
    for x in range (bande, (2*bande)):
        im.putpixel((x,y),(255,255,255))
    for x in range ((2*bande), col):
        im.putpixel((x,y),(255,0,0))
im.save("france.png")

Après avoir compris le script précédent, vous allez le modifier pour produire d’autres drapeaux. Pensez à enregistrer votre script modifié sous un autre nom et à modifier également le nom de l’image enregistrée par python pour ne pas écraser l’image précédente.

Enregistrez vos différentes versions de script jusqu’à ce que cela fonctionne. Vous joindrez vos scripts python afvm3-irlande et afm3-colombie à votre compte-rendu.

  • Modifiez les arguments de la commande putpixel() pour reproduire le drapeau irlandais. (pour avoir le code RGV des couleurs, vous pouvez les sélectionner sur une image avec Pixie ou avec la pipette de Photofiltre)
  • Pour ceux qui aiment les défis : plus difficile : modifiez les arguments de la commande putpixel() pour reproduire le drapeau colombien

A faire vous-même 4 : apporter des nuances

Avec quelques petites astuces, on peut aussi produire des dégradés assez facilement. Voici un script qui permet d’obtenir deux dégradés de bleu différents.

from PIL import Image
largeur = 255
hauteur = 255
im=Image.new('RGB', (largeur, hauteur))
for x in range(largeur):
    for y in range(hauteur):
        im.putpixel((x, y), (0, 0, y))
im2=Image.new('RGB', (largeur, hauteur))
for x in range(largeur):
    for y in range(hauteur):
        im2.putpixel((x, y), (0, 0, x))
im.save("camaieubleu1.png")
im2.save("camaieubleu2.png")   
  • Expliquez la ligne 7 du script précédent.
  • Expliquez la différence entre les 2 images.
  • Modifiez le script pour produire le dégradé suivant et enregistrer l’image sous le nom degrade.png

Dans un logiciel de traitement d’image comme Photofiltre, ou celui qui est présent dans l’appareil photo, il est possible de faire des corrections automatiques comme passer l’image en négatif.

Le principe de l’algorithme est de donner pour chaque pixel la couleur inverse : cette couleur est calculée selon le principe suivant :

A faire vous-même 5 : l’image en négatif

  • Enregistrez une image de votre choix dans votre répertoire de travail (pensez à choisir une image dont la licence vous permet sa modification)

Voici une partie du script permettant de créer le même effet négatif.

La commande pix = img.getpixel((x,y)) permet d’affecter dans une variable pix  les valeurs des canaux RVB extraites du pixel de coordonnées (x,y).

On peut exprimer ces valeurs sous forme d’un 3-tuple (c’est-à-dire une collection de 3 valeurs, ici correspondant aux 3 canaux RVG) :      p = (pix[0], pix[1], pix[2]) que l’on peut affecter à une variable (ici p) pour l’utiliser ensuite.

Remarque : les indices entre [ ] permettent d’accéder aux différents éléments du tuple. Pour accéder à un élément d’indice   i  d’un tuple t , on écrit      t[i]

  • On veut transformer chaque pixel de l’image (variable pix) en son négatif (variable pixneg). Trouvez comment calculer pixneg à partir de pix.

L’extrait de script ci-dessous permet d’ouvrir l’image que vous avez enregistrée, puis de créer une nouvelle image qui sera son négatif. Il manque dans le script suivant 3 lignes (respectez les indentations !) qui permettent de passer l’image en négatif.

  • À vous de les écrire et de tester le résultat. Vous joindrez vos images et votre script à votre compte-rendu.
from PIL import Image
  
img = Image.open(MonImage)
col,lgn = img.size
imgF = Image.new(img.mode,img.size)
print("Patientez pendant l'exécution du script …")
  
for x in range(col):
    for y in range(lgn):
...
...
... 
print("… C'est fait !, voir le résultat avec Photofiltre")
imgF.save("image_negatif.png")   

Parmi les retouches d’images très utilisées pour incruster un logo, un copyright ou une signature dans une image, il y a la fusion de deux images. Il s’agit de transformer plus ou moins légèrement la couleur des pixels de manière à ce que l’incrustation ne puisse pas être enlevée facilement.

L’opération mathématique à appliquer pour modifier l’encodage des pixels est la suivante :

                (R1, V1, B1)           est le 3-tuple de l’image 1,         

                (R2, V2, V2)          est le 3-tuple de l’image 2

                a             est le coefficient de dominance d’une image sur l’autre, dont la valeur est comprise entre 0 et 1.

A faire vous-même 6 : fusion d’images

  • Utilisez les informations ci-dessus pour compléter le script suivant de façon à obtenir une fusion des drapeaux de la France et de la Colombie.

Astuce : les valeurs (R,V,B) d’un pixel sont obligatoirement des entiers à utilisez     int()

La ligne 2 indique qu’il faudra entrer la valeur de a dans le shell (fenêtre de droite). Vous pourrez essayer différentes valeurs de a et comparer les images produites. Dans ce cas, pensez à modifier le nom du fichier enregistré (ligne 17) sous peine d’écraser le fichier précédent.

(Vous pouvez bien sûr utiliser des images de votre choix dans ce script, mais les 2 images doivent avoir les mêmes dimensions)

from PIL import Image
a=float(input("Entrez la valeur de a : "))
  
im1 = Image.open('france.png')
im2 = Image.open('colombie.png')
  
largeur,hauteur = im1.size
  
im = Image.new('RGB', (largeur, hauteur))
    for x in range(largeur):
        for y in range(hauteur):
            pix1 = im1.getpixel((x,y))
            pix2 = im2.getpixel((x,y))
            fusion = .......................... 
            im.putpixel((x,y),fusion)
  
im.save('fusion.jpg') 

Codage de l’image et capteur photo

Commençons par un bref historique de la photo sur cette vidéo:

La photo : de l’argentique au numérique

Revenons un petit peu en arrière à l’époque du Noir et Blanc:

Bien entendu, le codage en noir et blanc ne donne pas des images de bonne qualité !

On appelle profondeur de couleur le nombre de bits utilisés pour coder la couleur d’un pixel. Pour une image en noir et blanc, la profondeur est de 2 bits. Cela ne suffit pas pour donner une image correcte d’un ensemble complexe : en fait, la photographie en « noir et banc », n’est pas codée en noir et banc, mais en nuances de gris.

Ces 2 images correspondent à une même prise de vue, mais l’une est en noir et blanc (image en noir et blanc) et l’autre en nuances de gris (= image monochrome)

Souris en Noir et Blanc
La même souris, en nuances de gris

Un capteur photographique (dans un appareil photo ou un smartphone) contient des photosites : il s’agit de composants électroniques qui convertissent l’énergie lumineuse en tension électrique. Les tensions électriques seront converties en valeurs numériques par l’ordinateur afin de reconstituer les pixels.

 

A faire vous-même 1: codage en niveau de gris

Dans les travaux précédents, vous avez utilisé des images en noir et blanc : chaque pixel était encodé sur 1 bit. Pour avoir des nuances de gris, il est nécessaire d’avoir un encodage plus complexe utilisant davantage de bits pour un pixel. Par exemple, chaque bit pouvant prendre 2 valeurs, avec 2 bits, on peut obtenir 4 nuances.

En général, pour une image monochrome, la profondeur de couleur est de 8 bits : combien de nuances de gris sont possibles ?

Une photographie en couleur rendra encore mieux la réalité. Dans l’œil humain, la rétine contient des cellules sensibles au changement de luminosité (les bâtonnets) et des cellules sensibles à des radiations particulières de la lumière : les cônes.  Il existe 3 types de cônes : ceux qui sont sensibles aux radiations bleues, ceux qui sont sensibles au vert et ceux qui captent plutôt les rouges.  Grâce à ces 3 types de cônes, on peut voir toutes les couleurs par synthèse additive.

Ces 3 couleurs de lumière sont dites primaires.

Pour obtenir une photographie en couleurs, il y a devant le capteur photographique des filtres colorés comme la matrice Bayer RVB (Rouge, Vert, Bleu). On utilise donc un codage en Rouge/Vert/bleu.

La matrice Bayer est composée de 50 % de filtres verts (car l’œil humain est capable de distinguer de très nombreuses nuances de verts), 25 % de filtres rouges et autant de bleus.  

Il existe différents types de filtres (voir https://geometrian.com/programming/reference/subpixelzoo/index.php) qui permettent tous de capter pour chaque pixel, la luminance en rouge, vert et bleu.

Un pixel sera donc composé des informations en luminance des photosites par synthèse additive des couleurs primaires R, V, B

Expliquez en quoi consiste la synthèse additive (si besoin, faites une recherche)

On codera donc un pixel à l’aide d’un triplet de valeurs (par exemple 247, 56, 98). La première valeur donnant l’intensité du canal rouge, la deuxième valeur donnant l’intensité du canal vert et la troisième valeur donnant l’intensité du canal bleu (RVB ou RGB en anglais).

Expliquez pourquoi, pour chaque canal de chaque pixel, l’intensité lumineuse est comprise entre 0 et 255.

Si chaque canal est codé avec 8 bits, quelle est la profondeur de couleur ?

Combien de couleurs différentes sont-elles possibles avec une telle profondeur ?

A faire vous-même 2

Lancez le logiciel photofiltre puis ouvrez l’image souris.jpeg

Avec l’outil pipette (copie d’écran), prélevez différentes couleurs et donnez les codes correspondants en RVB.

A faire vous-même 3

Menu Réglage > négatif

Que deviennent les différentes couleurs ?

Donnez les codes RVB correspondants.

A faire vous-même 4

 A l’aide de l’outil Pixies à lancer ici, relevez le code RVB de la couleur sélectionnée en avant plan.

https://icn-isn-boissy.yj.fr/wp/wp-content/uploads/2020/02/pixie.zip

Calculez la couleur qu’on obtiendrait avec le réglage négatif réalisé dans le « à faire vous-même 3 ». Quel nom pourrait-on lui donner ?

Codage des pixels de l’image en noir et blanc

Le codage le plus simple de l’image est celui en noir et blanc. Dans ce type de codage, la couleur est encodée sur un bit (=binary digit) qui peut prendre 2 valeurs (vrai ou faux, 0 ou 1, blanc ou noir, ouvert ou fermé… etc.)

Pour une image matricielle en noir et blanc, telle que votre image initiale1.png, chaque pixel est encodé par 1 bit noir ou blanc. Le format le plus élémentaire d’image en noir et blanc est le format .pbm (Portable Bit Map).

Vous disposez du fichier carré8×8.pbm qui correspond à un carré blanc de 8 X 8 pixels. Vous allez manipuler l’image avec le logiciel EditHexa ou éditeur en ligne HexEd.it.

Télécharger l’image zippé ci dessous, pensez à la dézipper et à l’enregistrer dans votre dossier.

Vous allez créer une image en manipulant son encodage. Pour chaque étape, votre compte-rendu comportera la copie d’écran de l’encodage et l’image obtenue.

A faire vous-même 1 : le codage d’un carré blanc

Lancez le logiciel EditHexa (ou HexEd.it en ligne) et ouvrez le fichier carré8×8.pbm

Dans la fenêtre centrale, la partie encadrée contient l’encodage en octets et à droite, il y a la traduction sous forme de texte selon la norme ASCII (à un code sur 7 ou 8 bits, correspond un caractère ou une commande)

Copie d’écran de EditHexa (pour HexEd.it, c’est le même principe)

A partir de ce fichier,

Quel est le nombre d’octets qui encodent l’entête de l’image ? (astuce : cliquer sur différents octets dans la fenêtre centrale et vérifier à droite, à quelle « partie » du fichier cela correspond)

Déterminez le nombre d’octets qui encodent l’image elle-même. Quelle valeur ont-ils ?

 

Vous avez vu précédemment qu’un octet de l’image (ou du texte de l’entête) correspond à un « nombre » à 2 éléments.

Exemples : le G de GIMP correspond à 47, l’espace entre les deux 8, c’est 20 ou le point correspond à 0A.

  • Le système décimal utilise 10 symboles (de 0 à 9) : c’est notre système habituel de numération.
  • Le système binaire utilise 2 symboles (0 et 1) : utilisé car en électronique, le courant passe ou pas.
  • Le système hexadécimal utilise 16 symboles (0 à 9 et A à F) : cela permet d’écrire des nombres plus longs avec moins de symboles à avantage pour le stockage en informatique. C’est l’idéal pour les images !

Pour faire le travail suivant, il va falloir convertir un octet écrit avec 8 bits dans le système binaire (donc une série de huit 0 ou 1) en sa correspondance dans le système hexadécimal.

Prenons l’exemple de 2 octets 0000 0000 et 0011 1101. (remarque, on on écrit le nombre binaire en 2 paquets de 4 )

Pour convertir ces octets dans le système hexadécimal, on utilise le tableau de conversion ci-dessous pour chaque paquet de 4.

  • 0000 0000 du système binaire devient 00 dans le système hexadécimal.
  • 0011 1101 du système binaire devient 3D dans le système hexadécimal.
Hexadécimal Binaire
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111

A faire vous-même 2 : le codage d’un carré noir et d’un damier

Modifiez les bits des octets de l’image de manière à former un carré noir. (si besoin, revoir ce qui a été fait sur le codage d’un pixel dans la section précédente)

  • Avec l’outil en ligne HexEd.it, modifiez les valeurs des octets de l’image.
  • Avec EditHexa : Utilisez menu Outils avancés > manipuler les bits ou modifiez directement les valeurs dans la fenêtre centrale.

Enregistrez votre image sous le nom carrénoir.pbm

Vérifiez votre manipulation en ouvrant le fichier avec Photofiltre ou Gimp (Par défaut, les fichiers du format .pbm sont masqués : cliquez sur le menu déroulant « images les plus courantes » puis sélectionnez « toutes les images »)

Pour obtenir un carré 8×8 à rayure, il faut par exemple que la première ligne soit noire. Ce sera donc une suite de huit bits à 1, c’est-à-dire un octet dont tous les bits valent 1 qu’on peut écrire 1111 1111 ou alors FF.
La deuxième ligne doit être blanche, donc c’est l’octet 0000 0000 ou 00 dans le système hexadécimal.
Et ainsi de suite…

Procédez de la même façon pour obtenir un damier que vous appellerez damier.pbm
astuce : au brouillon, réalisez un tableau de 8×8, coloriez les cases noires du damier que vous voulez obtenir.

A faire vous-même 3 : le codage de l’initiale

Avec Photofiltre ou Gimp, ouvrez l’image initiale2.png créée à la séance précédente. Affichez la grille de repérage avec un pas de 2 pixels.

Avec EditHexa ou HexEd.it, modifiez l’encodage de l’image carré8×8.pbm de manière à reproduire le motif de votre initiale2.png    Vous obtenez alors votre image (vérifiez avec Photofiltre) sur 8 X 8 pixels.

caractéristiques d’une image numérique

Avant tout, créer un répertoire « thème Photo » dans votre zone personnelle SNT.

Ajouter dans ce répertoire, un nouveau dossier appelé « travail » dans lequel vous enregistrerez toutes les étapes intermédiaires de vos travaux sur les images.

Pour ce thème et les suivants, vous devez progresser sur la mise en forme de votre CR. La mise en forme sera prise en compte dans l’évaluation. Pistes de progrès à respecter:

  • Rédaction sans fautes d’orthographe
  • Utiliser l’option Justifier le texte dans LibreOffice pour utiliser toute la largeur de la page (disponible avec marge gauche, droite ou centrer)
  • Utiliser l’option Rogner les images afin de ne montrer que l’essentiel de la copie d’écran que vous faites
  • Après Rogner penser à agrandir les images pour plus de lisibilité et éventuellement centrer les images
  • Utiliser les options classiques de mise en forme du texte: police de caractères, titre , gras , italique , couleur , taille , souligné pour mettre en évidence les différents corps de votre texte

Une image numérique est un tableau (=matrice) de pixels. Un pixel (Picture Element) est un carré élémentaire de l’image.

A faire vous-même 1

Ouvrez le logiciel Photofiltre puis ouvrez l’image carreblanc.png (Fichier>Ouvrir) ci-dessous.

  • Utilisez le scroll ou l’outil zoom pour grossir l’image au maximum.
  • Utilisez le plus petit outil pinceau (taille 1 pixel) pour dessiner en noir l’initiale de votre prénom

Enregistrer votre image sous le nom de fichier initiale1.png.

Une image est caractérisée par différents paramètres (revoir la vidéo si besoin) : la définition, la résolution, la taille.

A faire vous-même 2

Quelles sont les caractéristiques de l’image ? Fichier>Propriétés de l’image

  • quelle est sa définition ?
  • combien de pixels contient l’image initiale1.png ?
  • quelle est la taille réelle de l’image ?
  • quelle est sa résolution ?
  • vérifiez par le calcul la résolution indiquée.

pour vous aider allez voir ici.

vidéo à regarder tout sur la résolution.

rappels : la résolution s’exprime en français en ppp (= pixel par pouce) ou en anglais en dpi (=dot per inch)

                               1 pouce (1 inch en anglais) = 2,54 cm

Si on fait varier le nombre de pixels, on modifie certains paramètres de l’image :

A faire vous-même 3

Menu Affichage > afficher la grille de repérage

Menu Outils > Préférences > palette d’outils et grille

  • Modifiez les paramètres de grille tels que figurés sur l’image :

Vous obtenez un quadrillage par pixels en rouge sur votre image.

  • Vérifiez la définition de votre image et faites une copie d’écran à joindre au compte-rendu.
  • Chaque pixel est codé avec 1 bit qui peut prendre 2 valeurs : noir ou blanc. Comme un octet = 8 bits, quel est le poids théorique de cette image ?
  • Quel serait le poids de l’image si c’était juste un carré blanc ?

A faire vous-même 4

  • Modifiez à nouveau les paramètres de grille de façon à quadriller avec des carrés de 2×2 pixels.
  • Coloriez entièrement en noir chaque carré contenant au moins 1 pixel noir.
  • Enregistrez la nouvelle image sous le nom initiale2.png . Faites une copie d’écran à joindre au compte-rendu.

Si on considère que chaque carré de la nouvelle grille représente un pixel :

  • combien de pixels contient la nouvelle version de l’image ?
  • quelle est sa définition ?
  • la taille de l’image a-t-elle changé ?
  • quelle est alors sa résolution ?
  • quel est le poids de cette nouvelle version ?

A faire vous-même 5

application

  1. J’ai une photo dont la définition est de 3000 × 4000, la résolution est de 72 dpi. Quelle est la taille d’impression ?
  2. Je souhaite pouvoir l’imprimer en format 10 × 13.5 cm, donc réduire les dimensions tout en gardant le même nombre de pixels. Comment puis-je faire ? L’image sera-t-elle de bonne qualité ? Quelle est maintenant la nouvelle résolution ?