1. Seuillage de la norme d'un gradient

<< | Liste des exercices | Détection des maxima locaux >>

Introduction

Le but de cet exercice est d'examiner l'adaptation d'un seuillage global de la norme d'un gradient à la détection des contours dans une image.

Représentation de la norme d'un gradient

Calcul de la norme d'un gradient par convolution

L'image considérée ici est codée sur 8 bits (niveaux de gris de 0 à 255) :

  1. Enregistrer cette image à partir de cette page et l'ouvrir sous ImageJ.
  2. Compléter la macro suivante :
// Calcul de la norme du gradient par masque de Sobel
//
requires("1.41i");	// requis par substring(string, index)
setBatchMode(true);

sourceImage = getImageID();
filename = getTitle();
extension = "";
if (lastIndexOf(filename, ".") > 0) {
    extension = substring(filename, lastIndexOf(filename, "."));
    filename = substring(filename, 0, lastIndexOf(filename, "."));
}
filenameDerX = filename+"_der_x"+extension;
filenameDerY = filename+"_der_y"+extension;
run("Duplicate...", "title="+filenameDerX);
run("32-bit");	// Conversion en Float avant calcul des dérivées !!
... // à compléter
/****** Calcul de la norme du gradient ******/
// récupération de la taille de l'image
w = getWidth();
h = getHeight();
// Calculs pour chaque pixel
... // à compléter
setBatchMode("exit and display");
de façon à :
  • Calculer une approximation des dérivées partielles de la fonction image dans chaque direction principale $(x,y)$ par convolution avec les masques de Sobel :
  • Calculer la norme du gradient dans une nouvelle image. Cette image peut être simplement créée par duplication de l'image de $\frac{\partial I}{\partial x}$ (ci-dessus nommée filenameDerX, de profondeur 32 bits), puis modifiée en chaque pixel grâce à la fonction setPixel.

Comparaison avec le résultat fourni par ImageJ.

  1. Pourquoi les images utilisées ici doivent-elles avoir une profondeur de 32 bits ? Quelle est la valeur minimale et la valeur maximale de la norme du gradient (utiliser le menu Analyse/Histogram ou Analyse/Measure) et comment les expliquez-vous ?
  2. Comparer cette image avec le résultat obtenu en appliquant sur l'image source la fonctionnalité de calcul de la norme du gradient intégrée à ImageJ (menu Process/Find Edges). Quelle transformation faut-il opérer sur l'image issue de votre calcul pour obtenir un résultat similaire ? Appliquer effectivement cette transformation grâce au menu Image/Adjust/Brightness/Contrast ..., transformer l'image correspondante en niveaux sur 8 bits, puis comparer numériquement (grâce au menu Process/Image Calculator ...) les deux images ainsi obtenues pour la norme du gradient.

Seuillage de la norme du gradient précédemment calculée

  1. Utiliser le menu Image/Adjust/Threshold... pour seuiller la norme du gradient calculée. Est-il possible de trouver ainsi un seuil global pour l'image qui mette en évidence les pixels contours de manière satisfaisante ?
  2. Une alternative est de déterminer ce seuil de manière semi-automatique grâce à l'histogramme cumulé de l'image de la norme du gradient. L'idée est de sélectionner seulement un certain pourcentage de pixels contours : ceux pour lesquels la norme est la plus élevée, c'est-à-dire les n% de pixels contours les plus significatifs.
Sur la base de ce principe, proposer un nouveau seuil pour la norme du gradient en ne retenant que 20% des pixels contours. Ce seuil est-il plus satisfaisant que celui déterminé à la question précédente ?
Remarque : Bizarrement, ImageJ ne comporte pas de fonction calculant l'histogramme cumulé d'une image. On pourra donc s'aider de la petite macro suivante :
// Histogramme cumulé
getRawStatistics(surf, moy, min, max, std, h); // h[0..255] <-> histo
hc=newArray(256);
hc[0]=h[0];
for (i=1;i< h.length;i++) {
    hc[i] = hc[i-1]+h[i] ;
}
Plot.create("Histogramme cumulé de "+getTitle, "Niveau", "hc", hc);
Plot.show();