La manipulation des canaux RVB d'une image est un grand classique des modifications que l'on peut apporter et est implémentée de base dans tout bon logiciel de retouche d'image (comme The GIMP par exemple). Nous allons voir comment saturer les canaux RVB d'une image à l'aide d'un script Python, convertir une image en niveaux de gris et créer son négatif.
Saturation d'un canal RVB
Un des canaux RVB d'une image peut être saturé. Le principe est le suivant :
Voici un exemple de script créant une fenêtre contenant l'image modifiée du tableau la Vie de Marc Chagall coloré en bleu (canal bleu saturé)
import pygame
from pygame.locals import *
# Initialisation de la fenêtre d'affichage
pygame.init()
fenetre = pygame.display.set_mode((870,522))
pygame.display.set_caption("La Vie de Marc Chagall")
fond = pygame.image.load("lavie.jpg").convert()
# Création d'une image vide
blank_surface = pygame.Surface((870, 522))
# Lecture et remplacement de la couleur de chaque pixel
for i in range(870):
for j in range(522):
color=list(fond.get_at((i,j)))
color[2]=255
color=tuple(color)
blank_surface.set_at((i,j),color)
#collage du fond
fenetre.blit(blank_surface,(0,0))
pygame.display.flip()
# Boucle principale
continuer = 1
while continuer:
for event in pygame.event.get():
# Quitter
if event.type == QUIT:
continuer = 0
pygame.quit()
A noter ici que :
pygame.Surface((870, 522))
permet de créer une image vide de dimension donnée (ici 870 x 522).fond.get_at((i,j))
permet de récupérer la couleur du pixel de coordonnée (i,j) de l'objet fond. Cette couleur est récupérée sous la forme d'un tuple non modifiable, d'où la nécessité de convertir ce tuple en liste.color[2]=255
sature la valeur du pixel correspondant au canal Bleu. Le canal Rouge est accessible via color[0] et le canal Vert via color[1]. set_at
en conservant les coordonnées (i,j) du pixel et appliquée à l'objet blank_surface
.Exemple d'exercice d'appropriation : créer un deuxième script permettant cette fois-ci de saturer le canal Vert d'une image de votre choix et un autre script permettant de saturer le canal Rouge.
La correction du script de saturation du canal Vert est ici.
La correction du script de saturation du canal Rouge est ici.
Voici l'image de départ redimensionnée et les résultats obtenus :
Conversion d'une image en Niveaux de Gris
Une manière simple de convertir une image en niveaux de gris est de calculer la moyenne des valeurs RVB d'un pixel et d'affecter cette moyenne à tous les canaux.
import pygame
from pygame.locals import *
# Initialisation de la fenêtre d'affichage
pygame.init()
fenetre = pygame.display.set_mode((870,522))
pygame.display.set_caption("La Vie de Marc Chagall")
# Traitement de l'image
fond = pygame.image.load("lavie.jpg").convert()
# Création d'une image vide
blank_surface = pygame.Surface((870, 522))
# Lecture et remplacement de la couleur de chaque pixel
for i in range(870):
for j in range(522):
color=list(fond.get_at((i,j)))
moyenne=int((color[0]+color[1]+color[2])/3)
color[0],color[1],color[2]=moyenne,moyenne,moyenne
color=tuple(color)
blank_surface.set_at((i,j),color)
#collage du fond
fenetre.blit(blank_surface,(0,0))
pygame.display.flip()
# Boucle principale
continuer = 1
while continuer:
for event in pygame.event.get():
# Quitter
if event.type == QUIT:
continuer = 0
pygame.quit()
A noter ici que :
int((color[0]+color[1]+color[2])/3)
afin d'être sur que les valeurs de la liste color sont toutes des nombres entiers.Exemple d'exercice d'appropriation : créer un script permettant cette fois-ci d'afficher l'image obtenue en négatif .
La correction est ici.
Voici l'image en niveaux de gris obtenue et son négatif :
Filtrage de type INVERT sur une portion de l'image
Nous allons nous intéresser dans cette section à la manipulation d'une zone limitée de l'image en utilisant un événement de type souris : l'opération que nous allons effectuer a pour résultat l'affichage d'une portion de l'image dont les canaux RVB ont été modifiés, cette modification étant localisée au niveau du pointeur de la souris.
Le code proposé ci-dessous permet d'afficher en négatif une portion de l'image délimitée par une zone carrée de 50 pixels de côté entourant la position du curseur de la souris.
import pygame
from pygame.locals import *
# Initialisation de la fenêtre d'affichage
pygame.init()
fenetre = pygame.display.set_mode((870,522))
pygame.display.set_caption("La Vie de Marc Chagall")
# Traitement de l'image
fond = pygame.image.load("lavie.jpg").convert()
# Création d'une image vide
blank_surface = pygame.Surface((870,522))
# Lecture et remplacement de la couleur de chaque pixel
for i in range(870):
for j in range(522):
color=list(fond.get_at((i,j)))
moyenne=int((color[0]+color[1]+color[2])/3)
color[0],color[1],color[2]=255-moyenne,255-moyenne,255-moyenne
color=tuple(color)
blank_surface.set_at((i,j),color)
# Boucle principale
continuer = 1
while continuer:
for event in pygame.event.get():
# Quitter
if event.type == QUIT:
continuer = 0
fenetre.blit(fond,(0,0))
position=pygame.mouse.get_pos()
if position[0]>25 and position[1]>25 and position[0]<845 and position[1]<497:
surface2=blank_surface.subsurface(position[0]-25,position[1]-25,50,50)
fenetre.blit(surface2,(position[0]-25,position[1]-25))
pygame.display.flip()
pygame.quit()
Etudions certaines parties de ce code:
pygame.mouse.get_pos()
, sous la forme d'un tuple (x , y)blank_surface.subsurface(position[0]-25,position[1]-25,50,50)
Exemple d'exercice d'appropriation : créer un script permettant cette fois-ci d'afficher en rouge une zone rectangulaire centrée sur la position du curseur de la souris de largeur 100 pixels et de hauteur 50 pixels.
La correction est ici .
Voici une copie d'écran obtenue dans chacun des cas.