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 pygamefrom pygame.locals import *# Initialisation de la fenêtre d'affichagepygame.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 videblank_surface = pygame.Surface((870, 522))# Lecture et remplacement de la couleur de chaque pixelfor 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 fondfenetre.blit(blank_surface,(0,0))pygame.display.flip()# Boucle principalecontinuer = 1while 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 pygamefrom pygame.locals import *# Initialisation de la fenêtre d'affichagepygame.init()fenetre = pygame.display.set_mode((870,522))pygame.display.set_caption("La Vie de Marc Chagall")# Traitement de l'imagefond = pygame.image.load("lavie.jpg").convert()# Création d'une image videblank_surface = pygame.Surface((870, 522))# Lecture et remplacement de la couleur de chaque pixelfor 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 fondfenetre.blit(blank_surface,(0,0))pygame.display.flip()# Boucle principalecontinuer = 1while 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 pygamefrom pygame.locals import *# Initialisation de la fenêtre d'affichagepygame.init()fenetre = pygame.display.set_mode((870,522))pygame.display.set_caption("La Vie de Marc Chagall")# Traitement de l'imagefond = pygame.image.load("lavie.jpg").convert()# Création d'une image videblank_surface = pygame.Surface((870,522))# Lecture et remplacement de la couleur de chaque pixelfor 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 principalecontinuer = 1while 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.