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

Traitement d’images (partie 2: Les histogrammes)

Un histogramme … pourquoi ?

Dans l’article précédent nous avons vu comment étaient composées nos images numériques. Ceci nous amène naturellement à aborder les histogrammes d’images. Bien sur on ne travaille pas une image comme on travaille du texte. Les images étant donc des matrices (comme des cartes de pixels finalement) nous allons les manipuler de manière ensembliste. Le premier axe de travail (et donc de retouche) est la colorimétrie.

Nous allons donc voir dans cet article comment analyser ces composantes de couleurs à travers d’histogrammes.

Chaque pixel étant donc un tuple ou plutôt une superposition de canaux de couleurs (Rouge, Vert et Bleu, soit [R, G, B]), nous allons devoir analyser cette répartition des trois couleurs primaires dans notre image.

Note : Nous allons rester sur des images codées en 24 bits (soit 2 puissance 8 = 256 valeurs possibles par canal).

Un histogramme d’image n’est ni plus ni moins qu’un graphique qui affiche :

  • En abscisse (Val. dans le graphe ci-dessous) les différentes valeurs de canaux/pixel
  • En ordonnée (Nb Pixel) le nombre de canaux/pixel qui possèdent cette valeur

Dans le graphe exemple ci-dessus, on a 2000 fois un pixel de valeur 100.

Vous remarquerez que je n’ai mis qu’une seule courbe. Cela signifie tout simplement que nous sommes en train de visualiser une image en niveau de gris, mais nous allons voir celà dans le paragraphe suivant.

Couleurs, Niveau de gris et Noir & Blanc

Comment distinguer alors une image en couleur d’une image en niveau de gris d’une image en noir et blanc sans regarder l’image ? Et bien c’est très simple avec les histogrammes d’images:

Une image en noir et Blanc a un histogramme très basique (binaire) qui ne comporte que des valeurs O ou 1 (pas de nuances sur 24 bits par exemple) :

Dans ce graphe (oubliez la droite svp 😉 ), on n’a de valeurs que pour 0 et 1.

Une image en niveau de gris ne possède qu’une seule courbe (celle des nuances de gris):

Si on a une image en couleur il nous faut maintenant avoir les nuances sur les trois canaux (Rouge, Vert et Bleu). On a donc 3 courbes :

Comment créer ces histogrammes avec Python ?

Avec Python il existe au moins 3 façons de créer des histogrammes d’images :

  • Directement en utilisant la librairie Numpy et matplotlib (et oui n’oubliez pas que nos images ne sont que des matrices)
  • Avec Scikit-Image
  • En utilisant OpenCV (Recommandé car beaucoup plus rapide)

Avant de commencer il faut ouvrir (voire convertir nos images) :

Ouverture des images

Importez tout d’abord les librairies Python, comme suit :

import matplotlib.pyplot as plt
from skimage.io import imread, imshow
from skimage import exposure
import matplotlib.pyplot as plt
from skimage.color import rgb2gray
import numpy as np

Ensuite il suffit de lire l’image avec la fonction imread() de skimage :

image1 = imread('railway.jpg') #, as_gray=True)

Pour lire l’image directement en niveau de gris (avec la conversion couleur -> niveau de gris) soit vous utilisez l’option as_gray=True comme suit :

image1_Gray = imread('railway.jpg', as_gray=True)

Soit vous utiliser la fonction rgb2gray() après avoir lu l’image en couleur :

image1_Gray = rgb2gray(image1)

Vous pouvez afficher l’image tout simplement avec la fonction imshow() :

imshow(image1)

Si vous voulez convertir l’image en noir et blanc, rien de plus simple. Utilisez la méthode de Numpy where qui permet de remplacer les éléments d’une matrice sous une condition. Dans l’exemple ci-dessous je remplace en 0 tous les éléments inférieurs à 128 et 1 tous les autres :

im = np.where(image1_Gray>128/256, 0, 1)
imshow(im, cmap=plt.get_cmap('gray'))

Histogrammes avec scikit-image

Avec scikit-image nous utiliserons simplement la fonction histogram pour tracer ces graphes :

def imageHist(image):
    _, axis = plt.subplots(ncols=2, figsize=(12, 3))
    if (image.ndim == 2):
        # Grascale Image
        axis[0].imshow(image, cmap=plt.get_cmap('gray'))
        axis[1].set_title('Histogram')
        axis[0].set_title('Grayscale Image')
        hist = exposure.histogram(image)
        axis[1].plot(hist[0])
    else:
        # Color image
        axis[0].imshow(image, cmap='gray')
        axis[1].set_title('Histogram')
        axis[0].set_title('Colored Image')
        rgbcolors = ['red', 'green', 'blue']
        for i, mycolor in enumerate(rgbcolors):
            axis[1].plot(exposure.histogram(image[...,i])[0], color=mycolor)

Dans le code ci-dessus vous remarquerez que je regarde en premier lieu le nombre de dimensions de la matrice image. Si on a 3 dimensions c’est que l’on a une image avec couleur sinon on est en niveau de gris. Dans le cas où l’on a une image avec couleur on doit empiler les canaux et donc nous aurons 3 courbes comme suit :

Histogrammes avec OpenCV

Avec OpenCV c’est tout aussi simple et c’est en plus beaucoup plus rapide en temps de traitement. Voici comment visualiser l’histogramme d’une image couleur :

def histogramOpenCV(_img):
    _, axis = plt.subplots(ncols=2, figsize=(12, 3))
    axis[0].imshow(_img)
    axis[1].set_title('Histogram')
    axis[0].set_title('Image')
    rgbcolors = ['red', 'green', 'blue']
    for i,col in enumerate(color):
        histr = cv.calcHist([_img],[i],None,[256],[0,256])
        axis[1].plot(histr,color = col)

Voila nous avons vu comment analyser une image avec des histogrammes. Nous verrons dans le prochain article de la série ‘Traitement d’images » à quoi servent ces histogrammes et nous les utiliserons pour effectuer quelques techniques de base de retouche d’image.

Partager cet article

10 Replies to “Traitement d’images (partie 2: Les histogrammes)”

  1. Bonjour,
    Merci pour ce tuto très détaillé et complet.
    Je l’ai essayé mais l’affichage de l’image (après imshow) ne se produisait pas.
    Il semblerait qu’il manque l’instruction plt.show() à la fin.
    Merci encore

  2. Je viens de tester ce code:

    import matplotlib.pyplot as plt
    from skimage.io import imread, imshow
    from skimage import exposure
    import matplotlib.pyplot as plt
    from skimage.color import rgb2gray
    import numpy as np
    image1 = imread(‘railway.jpg’) #, as_gray=True)
    image1_Gray = imread(‘railway.jpg’, as_gray=True)
    imshow(image1)
    plt.show()

    Il manque effectivement plt.show() sinon rien ne s’affiche

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.