Géométrie Discrète (Master GIG) - TP n° 7

Exercices sur les opérateurs de base de la morphologie mathématique avec Astico2D

Nous continuerons à utiliser Astico2D pour les exercices de TP. Les consignes restent les mêmes :

Opérateurs de base

Vous commencerez par implanter l'érosion et la dilatation.

Exercice 1

Définissez un struct appelé ES pour l'élément structurant.

Votre structure de données doit être assez flexible pour pouvoir représenter différents éléments structurants, symétriques ou non. Vous avez le choix entre encoder l'élément structurant comme un ensemble (avec une liste de points) ou un masque (avec un tableau bidimensionnel).

Définissez au moins deux éléments structurants, comme le carré 3×3 et le diamant 3×3.

Exercice 2

Faites une fonction void erosion(cv::Mat &img_niv, ES &es) qui applique une érosion à une image binaire avec un élément structurant.

Faites attention quand l'élément structurant sort du domaine de l'image. Nous supposons que les pixels en dehors du domaine sont tous noirs (zéro).

Déclenchez cette fonction avec la touche 1. Vous pouvez définir l'élément structurant utilisé en dur dans votre code, ou utiliser une touche pour parcourir les différents éléments structurants que vous avez défini dans l'exercice 1.

Quand nous effectuons plusieurs érosions sur une image, ça revient à faire une seule érosion avec un élément structurant plus grand. Il existe une formule pour connaître cet élément structurant : \( (A \ominus B) \ominus B = A \ominus (B \oplus B) \)

Exercice 3

Ajoutez un slider pour choisir le nombre de fois qu'on effectue l'érosion :

  1. Déclarez une variable repetitions dans votre classe MyApp et donne-la la valeur par défaut 1.
  2. Appelez la fonction creer_slide dans le constructeur :
    MonApp (int argc, char **argv) : Astico2D (argc, argv)
    {
      if (!init_ok) return;  // erreur dans l'initialisation
      creer_slider ("Répétitions", &repetitions, 50);
    }

Maintenant, renommez votre fonction qui fait l'érosion une_erosion et faites une nouvelle fonction erosion qui effectue le nombre d'itérations défini par le slider.

Passons maintenant à la dilatation, ce qui devrait être facile maintenant.

Exercice 4

Faites une fonction void dilatation(cv::Mat &img_niv, ES &es) qui applique une dilatation à une image avec un élément structurant.

Vous pouvez utiliser la définition vue en cours ou utiliser la dualité avec l'érosion. Si vous choisissez cette deuxième option, fait attention à la valeur des pixels à l'extérieur du domaine de l'image

Déclenchez cette fonction avec la touche 2.

Ensuite, généralisez votre code comme dans l'exercice 3 pour faire plusieurs dilatations.

Exercice 5

Faites une fonction void ouverture(cv::Mat &img_niv, ES &es) qui applique une ouverture à une image avec un élément structurant. Déclenchez cette fonction avec la touche 3.

Faites de même pour la fermeture.

Nous avons maintenant les outils nécessaires pour corriger une image.

Exercice 6

Faites une fonction void debruiter(cv::Mat &img_niv, ES &es) qui combine des ouvertures et des fermetures pour débruiter cette image :

Image à débruiter

Fixez dans le code le nombre de répétitions à faire.

Déclenchez cette fonction avec la touche 5.

Avec l'exercice précédent vous vous êtes sans doute posé des questions sur la différence entre faire une ouverture et puis une fermeture ou le contraire.

Exercice 7

Quelle est la relation entre \( (A \circ B) \bullet B \) (ouverture, puis fermeture) et \( (A \bullet B) \circ B \) (fermeture, puis ouverture) ?

Implantez les deux opérations et comparez les résultats pour voir s'il existe une relation (inclusion, égalité) ou pas entre les deux.

Squelette et reconstruction

Vous allez implanter l'algorithme de squelettisation vu en cours.

Notez qu'on peut associer à chaque pixel du squelette le numéro de l'itération dans laquelle il a été trouvé. Ce sera utile pour la deuxième partie.

Exercice 8

Faites une fonction void squelette(cv::Mat &img_niv, ES &es) qui calcule le squelette d'une image avec un élément structurant.

Une propriété remarquable de cet algorithme de squelettisation est qu'il est réversible : on peut reconstruire l'objet initial à partir du squelette. Soit \[ \sigma(A) = \cup_{k \geq 0} \left( \varepsilon_B^k(A) - \varepsilon_B^k(A) \circ B \right) = \cup_{k \geq 0} S_k \] alors \[ A = \cup_{k \geq 0} \delta_B^k(S_k) \]

Exercice 9

Faites une fonction void reconstruction(cv::Mat &img_niv, ES &es) qui prend le squelette calculé par la fonction squelette de l'exercice 8 et reconstruit l'objet initial.

Affichez l'objet reconstruit et vérifiez qu'il coïncide avec l'objet initial.