On distingue 2 types d’opérations morphologiques de base : l’érosion et la dilatation qui sont 2 techniques duales (dans la mesure où elles se complètent).
Ces 2 opérations permettent d’améliorer la qualité informationnelle d’une image numérique.
L'Érosion
Il s’agit d’un processus qui permet de séparer des objets qui sont collés.

Cette opération permet de supprimer des extrusions (ou aspérités).
Voici un autre exemple, avec un objet circulaire. On constate que le cercle après érosion est plus affiné. Concrètement, l’opération a permis de nettoyer la forme :

Définition :
Soit X un ensemble et B un élément structurant, l’érosion de X par B est donnée par :
ϵB(X)=X⊖B={x∈image|Bx⊂X}
C'est-à-dire l’ensemble des points x de l'image, tels que B est totalement inclus dans X si B est centré en x.

Principe :
Partons d’un objet blanc sur fond noir et observons l’application de l’érosion sur cet exemple.
Ne perdons pas de vue que l’application de l’érosion sur un tel exemple avec l’élément structurant va réduire la taille de l’objet.
Algorithme :
Considérons 2 images :
Image d’entrée =
ImaIn
(il s’agit de l’image brute) ;Image de sortie =
ImaOut
(il s’agit de l’image résultat).
Algorithme de l’érosion dans le cas d’images binaires :
Entrée : ImaIn //Image à traiter
Sortie : ImaOut //Image traitée
// Principe de l'ÉROSION dans le cas d’images binaires
Début
Pour tous les points ImaIn(x,y) Faire
// calculer B ET (x,y) : le ET des voisins ;
Si B ET (x,y) Alors
ImaOut(x,y) = ImaIn(x,y);
Sinon
ImaOut(x,y) = 0;
FinSi
FinPour
Fin
La Dilatation
Il s'agit d'un processus qui permet de réparer des traits interrompus :

Cette opération permet aussi de combler les intrusions (ou trous) dans un objet :

Définition :
Soit X un ensemble et B un élément structurant, la dilatation de X par B est donnée par :
δB(X)=X⊕B={x∈image|Bx∩X≠∅}
C'est-à-dire l'ensemble des points x de l'image, tels que Bx a une intersection non vide avec X.
Remarque : autrement dit, la dilatation de X correspond donc à l'érosion du complémentaire de X.
Principe :
Partons d’un objet blanc sur fond noir et observons l’application de la dilatation sur cet exemple.
Ne perdons pas de vue que l’application de la dilatation sur un tel exemple avec l’élément structurant va agrandir la taille de l’objet.
Algorithme :
Entrée : ImaIn // Image à traiter
Sortie : ImaOut // Image traitée
// Principe de la DILATATION dans le cas d’images binaires
Début
Pour tous les points ImaIn(x,y) Faire
// calculer B OU (x,y) : le OU des voisins ;
Si B OU (x,y) Alors
ImaOut(x,y) = 1;
Sinon
ImaOut(x,y) = ImaIn(x,y);
FinSi
FinPour
Fin
Activité n° 3 - Érosion et dilatation
Le code suivant utilise l'image smiley_nb.png
que vous avez téléchargée dans le premier chapitre de cette partie.
Copiez-collez le chargement des modules nécessaires dans votre environnement Python :
#3_3 érosion et dilatation
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
Ensuite, nous allons définir un algorithme générique de convolution. Ce code permet de calculer la valeur de chaque pixel d'une nouvelle image via l'application d'une fonction prenant en paramètre l'image, les coordonnées du pixel à calculer et un filtre à appliquer à ce pixel-là.
Copiez-collez ce code afin de créer cette fonction :
def convolution (image,filtre,function):
new_image = np.zeros(image.shape,np.uint8)
for i in range(0,image.shape[0]):
for j in range(0,image.shape[1]):
new_image[i,j] = function(image,i,j,filtre)
return new_image
À quoi correspond la valeurimage.shape[0]
?
L'opération de dilatation correspond à une convolution particulière. Il nous faut donc coder la fonction correspondant à l'opération de dilatation sur un pixel donné. Comme indiqué auparavant, cette fonction revient à attribuer la valeur 1 à un pixel si au moins un pixel de son voisinage et son pixel correspondant dans l'élément structurant sont également égaux à 1.
Complétez le code suivant pour coder l'opérateur de dilatation sur un pixel :
def pixel_dilatation(image, ligne, colonne, elmt_structurant):
width = elmt_structurant.shape[0] // 2
height = elmt_structurant.shape[1] // 2
pixel_value = False;
for i in range(0,elmt_structurant.shape[0]):
for j in range(0,elmt_structurant.shape[1]):
x_image = ligne + i - width
y_image = colonne + j - height
if ((x_image >= 0) and (x_image < image.shape[0]) and
(y_image>=0) and (y_image<image.shape[1])):
if(... à compléter ...):
pixel_value = True
return pixel_value
Procédez de même pour l'érosion. Complétez la fonction pixel_erosion
:
def pixel_erosion(image, ligne, colonne, elmt_structurant):
width = elmt_structurant.shape[0] // 2
height = elmt_structurant.shape[1] // 2
pixel_value = True;
for i in range(0,elmt_structurant.shape[0]):
for j in range(0,elmt_structurant.shape[1]):
x_image = ligne + i - width
y_image = colonne + j - height
if((x_image >= 0) and (x_image < image.shape[0]) and
(y_image>=0) and (y_image<image.shape[1])):
if(... à compléter ...):
pixel_value = False
return pixel_value
Appliquez maintenant l'opérateur de dilatation et d'érosion sur l'image smiley_nb.png
image = cv.imread('smiley_nb.png',0)
plt.imshow(image,cmap='gray')
plt.show()
kernel_cross = cv.getStructuringElement(cv.MORPH_CROSS,(5,5))
plt.figure()
plt.imshow(erosion(image,kernel_cross),cmap='gray')
plt.title("Erosion")
plt.show()
plt.figure()
plt.imshow(dilatation(image,kernel_cross),cmap='gray')
plt.title("Dilatation")
plt.show()
Voici les images que vous devriez voir apparaître.
Après érosion :

Après dilatation :

Proposez un autre élément structurant afin de faire disparaître les yeux et la bouche après l'opération de dilatation.
Réponses aux activités
Activité n° 3 - Érosion et dilatation
À quoi correspond la valeur image.shape[0]
?
Réponse : la valeur correspond au nombre de lignes de l'image.
Complétez le code suivant pour coder l'opérateur de dilatation sur un pixel :
Réponse :
def pixel_dilatation(image, ligne, colonne, elmt_structurant):
width = elmt_structurant.shape[0] // 2
height = elmt_structurant.shape[1] // 2
pixel_value = False;
for i in range(0,elmt_structurant.shape[0]):
for j in range(0,elmt_structurant.shape[1]):
x_image = ligne + i - width
y_image = colonne + j - height
if ((x_image >= 0) and (x_image < image.shape[0]) and
(y_image>=0) and (y_image<image.shape[1])):
if(image[x_image,y_image] and elmt_structurant[i,j]):
pixel_value = True
return pixel_value
La fonction de dilatation consiste ensuite à appliquer le filtre de convolution avec cette nouvelle fonction et un élément structurant.
def dilatation(image, elmt_structurant):
return convolution(image,elmt_structurant,pixel_dilatation)
Procédez de même pour l'érosion. Complétez la fonctionpixel_erosion
:
Réponse :
def pixel_erosion(image, ligne, colonne, elmt_structurant):
width = elmt_structurant.shape[0] // 2
height = elmt_structurant.shape[1] // 2
pixel_value = True;
for i in range(0,elmt_structurant.shape[0]):
for j in range(0,elmt_structurant.shape[1]):
x_image = ligne + i - width
y_image = colonne + j - height
if((x_image >= 0) and (x_image < image.shape[0]) and (y_image>=0) and (y_image<image.shape[1])):
if (elmt_structurant[i,j] and not(image[x_image,y_image])):
pixel_value = False
return pixel_value
Proposez un autre élément structurant afin de faire disparaître les yeux et la bouche après l'opération de dilatation.
Réponse : cv.MORPH_RECT,(6,6))