Outils pour utilisateurs

Outils du site


tp:python:transforme_images

Warning: Trying to access array offset on false in /home/signac/doku/inc/html.php on line 1164

Warning: Trying to access array offset on false in /home/signac/doku/inc/html.php on line 1168

Warning: Trying to access array offset on false in /home/signac/doku/inc/html.php on line 1171

Warning: Trying to access array offset on false in /home/signac/doku/inc/html.php on line 1172

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
tp:python:transforme_images [2015/01/13 08:21]
lsignac [D'autres transformations d'images]
tp:python:transforme_images [2021/05/04 15:12] (Version actuelle)
Ligne 1: Ligne 1:
-====== Transformer des images ======+====== 📓 Transformer des images ======
 [[:sol:transforme_image|Solution]] [[:sol:transforme_image|Solution]]
  
Ligne 9: Ligne 9:
  
 ===== Création de l'image de départ ===== ===== Création de l'image de départ =====
-Commencez par choisir l'image sur laquelle vous allez travailler parmi celle qui sont proposées en lien ici :+Commencez par choisir l'image sur laquelle vous allez travailler parmi celle qui sont proposées en lien ici
 +Si possible, choisissez une zone de l'image où on distingue au moins 2 composantes.
   * [[http://commons.wikimedia.org/wiki/File:Van_Eyck_-_Arnolfini_Portrait.jpg#|Les époux Arnolfini (J. van Eyck)]]   * [[http://commons.wikimedia.org/wiki/File:Van_Eyck_-_Arnolfini_Portrait.jpg#|Les époux Arnolfini (J. van Eyck)]]
   * [[http://commons.wikimedia.org/wiki/File:Hans_Holbein_the_Younger_-_The_Ambassadors_-_Google_Art_Project.jpg | Les Ambassadeurs (H. Holbein) ]]   * [[http://commons.wikimedia.org/wiki/File:Hans_Holbein_the_Younger_-_The_Ambassadors_-_Google_Art_Project.jpg | Les Ambassadeurs (H. Holbein) ]]
Ligne 37: Ligne 38:
 [[stu:python_gui:tuto_images|Travailler avec des images en Python]]. [[stu:python_gui:tuto_images|Travailler avec des images en Python]].
  
-Il existe plusieurs façons de procéder, chacune ayant ses avantages et ses inconvénients. Dans +Il existe plusieurs façons de procéder, chacune ayant ses avantages et ses inconvénients.  
-ce TP, nous conseillons d'utiliser le module ''imageio''pour charger les images et ''ImageWindow'' pour les afficher et faire une petite interface graphique. +Nous conseillons ici d'utiliser PIL et matplotlib pour charger et afficher les images. La méthode est détaillée 
- +dans le document cité plus haut.
-L'utilisation de ''Pillow'' pour charger les images, ''matplotlib'' pour les afficher est aussi envisageable (mais déconseillée pour ce TP). +
- +
-Voici un programme de départ utilisant ''imageio'' et ''ImageWindow''. Il charge l'image nommée +
-''img.png'' et attend. Lorsque vous appuyez sur la touche Espace, un point rouge apparaît au centre de l'image. +
- +
-<file python login_image.py> +
-from ImageWindow import Visu +
-import imageio +
-  +
-def pouet(img): +
-    mx, my = img.shape[1] // 2, img.shape[0] // 2 +
-    # On fait une copie de l'image +
-    img2 = img.copy() +
-    # On ajouter le point rouge +
-    img2[my, mx] = (255, 0, 0) +
-    return img2 +
-     +
-def clavier(t): +
-    if t == ' ': # Si la touche appuyée est espace +
-        img2 = pouet(gimg) # Calculer l'image avec point rouge +
-        gwin.setImage(img2) # L'afficher dans la fenêtre +
-    return False +
-  +
-gwin = Visu() # Création de la fenêtre +
-gimg = imageio.imread("img.png") # Chargement d'une image avec imageio +
-gimg = gimg[:,:,:3] # On enlève l'éventuel canal alpha +
-gwin.setImage(gimg) # Affiche l'image chargée dans la fenêtre +
-gwin.register("keyboard",clavier) # Appelle la fonction 'clavier' si on appuie sur une touche +
-# Pas nécessaire depuis un shell interactif comme IEP (pyzo), mais +
-# il faut le mettre dans une appli indépendante. +
-#  gwin.run() +
-</file> +
- +
-Le parti pris, dans l'exemple qui précède est de ne pas modifier l'image d'origine, mais de créer une nouvelle image.  +
-L'avantage est qu'on peut alors tester plusieurs transformations toujours à partir de l'image d'origine. L'inconvénient est qu'on ne peut pas appliquer plusieurs transformations à la fois. +
- +
-<WRAP tip> +
-Vous pouvez réfléchir à un moyen de lever ces limitations. +
-</WRAP> +
- +
-<WRAP tip> +
-S'il y a des choses que vous ne comprenez pas dans l'exemple qui précède, n'hésitez pas à demander. +
-</WRAP> +
  
 =====  D'autres transformations d'images ===== =====  D'autres transformations d'images =====
Ligne 93: Ligne 50:
 <WRAP important> <WRAP important>
 Votre programme doit comporter une fonction différente pour chaque transformation mentionnée ci-dessous. Votre programme doit comporter une fonction différente pour chaque transformation mentionnée ci-dessous.
 +Chaque fonction doit prendre une image en paramètres (plus d'autres paramètres si vous en avez besoin) et renvoyer une image.
 </WRAP> </WRAP>
  
Ligne 100: Ligne 58:
 </WRAP> </WRAP>
  
-| {{img.png}} | | +/* 
-| **Image de départ** : La belle princesse (attribuée à Léonard de Vinci) ||+{{img_sombre.png}} Image assombrie, chaque composante est divisée par 4 (1)  
 +{{img_binaire.png}} Version monochrome (2 couleurs) (1) 
 +{{img_reverse.png}} Image en négatif (inverse vidéo) (1) 
 +*/ 
 +  
 +Par ordre de difficulté : 
 +  * niveaux de gris, couleurs cyclées, miroir vertical,  
 +  * image quantifiée (sur les couleurs), pop art 
 +  * photomaton, floutage, mosaïque 
 +  * solvant renversé 
 +  * détection de contours 
 +  *  
 +| {{arles.png}} | | 
 +| **Image de départ** : La chambre de van Gogh à Arles (v.2 ;-) ) ||
 | {{img_gris.png}} | {{img_cycle.png}}|  | {{img_gris.png}} | {{img_cycle.png}}| 
-| Image en niveaux de gris | Couleurs cyclées  +| Image en niveaux de gris (1) | Couleurs cyclées : un pixel bleu deviendra rouge, un pixel rouge deviendra vert et un pixel vert deviendra bleu) (1) |
-: un pixel bleu deviendra rouge, un pixel rouge deviendra vert et un pixel vert deviendra bleu) +
-| {{img_sombre.png}} | {{img_reverse.png}}| +
-|Image assombrie, chaque composante est divisée par 4  | Image en négatif (inverse vidéo)|+
 | {{img_quantize.png}} | {{img_floue.png}} | | {{img_quantize.png}} | {{img_floue.png}} |
-| Image «quantifiée», chaque composante ne peut prendre que 8 valeurs différentes, régulièrement réparties| Image floue, chaque point est obtenue en faisant la moyenne des valeurs de pixels dans un carré 5x5 centré en i,j | +| Image «quantifiée», chaque composante ne peut prendre que 8 valeurs différentes, régulièrement réparties (2) | Image floue, chaque point est obtenue en faisant la moyenne des valeurs de pixels dans un carré 5x5 centré en i,j (3) 
-| {{img_flip.png}} |{{img_sobel.png}} | +| {{img_flip.png}} |{{img_contours.png}} | 
-| Miroir vertical | Détection de contour (ici : [[wpfr>Filtre_de_Sobel]])| +| Miroir vertical (1) | Détection de contour (4)| 
- +| {{img_popart.png}} |{{img_photomaton.png}} | 
-<WRAP exo> +| Version Pop-art (le rouge devient plus rouge, le bleu plus bleu et le vert plus vert...) (2) | Transformée du photomaton (iciversion réversible) (3)| 
-Dans le cas de la **détection de contours**vous n'êtes pas obligés de programmer le filtre de Sobel. +| {{img_mosaique.png}} | {{img_coule.png}} | 
-Mais dans tous les casvous devez **expliquer** la méthode que vous aurez employée+|  Mosaïque (5x5) (2)| Vincent a renversé du solvant...|
-</WRAP>+
  
 <WRAP exo> <WRAP exo>
Ligne 122: Ligne 89:
 </WRAP> </WRAP>
  
-===== Idées de transformations ===== +===== Espace de couleurs ===== 
-** Ce travail n'est pas à faire (non noté 8-) )**+ 
 + 
 +Il existe plusieurs [[https://fr.wikipedia.org/wiki/Espace_de_couleur|espaces de couleur]] pour représenter les couleurs des images. 
 + 
 +  le modèle RGB est un triplet de trois valeurs numériques, //Red//, //Green// et //Blue//, comprises entre 0 et 1 (ou 0 à 255 dans les exemples que nous avons vu précédemment). 
 +  le modèle HSV est un triplet de trois valeurs : //Hue// qui est un angle 
 +en degrés dont la valeur est comprise entre 0 et 360 et représente la teinte, //Value// et //Saturation// 
 +sont des valeurs numériques comprises entre 0 et 1 et représentent respectivement la brillance (0 pour //Value// donne du noir) et l'intensité (lorsque //Saturation// diminue, la couleur devient fade) 
 + 
 +Un des intérêts du modèle HSV est qu'il correspond mieux à une perception humaine des couleurs. De plus, une seule valeur correspond à la teinte, et il est donc facile de traverser tout le spectre des couleurs en faisant varier un seul paramètre : //Hue//. 
 + 
 +Nous allons créer une fonction qui transforme une teinte en une autre, dans une image, en opérant une translation de toutes les valeurs de teintes. Il suffira pour cela de décaler toutes les valeurs de *Hue* d'un certain nombre de degrés. Par exemple, ajouter 120 à la teinte fera passer le jaune (60°) au cyan (180°). Naturellement, les autres couleurs seront modifiées aussi. 
 + 
 +Pour réaliser cela, nous allons devoir, pour chaque couleur RGB d'une image, la transformer en HSV, opérer le décalage, puis retransformer en RGB pour stocker la nouvelle couleur. 
 + 
 +Les outils à avoir à notre disposition sont donc une fonction qui passe de l'espace de couleurs RGB à HSV, et une autre fonction qui fait le contraire. Les formules permettant de passer d'un espace à un autre sont données ici : [[https://fr.wikipedia.org/wiki/Teinte_Saturation_Valeur#Transformation_entre_TSV_et_RVB|Transformation entre TSV et RVB]]. 
 +Nous les redonnons ci-dessous. 
 + 
 +==== RGB vers HSV ==== 
 + 
 +Soient $M=\max(R, G, B)$ et $m = \min(R, G, B)$. 
 +Si $M=m$, on prend $H = 0$. Sinon : 
 + 
 +  si $M = R$, $H = 60\times (G - B) / (M - m) \bmod 360$ 
 +  si $M = G$, $H = 60\times (B - R) / (M - m) + 120$ 
 +  * si $M = B$, $H = 60\times (R - G) / (M - m) + 240$ 
 + 
 +On obtient ainsi une valeur de $H$ entre 0 et 360. 
 +Puis on prend $V = M / 255$ (pour avoir une valeur entre 0 et 1 si les composantes RGB sont des entiers sur un octet) 
 +Et enfin, $S=(M-m)/M$ si $M$ est non nul et $S=0$ sinon. 
 + 
 +==== HSV vers RGB ==== 
 + 
 +Ce qui suit est valable pour H dans $[0, 360[$. 
 +On calcule en premier le sextant contenant la teinte, et la position dans le sextant : 
 + 
 +  * $a = \lfloor H/60\rfloor$ : sextant 
 +  * $f = H/60 - a$ : position dans le sextant 
 + 
 +puis : 
 + 
 +  * $l = V\times (1 - S)$ 
 +  * $m = V\times (1 - f\times S)$ 
 +  * $n = V \times (1 - (1 - f)\times S)$ 
 + 
 +Les 3 valeurs RGB (ici entre 0 et 1, il faudra les multiplier pour obtenir un entier stockable sur un octet) sont lors données par le tableau suivant : 
 + 
 +| $a$ |  0 |  1 |  2 |  3 |  4 |   5 | 
 +| R,G,B    |$V,n,l$|$m,V,l$|$l,V,n$|$l,m,V$|$n,l,V$|$V,l,m$| 
 + 
 + 
 +==== Travail à faire ==== 
 + 
 +Écrivez une fonction qui prend une image et un angle en paramètres et fait tourner toutes les teintes de l'image de l'angle en question. 
 + 
  
-| {{img_mosaique.png}} | | 
-| Mosaïque (5x5) | | 
  
tp/python/transforme_images.1421137304.txt.gz · Dernière modification: 2015/01/13 08:21 de lsignac