3. Seuillage des maxima locaux par hystérésis

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

Introduction

Après avoir détecté les maxima locaux de la norme du gradient, une étape de seuillage est nécessaire pour aboutir aux pixels contours. Le seuillage par hystérésis proposé par Canny utilise 2 seuils au lieu d'un. Cela améliore la flexibilité du seuillage, mais nécessite davantage de calculs. Pour obtenir des temps de calcul raisonnables, nous allons implémenter son algorithme dans ImageJ sous forme de plugin (écrit en Java) et non plus de macro.

L'image de travail est la même que celle des exercices précédents (Phare).

Analyse d'un plugin existant

La méthode ci-dessous, inspirée du code de Xavier Philippeau, réalise l'implémentation du seuillage par hystérésis de l'image représentant la norme du gradient :

public ByteProcessor hystIter(ImageProcessor imNormeG, int seuilBas, int seuilHaut) {
    int width = imNormeG.getWidth();
    int height = imNormeG.getHeight();

    ByteProcessor maxLoc = new ByteProcessor(width,height);
    List<int[]> highpixels = new ArrayList<int[]>();

    for (int y=0; y<height; y++) {
        for (int x=0; x<width; x++) {

            int g = imNormeG.getPixel(x, y)&0xFF;
            if (g<seuilBas) continue;

            if (g>seuilHaut) {
                maxLoc.set(x,y,255);
                highpixels.add(new int[]{x,y});
                continue;
            }

            maxLoc.set(x,y,128);
        }
    }

    int[] dx8 = new int[] {-1, 0, 1,-1, 1,-1, 0, 1};
    int[] dy8 = new int[] {-1,-1,-1, 0, 0, 1, 1, 1};

    while(!highpixels.isEmpty()) {

        List<int[]> newhighpixels = new ArrayList<int[]>();

        for(int[] pixel : highpixels) {
            int x=pixel[0], y=pixel[1];

            for(int k=0;k<8;k++) {
                int xk=x+dx8[k], yk=y+dy8[k];
                if (xk<0 || xk>=width) continue;
                if (yk<0 || yk>=height) continue;
                if (maxLoc.get(xk, yk)==128) {
                    maxLoc.set(xk, yk, 255);
                    newhighpixels.add(new int[]{xk, yk});
                }
            }
        }

        highpixels = newhighpixels;
    }

    for (int y=0; y<height; y++) {
        for (int x=0; x<width; x++) {
            if (maxLoc.get(x, y)!=255) maxLoc.set(x,y,0);
        }
    }
    return maxLoc;
}
  1. Intégrer cette méthode dans un plugin imageJ et tester celui-ci. Pour vous aider, voici une version minimaliste (seuils définis dans le code) de ce plugin dans lequel pourra être intégrée la méthode :
import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.plugin.filter.PlugInFilter;
import ij.process.*;
import java.util.ArrayList;
import java.util.List;

public class TestPlugin_ implements PlugInFilter {

    private int seuilBas=30;
    private int seuilHaut=100;

    public int setup(String arg, ImagePlus imp) {
        return PlugInFilter.DOES_8G;
    }

    public void run(ImageProcessor ip) {
        ByteProcessor newbp = hystIter(ip, this.seuilBas, this.seuilHaut);
        ImagePlus newImg = new ImagePlus("Résultat du seuillage par hystérésis", newbp);
        newImg.show();
    }
}
  1. Analyser le code de la méthode hystIter, décrire globalement son fonctionnement, puis lui ajouter tous les commentaires nécessaires à sa compréhension.

Implémentation récursive du seuillage par hystérésis

  1. Écrire une version récursive hystRec de la méthode de seuillage précédente. Cela consiste à propager récursivement le seuillage à partir de chaque point $(x,y)$ pour lequel la norme du gradient est supérieure au seuil haut, par exemple grâce à la méthode :
private void propaRec (ImageProcessor imNormeG, ImageProcessor imContours, int seuilBas, int x, int y)
Cette méthode doit marquer le point $(x,y)$ comme contour puis propager récursivement le seuillage à ses 8 voisins. Les conditions d'arrêt de la récursivité devront évidemment être spécifiées. Comparer le résultat obtenu avec celui fourni par la version itérative.
  1. Il n'existe pas de méthode pour déterminer automatiquement des seuils fournissant des résultats satisfaisants sur tous types d'images. Déterminer donc empiriquement, pour notre image de travail, quels sont les seuils que vous préconisez d'adopter. Bien que basés sur une analyse subjective, ceux-ci devront être justifiés au regard des résultats obtenus.