Ci-dessous, les différences entre deux révisions de la page.
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 ====== | + | ====== |
[[: | [[: | ||
Ligne 9: | Ligne 9: | ||
===== Création de l' | ===== Création de l' | ||
- | Commencez par choisir l' | + | Commencez par choisir l' |
+ | Si possible, choisissez une zone de l' | ||
* [[http:// | * [[http:// | ||
* [[http:// | * [[http:// | ||
Ligne 37: | Ligne 38: | ||
[[stu: | [[stu: | ||
- | Il existe plusieurs façons de procéder, chacune ayant ses avantages et ses inconvénients. | + | Il existe plusieurs façons de procéder, chacune ayant ses avantages et ses inconvénients. |
- | ce TP, nous conseillons d' | + | Nous conseillons |
- | + | dans le document cité plus haut. | |
- | L' | + | |
- | + | ||
- | Voici un programme de départ utilisant '' | + | |
- | '' | + | |
- | + | ||
- | <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' | + | |
- | 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 | + | |
- | img2 = pouet(gimg) # Calculer l' | + | |
- | gwin.setImage(img2) # L' | + | |
- | return False | + | |
- | + | ||
- | gwin = Visu() # Création de la fenêtre | + | |
- | gimg = imageio.imread(" | + | |
- | gimg = gimg[:,:,: | + | |
- | gwin.setImage(gimg) # Affiche l' | + | |
- | gwin.register(" | + | |
- | # Pas nécessaire depuis un shell interactif comme IEP (pyzo), mais | + | |
- | # il faut le mettre dans une appli indépendante. | + | |
- | # gwin.run() | + | |
- | </ | + | |
- | + | ||
- | Le parti pris, dans l' | + | |
- | L' | + | |
- | + | ||
- | <WRAP tip> | + | |
- | Vous pouvez réfléchir à un moyen de lever ces limitations. | + | |
- | </ | + | |
- | + | ||
- | <WRAP tip> | + | |
- | S'il y a des choses que vous ne comprenez pas dans l' | + | |
- | </ | + | |
===== D' | ===== D' | ||
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' | ||
</ | </ | ||
Ligne 100: | Ligne 58: | ||
</ | </ | ||
- | | {{img.png}} | | | + | /* |
- | | **Image de départ** : La belle princesse (attribuée à Léonard | + | {{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 | ||
| {{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 | + | |
| {{img_quantize.png}} | {{img_floue.png}} | | | {{img_quantize.png}} | {{img_floue.png}} | | ||
- | | Image «quantifiée», | + | | Image «quantifiée», |
- | | {{img_flip.png}} |{{img_sobel.png}} | | + | | {{img_flip.png}} |{{img_contours.png}} | |
- | | Miroir vertical | Détection de contour (ici : [[wpfr> | + | | Miroir vertical |
- | + | | {{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 (ici, version réversible) (3)| |
- | Dans le cas de la **détection de contours**, vous n' | + | | {{img_mosaique.png}} | {{img_coule.png}} | |
- | Mais dans tous les cas, vous devez **expliquer** la méthode que vous aurez employée. | + | | Mosaïque (5x5) (2)| Vincent a renversé du solvant...| |
- | </ | + | |
<WRAP exo> | <WRAP exo> | ||
Ligne 122: | Ligne 89: | ||
</ | </ | ||
- | ===== Idées | + | ===== Espace |
- | ** Ce travail n' | + | |
+ | |||
+ | Il existe plusieurs [[https:// | ||
+ | |||
+ | | ||
+ | | ||
+ | en degrés dont la valeur est comprise entre 0 et 360 et représente la teinte, //Value// et // | ||
+ | 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 // | ||
+ | |||
+ | 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, | ||
+ | |||
+ | 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' | ||
+ | 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 = 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/ | ||
+ | * $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, | ||
+ | |||
+ | |||
+ | ==== Travail à faire ==== | ||
+ | |||
+ | Écrivez une fonction qui prend une image et un angle en paramètres et fait tourner toutes les teintes de l' | ||
+ | |||
- | | {{img_mosaique.png}} | | | ||
- | | Mosaïque (5x5) | | | ||