package fr.unistra.pelican.algorithms.segmentation.labels; import java.util.Arrays; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.Image; import fr.unistra.pelican.IntegerImage; /** * Merge the labels of connected regions belonging to the same class * * @author Lefevre */ public class MergeLabelsFromClasses extends Algorithm { /** * * Label Image */ public Image labelImage; /** * Class Image */ public Image classImage; /** * Flag for 4-connexity */ public boolean connexity4 = false; /** * result */ public Image outputImage; /** * Constructor * */ public MergeLabelsFromClasses() { super.inputs = "labelImage,classImage"; super.options = "connexity4"; super.outputs = "outputImage"; } public void launch() { outputImage = labelImage.copyImage(false); int xdim = labelImage.getXDim(); int ydim = labelImage.getYDim(); // Rᅵcupᅵration de la classe de chaque label if (!Image.haveSameDimensions(labelImage, classImage)) { System.err .println("MergeLabelsFromClasses: labelImage and classImage do not have same dimensions"); return; } // Dᅵcompte du nombre de labels int maxLabel = 0; for (int p = 0; p < labelImage.size(); p++) if (labelImage.getPixelInt(p) > maxLabel) maxLabel = labelImage.getPixelInt(p); // Association des labels au classes int tabLabel[] = new int[maxLabel + 1]; int min=0; Arrays.fill(tabLabel, -1); for (int p = 0; p < labelImage.size(); p++) { int val = labelImage.getPixelInt(p); if (tabLabel[val] == -1 && classImage.getPixelInt(p) != 0) tabLabel[val] = classImage.getPixelInt(p); } for (int b = 0; b < labelImage.getBDim(); b++) for (int t = 0; t < labelImage.getTDim(); t++) for (int z = 0; z < labelImage.getZDim(); z++) { // Crᅵation de la table d'ᅵquivalence int newLabel[] = new int[maxLabel + 1]; int newLabel2[] = new int[maxLabel + 1]; for (int tt = 0; tt < newLabel.length; tt++) newLabel[tt] = tt; // Parcours de l'image de label et recherche des zones connexes for (int y = 1; y < ydim - 1; y++) for (int x = 1; x < xdim - 1; x++) { int val = labelImage.getPixelInt(x, y, z, t, b); for (int yy = -1; yy <= 1; yy++) for (int xx = -1; xx <= 1; xx++) if (xx != 0 && yy != 0) if (!connexity4 || Math.abs(xx - yy) == 1) { int val2 = labelImage .getPixelInt(x + xx, y + yy, z, t, b); // Si les 2 zones connexes sont de la mᅵme classe, on met // ᅵ // jour la table d'ᅵquivalence if (val2 != val && newLabel[val2] != newLabel[val] && tabLabel[val2] == tabLabel[val]) { min=Math.min(newLabel[newLabel[val]], newLabel[newLabel[val2]]); newLabel[newLabel[val]]=min; newLabel[newLabel[val2]]=min; newLabel[val]=min; newLabel[val2]=min; //newLabel[Math.max(val, val2)] = Math.min(val, val2); //System.out.println(Math.max(val, val2)+" => "+Math.min(val, val2)); } } } // Simplification de la table de labels int nbLabels = 0; for (int tt = 0; tt < newLabel.length; tt++) { if (newLabel[tt] == tt) newLabel2[tt] = nbLabels++; else { int tt2=tt; while (newLabel[tt2] != tt2) tt2=newLabel[tt2]; newLabel[tt]=tt2; } //System.out.println(tt+" "+tabLabel[tt]+" "+newLabel[tt]+" "+newLabel2[newLabel[tt]]); } // Nouveau parcours pour mise ᅵ jour des labels for (int y = 0; y < ydim; y++) for (int x = 0; x < xdim; x++) outputImage.setPixelInt(x, y, z, t, b, newLabel2[newLabel[labelImage.getPixelInt(x, y, z, t, b)]]); } } public static IntegerImage exec(Image labelImage, Image classImage) { return (IntegerImage) new MergeLabelsFromClasses().process(labelImage, classImage); } public static Image exec(Image labelImage, Image classImage, boolean connexity4) { return (IntegerImage) new MergeLabelsFromClasses().process(labelImage, classImage, connexity4); } }