Images

Négatif.

L'image à charger ici est une photographie de l'entrée du lycée au format ppm.

L'objectif de ce premier exercice est de lire les données dans ce fichier ppm et de créer un second fichier ppm qui contiendra l'image en négatif (ce qui signifie que chaque entier apparaissant dans le code d'un pixel est transformé en son complément à 255, c'est à dire x↦255-x).

Il s'agit donc de passer de l'image de gauche à l'image de droite :

LyceeMongeLyceeMonge inversé

Vous aurez éventuellement besoin des fonctions join() et split() pour lesquelles vous trouverez une présentation ici.

Résolution de l'exercice "Négatif".

Une solution possible est présentée ci-dessous. Prenez le temps de tester, de faire des modifications, d'ouvrir les fichiers images associés...


#ouverture en lecture
# du fichier source
fsource=open('LyceeMonge.ppm','r')

# ouverture en écriture du fichier
# à créer
fbut=open('invLyceeMonge.ppm','w')


# on recopie les 3 lignes d'entête
# de la source vers le but
for i in range(3) :
	L=fsource.readline()
	fbut.write(L)

#les lignes suivantes sont des chaînes constituées
# d'entiers entre 0 et 255 
# et terminées par '\n'

L=fsource.readline()
while L : # tant que la ligne lue n'est pas vide
	# suppression de '\n' en fin de chaîne
	L.rsplit('\n')
	# conversion en liste :
	L=L.split()
	# conversion en liste d'entiers
	L=[int(x) for x in L]
	# liste des compléments à 255
	L=[255-x for x in L]
	#conversion en liste de str
	L=[str(x) for x in L]
	# écriture des éléments dans le fichier but :
	for x in L :
		fbut.write(x+'\n')
	#lecture de la ligne suivante dans le fichier source
	L=fsource.readline()

fsource.close()
fbut.close()

Le zèbre trois fois trop lourd.

Le fichier à charger ici est une photo d'un zèbre au format ppm.

  1. Ouvrez ce fichier avec un éditeur de texte. Expliquez pourquoi on peut dire que ce fichier est trois fois trop lourd (il s'agit du poids en octets bien sûr) en observant les codes couleurs des pixels.
  2. En cherchant sur le web, la définition du format pgm (par exemple ici), écrire un programme python qui crée un fichier de l'image environ trois fois moins lourd.

Résolution de l'exercice "Le zèbre lourd ".

Rappelons que chaque pixel est codé, dans le format ppm, par trois entiers (compris entre 0 et 255 et correspondant aux intensités respectives de rouge, vert, bleu).
On lit dans le fichier que chaque paquet de trois entiers correspondant à un pixel est constitué de trois entiers égaux. L'information est donc redondante et on devrait pouvoir la réduire.
Il se trouve que le format pgm (images en niveaux de gris) permet cette économie : dans ce format pgm, chaque pixel est codé par un seul entier entre 0 et 255, entier correspondant à l'intensité du gris du pixel.


#ouverture en lecture
# du fichier source
fsource=open('zebre.ppm','r')

# ouverture en écriture du fichier
# à créer
fbut=open('zebre.pgm','w')


# la première ligne est modifiée :
L=fsource.readline()
fbut.write('P2\n')
# on recopie les 2 lignes suivantes
# de la source vers le but
for i in range(2) :
	L=fsource.readline()
	fbut.write(L)

#les lignes suivantes sont des chaînes constituées
# d'entiers entre 0 et 255 
# et terminées par '\n'


ListeDesCodes=[]

L=fsource.readline()
while L : # tant que la ligne lue n'est pas vide
	
	# suppression de '\n' en fin de chaîne
	L.rsplit('\n') 
	# conversion en liste :
	L=L.split()
	
	# ajout à la liste des codes :
	ListeDesCodes.extend(L)
	#lecture de la ligne suivante dans le fichier source
	L=fsource.readline()
	
	
# on ne retient qu'une copie des trois entiers codant un pixel :
ListeCodesReduite=[]
for j in range(0,len(ListeDesCodes),3) :
	ListeCodesReduite.append(ListeDesCodes[j])
	

# écriture des éléments dans le fichier but :
for x in ListeCodesReduite :
	fbut.write(x+'\n')
	
  
fsource.close()
fbut.close()

Consultez les poids des deux fichiers (pour le ppm initial : 7.9 Mo, pour le pgm obtenu : 2.6 Mo ). On a bien un rapport de 3 environ.

Griser.

Le fichier à charger ici est une photo de fruits et légumes au format ppm.

L'objectif est de transformer cette photo en photo en niveaux de gris. On cherche donc à passer de la joyeuse image de gauche à la triste image de droite.

coloré triste

Vous pourrez vous inspirer de l'exercice précédent pour trouver une solution.

Résolution de l'exercice "Griser".

L'exercice précédent peut suggérer que l'on obtiendra une image en divers gris avec des intensités égales en rouge, vert, bleu pour chaque pixel.

Un moyen simple de rendre les intensités RGB d'un pixel égales en conservant une différence entre pixels est de calculer la moyenne des intensités RGB.
On trouve sur le web des formules telles que code du gris = 0.2125 R + 07154 G + 0.0721 B qui permettent d'améliorer assez sensiblement les résultats sur certaines images.


#ouverture en lecture
# du fichier source
fsource=open('fruitslegumes.ppm','r')

# ouverture en écriture du fichier
# à créer
fbut=open('fruitslegumes.pgm','w')


# la première ligne est modifiée :
L=fsource.readline()
fbut.write('P2\n')
# on recopie les 2 lignes suivantes
# de la source vers le but
for i in range(2) :
	L=fsource.readline()
	fbut.write(L)

#les lignes suivantes sont des chaînes constituées
# d'entiers entre 0 et 255 
# et terminées par '\n'


ListeCodesPPM=[]

L=fsource.readline()
while L : # tant que la ligne lue n'est pas vide
	
	# suppression de '\n' en fin de chaîne
	L.rsplit('\n')
	# conversion en liste :
	L=L.split()
	
	# ajout à la liste des codes :
	ListeCodesPPM.extend(L)
	#lecture de la ligne suivante dans le fichier source
	L=fsource.readline()
	
	
# un pixel pgm est codé par la moyenne
# des trois entiers codant le pixel
# correspondant du fichier ppm
ListeCodesPGM=[]
for j in range(0,len(ListeCodesPPM),3) :
	m=(int(ListeCodesPPM[j])+int(ListeCodesPPM[j+1])+int(ListeCodesPPM[j+2]))//3
	ListeCodesPGM.append(str(m))
	

# écriture des éléments dans le fichier but :
for x in  ListeCodesPGM  :
	fbut.write(x+'\n')
	 
  
fsource.close()
fbut.close()

Remarque

Dans la seconde série d'exercices, nous utiliserons le module PIL.

Ce module permet de manipuler les images et automatise bien sûr ce genre de traitement.

Exemple avec l'image suivante au format jpg :
panda


from PIL import Image

# ouverture de l'image initiale :
imageSource=Image.open('ptpanda.jpg')
# conversion en niveaux de gris :
imageSource=imageSource.convert('L')
# sauvegarde du résultat sous un nouveau nom :
imageSource.save('pandagris.jpg')
# on lance une visualisation :
imageSource.show()

On obtient :
panda

Le créateur de rose.

Le fichier à charger ici est la photo d'une rose au format ppm.

L'objectif est de créer une catégorie de rose verte.

En d'autres termes, vous devez transformer la rose de gauche en celle de droite.

rose verte

Résolution de l'exercice "Le créateur de rose".

L'idée consiste à simplement échanger les intensités de rouge et de vert.


#ouverture en lecture
# du fichier source
fsource=open('rose.ppm','r')

# ouverture en écriture du fichier
# à créer
fbut=open('verte.ppm','w')


 
# on recopie les 3 lignes d'entête
# de la source vers le but
for i in range(3) :
	L=fsource.readline()
	fbut.write(L)

#les lignes suivantes sont des chaînes constituées
# d'entiers entre 0 et 255 
# et terminées par '\n'


ListeCodesRose=[]

L=fsource.readline()
while L : # tant que la ligne lue n'est pas vide
	
	# suppression de '\n' en fin de chaîne
	L.rsplit('\n') 
	# conversion en liste :
	L=L.split()
	
	# ajout à la liste des codes :
	ListeCodesRose.extend(L)
	#lecture de la ligne suivante dans le fichier source
	L=fsource.readline()
	
	
# on échange les intensités de vert et de rouge
ListeCodesVerte=[]
for j in range(0,len(ListeCodesRose),3) :
	a, b, c= ListeCodesRose[j], ListeCodesRose[j+1], ListeCodesRose[j+2]
	ListeCodesVerte.append(b+' '+a+' '+c)
	

# écriture des éléments dans le fichier but :
for x in  ListeCodesVerte  :
	fbut.write(x+'\n')
	 
  
fsource.close()
fbut.close()