Niveau
Débutant
Env.
Local (Windows), Local (Linux), Google Colab
Code
Python
Libs
skimage, matplotlib
Sources

Traitement d’images (partie 4: Transformations)

Nous avons vu d’une part que les images sont en réalité des matrices a 2 (noir et blanc) ou 3 dimensions (couleurs), nous avons alors vu comment les analyser rapidement grâce aux histogrammes, puis nous avons utilisé ces connaissances pour effectuer des opérations de seuillages sur les images. Nous allons voir dans cet article comment effectuer quelques transformations de bases sur des images avec scikit-image comme la rotation, et changement d’échelle et de taille d’image.

Cet article très simple nous amènera ensuite aux filtres d’images, puis par extension vers les réseaux de neurones à convolution (parties 5 et 6).

Rotation

Avant de voir comment effectuer une rotation d’image simplement avec scikit-image. je vous invite à aller sur le site de skimage pour regarder toutes les transformations d’images que la bibliothèque propose. Il y en a un grand nombre et on n’en verra que certaines dans cet article bien sur. Commençons donc par la rotation.

Avant tout importons les bonnes librairies Python:

import matplotlib.pyplot as plt
from skimage.io import imread, imshow
from skimage import exposure, transform
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import math

Ensuite créons un image ultra-simple (4 x 4) composées de pixels noir ou blanc, et affichons la avec la méthode imshow. Nous pourrions utiliser n’importe quel type d’image bien sur mais je trouve qu’un exemple très simple est plus parlant, surtout quand on montre les matrices résultat.

image_test = np.array([[1,0,0,0], [0,1,0,0], [0,1,1,0], [0,0,0,1]])
imshow(image_test, cmap=plt.get_cmap('gray'))

Un simple appel à la fonction transform.rotate() permet donc d’effectuer cette rotation sur l’angle voulu (ci-dessous 90°)

rotated = transform.rotate(image_test, angle=90, preserve_range=True)
print(rotated)
array([[0, 0, 0, 1],
       [0, 0, 1, 0],
       [0, 1, 1, 0],
       [0, 0, 0, 0]], dtype=int32)

Notez le paramètre preserve_range qui permet de garder la même normalisation de nombre dans la matrice/image.

Visualisons le résultat :

_, axes = plt.subplots(ncols=2)
axes[0].imshow(image_test, cmap=plt.get_cmap('gray'))
axes[1].imshow(rotated, cmap=plt.get_cmap('gray'))

Changement de taille

Changer la taille d’une image est bien sur une opération courante. Imaginons que l’on veuille augmenter la taille de notre image de 4×4 à 6×6. Nous utiliserons pour cela la fonction transform.resize() en lui passant en paramètre le tuple (6,6)

resized_img = transform.resize(image=image_test, output_shape=(6,6), preserve_range=True)

Regardons l’image résultante :

print(resized_img)
array([[0.72222222, 0.5       , 0.13888889, 0.02777778, 0.        , 0.        ],
       [0.5       , 0.5       , 0.41666667, 0.08333333, 0.        , 0.        ],
       [0.16666667, 0.5       , 0.86111111, 0.30555556, 0.08333333, 0.02777778],
       [0.16666667, 0.5       , 0.97222222, 0.86111111, 0.41666667, 0.13888889],
       [0.08333333, 0.25      , 0.5       , 0.5       , 0.5       , 0.5       ],
       [0.02777778, 0.08333333, 0.16666667, 0.16666667, 0.5       , 0.72222222]])

Si on explore de plus près ses dimensions, on a bien une image 6×6.

resized_img.shape
(6, 6)

Vous avez sans doute remarqué que nous avons dorénavant des nombres décimaux dans la matrice (donc des niveaux de gris). Celà est en fait dû à l’agrandissement. Repassons en pur noir et blanc pour avoir notre véritable agrandissement. Pour celà nous allons convertir les valeurs > 0,5 en 1 et les autres en zéro:

intresized = resized_img > 0.5
imshow(intresized.astype('int32'), cmap=plt.get_cmap('gray'))

On voit mieux maintenant notre étirement d’image avec la forme du milieu et celle du haut à gauche.

Changement d’échelle

Pour changer le grossissement d’une image on pourra utiliser transform.rescale(). Ci-dessous nous utilisons un ratio de 1/2:

image_rescaled = transform.rescale(image=image_test, scale=1.0 / 2.0, anti_aliasing=False, preserve_range=True)
_, axes = plt.subplots(ncols=2)
axes[0].imshow(image_test, cmap=plt.get_cmap('gray'))
axes[1].imshow(image_rescaled, cmap=plt.get_cmap('gray'))

Transformations euclidiennes

La librairie scikit-image permet d’effectuer vraiment un grand nombre de transformations sur des images. Je trouve la transformation SimilarityTransform() particulièrement utile car elle permet de combiner des transformations euclidiennes (translations) avec du changement d’echelle.

Prenons une image normale cette fois-ci, l’image n’est pas droite et nous allons la redresser, puis la décaler directement avec cette fonction

image = imread('book.jpg')
imshow(image)
tr = transform.SimilarityTransform(scale=1.5, rotation=math.pi/20, translation=(-40, -250))
plt.figure(figsize=(8, 5))
image_tr_1 = transform.warp(image, tr)
plt.imshow(image_tr_1)

En fait la rotation de l’image créé un décalage que nous corrigeons avec le parametre translation ci-dessus.

Voici qui cloture cet article sur les transformations de bases d’image. Nous allons dans les prochains articles aborder les filtres et notament ceux de convolution qui nous permettrons de mieux comprendre comment les réseaux de neurones dit convolutifs sont devenus aussi omniprésents dans le monde du traitement de l’image.

Partager cet article

8 Replies to “Traitement d’images (partie 4: Transformations)”

  1. Bonjour,
    Cette série d’article est très intéressante. Par contre incluez vous la dilation et l’érosion dans les transformations de base, car je pense que cela ne fait pas partie des filtre. Ce sont néanmoins des opérations très utiles.

    1. Bonjour,
      Vous avez raison d’une certaine manière. Mais à vrai dire, dilatation et érosion sont considérés comme des filtres non linéaires (cf. transformations morphologiques) bref si on est puriste on mettra ces transformations plutot dans les filtres. Ça sera chose faite dans le prochain article de la série.
      Benoit

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.