Une image informatique est constituée d'un ensemble de points élémentaires, appelés pixels; la vision de ces pixels de plus ou moins loin permet à l’œil de reconstituer globalement l'image réelle.
Ces pixels étant organisés en "lignes" et en "colonnes", c'est à dire une matrice ( en anglais bitmap ), on parle d'image matricielle lorsque l'on décrit effectivement l'image pixel par pixel. ( il existe en effet un autre type d'images dites vectorielles, qui ne sont pas décrites point par point mais par des fonctions mathématiques : droites, cercles, courbes,...)
On comprend que ce principe est à l'origine des limitations liées aux images matricielles :
Un compromis est donc généralement à faire entre la finesse de l'image et la taille du fichier résultant; ce compromis dépend de la destination de l'image : affichage en petite ou grande taille, affichage ou impression, envoi ou pas sur un réseau,...
Les fichiers d'images vectorielles sont beaucoup plus "légers", mais par contre, ils ne permettent pas de représenter tous les détails d'une photo par exemple.
Pour coder par exemple un pixel rouge en mode 8 bits, les trois valeurs seront ainsi : (255,0,0); pour un bleu : (0,0,255); un jaune ( mélange de rouge et de vert ) : (255,255,0),etc...
On voit tout de suite le lien avec la notion de matrices pour représenter une image matricielle en mémoire d'un ordinateur :
Toutes ces informations sur les pixels, il va bien falloir les stocker dans un fichier à un moment donné !
De nombreux formats de fichiers image existent, le plus connu et le plus utilisé de nos jours est le format JPEG (Join Photographic Expert Group); le problème est qu'il s'agit d'un format compressé assez délicat à manipuler.
Pour simplifier notre travail nous utiliserons deux formats d'image beaucoup plus simples et non compressés : le format PGM ( pour des images monochrome ou en niveaux de gris ) et PPM ( images en couleur ).
Le but étant de vous faire manipuler des matrices et pas de vous ennuyer avec des problèmes d'écriture de fichiers, vous trouverez ici un script contenant deux fonctions pour ouvrir et écrire des fichiers au format PGM ou PPM.
from images import *
data = lecture('nom_du_fichier.pgm/ppm')
Cette fonction renvoie la matrice contenant les valeurs des pixels de l'image, soit, selon l'extension du fichier, des valeurs uniques de niveaux de gris pour les fichiers PGM, ou des tuples de trois valeurs (R,V,B) pour les PPM ).
ecriture(data,'nom_du_fichier.pgm/ppm')
La fonction détecte l'extension du fichier : la matrice data devra donc contenir des valeurs en cohérence avec le format du fichier ( valeurs uniques de niveaux de gris pour les fichiers PGM, ou tuples de trois valeurs (R,V,B) pour les PPM ).
Visualisation des fichiers créés
Une fois écrits sur le disque, les fichiers images peuvent être ouverts en double-cliquant sur leur nom.
Vous allez écrire un unique script qui utilise des matrices pour créer automatiquement des images numériques et les enregistrer au format PGM ou PPM.
Pour chaque image, vous écrirez une fonction qui construira la matrice des valeurs de pixels, et qui renverra ensuite cette matrice au programme principal.
La matrice sera construite selon une méthode à votre choix : élément par élément, ou par compréhension.
Voila un exemple qui crée une image de 200 x 200 pixels tous noirs :
from images import *
def noir()->list:
'''
Fonction qui créé une matrice correspondant à une image de 200 x 200 pixels noirs
Entrée :
Aucune
Sortie :
la matrice des 200 x 200 valeurs des pixels
'''
m = [[0 for col in range(200)] for lin in range(200)] # construction de la matrice contenant les valeurs des pixels ( 0 = noir )
return m
'''PROGRAMME PRINCIPAL'''
data = noir() # appel de la fonction et récupération de la matrice qu'elle a construit
ecriture(data, 'noire.pgm') # écriture du fichier image
Commençons pour simplifier par des images en niveaux de gris.
Une image contenant des pixels de valeurs aléatoires ( entre 0 et 255 ), et dont la largeur, la hauteur sont passées comme arguments à la fonction.
Attention, plus délicat; si vous avez du mal avec la construction par compréhension, suivez ces deux étapes pour mener à bien votre codage :
Et maintenant, un peu de couleur...Vous pourrez souvent vous inspirer des scripts précédents pour créer les images suivantes au format PPM.
Rappelez-vous que dans ce cas, la couleur d'un pixel est codée non pas par une valeur unique, mais par un tuple de 3 valeurs représentant, dans l'ordre, la composante Rouge, la Verte et la Bleue ( chaque composante variant entre 0 et 255 ).
Chaque "case" des matrices représentant l'image contiendra donc un tuple de 3 valeurs et non pas une valeur unique.
Voila un exemple qui crée une image de 200 x 200 pixels tous rouges :
from images import *
def rouge()->list:
'''
Fonction qui créé une matrice correspondant à une image de 200 x 200 pixels rouges
Entrée :
Aucune
Sortie :
la matrice des 200 x 200 valeurs des pixels
'''
m = [[(255,0,0) for col in range(200)] for lin in range(200)] # construction de la matrice contenant les valeurs des pixels ( (255,0,0) = rouge )
return m
'''PROGRAMME PRINCIPAL'''
data = rouge() # appel de la fonction et récupération de la matrice qu'elle a construit
ecriture(data, 'rouge.ppm') # écriture du fichier image
Une image contenant des pixels ayant chacun une couleur aléatoire, et dont la largeur, la hauteur sont passées comme arguments à la fonction.
Il va s'agir maintenant d'utiliser de "vraies" images ( des photos, quoi...), pour les manipuler comme on le ferait avec un logiciel de retouche d'images.
Voila deux images au format PGM et PPM sur lesquels vous allez pouvoir travailler :
Vous écrirez les fonctions qui permettront de transformer la matrice des valeurs de pixels pour obtenir l'effet recherché.
Le programme principal de votre script devra :
La fonction devra au préalable faire une copie de la matrice des pixels d'origine, et ne travailler ensuite que sur cette copie.
from images import *
def ma_fonction(matrice)->list:
'''
Fonction qui modifie une matrice de pixels pour obtenir un certain effet
Entrée :
la matrice des valeurs de pixels de l'image
d'autres paramètres si besoin...
Sortie :
une matrice des valeurs de pixels modifiées
'''
...... copie de la matrice d'origine
....... modification de la matrice des valeurs de pixels
return matrice_modifiee
'''PROGRAMME PRINCIPAL'''
data = lecture('fichier_exemple.pgm') # lecture du fichier image d'origine et récupération de la tableau des valeurs de ses pixels
data2 = ma_fonction( data ) # appel de la fonction et récupération de la matrice modifiée
ecriture(data2, 'fichier_exemple MODIF.pgm') # écriture du fichier image modifié
Effet très populaire dans les années 70 et 80 : les pixels blancs de l'image sont transformés en pixels noirs, et vice et versa; de manière générale, toutes les valeurs de pixels sont remplacées par leur complément à 255 :
Effet qui revient à transformer une image en niveaux de gris en une image monochrome : tous les pixels en dessous d'une certaine valeur ( appelée "seuil" ) sont transformés en pixels noirs ( valeur = 0 ), et tous
les pixels de valeur supérieure au seuil sont transformés en pixels blancs ( valeur = 255 ). Il n'y a donc effectivement plus que deux "couleurs" dans l'image.
Selon la valeur du seuil ( que l'on passera en argument à la fonction ), on obtient des effets différents :
Ou comment faire pivoter l'image de 180° ?
Indication : vous pouvez vous inspirer de la manière dont vous avez inversé une chaîne de caractères...
Comment transformer une image en couleur en image en niveaux de gris ?
Indication : il faut remplacer chaque tuple de valeurs (R,V,B) par un nombre égal à la moyenne de ces trois valeurs.