package fr.unistra.pelican.algorithms.segmentation; import java.awt.Point; import java.util.Vector; import weka.clusterers.SimpleKMeans; import weka.core.FastVector; import weka.core.Instance; import weka.core.Instances; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.BooleanImage; import fr.unistra.pelican.Image; import fr.unistra.pelican.InvalidNumberOfParametersException; import fr.unistra.pelican.InvalidTypeOfParameterException; import fr.unistra.pelican.algorithms.geometric.Crop2D; import fr.unistra.pelican.algorithms.io.ImageLoader; import fr.unistra.pelican.algorithms.io.ImageSave; import fr.unistra.pelican.algorithms.morphology.gray.GrayGradient; import fr.unistra.pelican.algorithms.morphology.gray.geodesic.GrayOpeningByReconstruction; import fr.unistra.pelican.algorithms.morphology.gray.granulometry.LimitedGranulometry; import fr.unistra.pelican.algorithms.visualisation.Viewer2D; import fr.unistra.pelican.util.morphology.FlatStructuringElement2D; /** * This algorithm return an segmented image based on granulometry analysis. It's * based on the granulometric analysis of various areas coming from a watershed * operation */ public class TextureCharacterization extends Algorithm { // Inputs parameters public Image inputImage; public int nbClusters; // Outputs parameters public Image outputImage; /** * Constructor * */ public TextureCharacterization() { super(); super.inputs = "inputImage,nbClusters"; super.outputs = "outputImage"; } /* * (non-Javadoc) * * @see fr.unistra.pelican.Algorithm#launch() */ public void launch() throws AlgorithmException { try { int count = 0; Vector granulometry_vector = new Vector(); outputImage = inputImage.copyImage(false); outputImage.setColor(true); // Elements structurants pour les traitements BooleanImage se = FlatStructuringElement2D .createSquareFlatStructuringElement(3); BooleanImage se2 = FlatStructuringElement2D .createSquareFlatStructuringElement(2); // Image OKKO = GrayOCCO.process(inputImage,se); // Viewer2D.exec(OKKO,"okko"); // Image median = GrayMedian.process(inputImage,se); // Viewer2D.exec(median,"median"); Image to = (Image) new GrayOpeningByReconstruction().process(inputImage, se); Image img2 = (Image) new GrayGradient().process(to, se2); System.out.println("GrayGradient done"); new Viewer2D().process(img2, "gradient"); Image img3 = (Image) new Watershed().process(img2); System.out.println("Watershed done"); // Creation du mask pour la granulometrie BooleanImage mask = new BooleanImage(inputImage, false); // Image temporaire "vide" de la taille de l'image de depart Image fond = inputImage.copyImage(false); // On calcule la distribution de chacun des labels de l image // segmentee par watershed Vector v = label_distribution(img3); for (int i = 1; i < v.size(); i++) {// v.size() mask = new BooleanImage(inputImage, false); mask.setBDim(1); mask.fill(false); int x, y; int x1 = 0, x2 = 0, y1 = 0, y2 = 0; Image tmp = fond.copyImage(false); // On recupere l'ensemble des pixels de label i Vector ens_pixel = (Vector) v.get(i); // Si l'entree i n existe pas c est que le label i n existe pas if (ens_pixel == null) { System.out.println("l entree" + i + "existe pas"); count++; } // On recopie les pixels de label i a partir de l image de // depart dans une nouvelle image // Puis on recadre autour de la zone de label i et on effectue // une mesure de granulometrie else { if (ens_pixel.size() == 0) System.out.println("Oops"); x1 = (int) ((Point) (ens_pixel.get(0))).getX(); x2 = (int) ((Point) (ens_pixel.get(0))).getX(); y1 = (int) ((Point) (ens_pixel.get(0))).getY(); y2 = (int) ((Point) (ens_pixel.get(0))).getY(); // Boucle pour chaque pixel de label i for (int j = 0; j < ens_pixel.size(); j++) { Point a; // On calcule le plus petit cadre autour de la zone de // pixel de label i a = (Point) ens_pixel.get(j); x = (int) a.getX(); y = (int) a.getY(); if (x < x1) x1 = x; if (y < y1) y1 = y; if (x > x2) x2 = x; if (y > y2) y2 = y; // On cree un masque de taille adaptee initialise a faux // Il sera utilise pour calculer des donnees // granulometriques plus precises // On recopie les pixels depuis l image de depart vers // une image a analyser for (int bande = 0; bande < inputImage.getBDim(); bande++) { tmp.setPixelXYBDouble(x, y, bande, inputImage .getPixelXYBDouble(x, y, bande)); mask.setPixelXYBBoolean(x, y, 0, true); } } } // Recadrage autour de la zone de label i Image window = (Image) new Crop2D().process(tmp, x1, y1, x2, y2); BooleanImage imask = (BooleanImage) new Crop2D().process(mask, x1, y1, x2, y2); // Resultat de l analyse granulometrique de la zone de label i double[] granulometry = (double[]) new LimitedGranulometry().process(window, 7, imask); if ((i % 1000) == 0)// pour voir avancement System.out.println("Granulo " + i); // On place ce resultat dans le vecteur resultat if (granulometry_vector.size() <= i) { granulometry_vector.setSize(i + 1); } granulometry_vector.set(i, granulometry); } System.out.println("Granulometry done "); // Debut de la classification Kmeans SimpleKMeans clusterer = new SimpleKMeans(); try { clusterer.setNumClusters(nbClusters); } catch (Exception e) { e.printStackTrace(); } double[] vect = (double[]) granulometry_vector.get(1); // Nb de mesures granulometriques int taille = vect.length; FastVector attributes = new FastVector(taille); for (int i = 0; i < vect.length; i++) attributes.addElement(new weka.core.Attribute("SE " + i)); Instances dataset = new Instances("dataset", attributes, 0); for (int i = 1; i < granulometry_vector.size(); i++) { double tmp[] = (double[]) granulometry_vector.get(i); Instance instance = new Instance(dataset.numAttributes()); for (int j = 0; j < taille; j++) { instance.setValue(j, tmp[j]); } instance.setDataset(dataset); dataset.add(instance); } // Learn the classification try { clusterer.buildClusterer(dataset); } catch (Exception e) { e.printStackTrace(); } System.out.println(clusterer.toString()); for (int i = 1; i < granulometry_vector.size(); i++) { double tmp[] = (double[]) granulometry_vector.get(i); Instance instance = new Instance(dataset.numAttributes()); for (int j = 0; j < taille; j++) { instance.setValue(j, tmp[j]); } instance.setDataset(dataset); int label = -1; try { label = clusterer.clusterInstance(instance); } catch (Exception e) { e.printStackTrace(); } Vector ens_pixel = (Vector) v.get(i); int couleur = (255 / nbClusters) * (label); // On attribue une couleur aux pixels d'un label i for (int i_ = 0; i_ < ens_pixel.size(); i_++) { Point a = (Point) ens_pixel.get(i_); int x = (int) a.getX(); int y = (int) a.getY(); // Pour attribuer simplement le numero du label au tous les // pixels, simplement mettre setPixelInt(x,y,label) if (label % 5 == 0) { outputImage.setPixelXYBByte(x, y, 0, couleur); } else if (label % 5 == 1) { outputImage.setPixelXYBByte(x, y, 1, couleur); } else if (label % 5 == 2) { outputImage.setPixelXYBByte(x, y, 2, couleur); } else if (label % 5 == 3) { outputImage.setPixelXYBByte(x, y, 0, couleur); outputImage.setPixelXYBByte(x, y, 1, couleur); } else if (label % 5 == 4) { outputImage.setPixelXYBByte(x, y, 1, couleur); outputImage.setPixelXYBByte(x, y, 2, couleur); } else { outputImage.setPixelXYBByte(x, y, 0, couleur); outputImage.setPixelXYBByte(x, y, 2, couleur); } } } System.out.println("Classification done"); } catch (Exception e) { e.printStackTrace(); } } // This function puts the coordinates of the point (of the image img) which // label is L at the position L in a vector private Vector label_distribution(Image img) { Vector<Vector> ens_label = new Vector<Vector>(); for (int i = 0; i < img.getXDim(); i++) { for (int j = 0; j < img.getYDim(); j++) { int label = img.getPixelXYBInt(i, j, 0) - Integer.MIN_VALUE; if (ens_label.size() <= label) { ens_label.setSize(label + 1); } if (ens_label.get(label) == null) { ens_label.set(label, new Vector()); } (ens_label.get(label)).add(new Point(i, j)); } } System.out.println("Number of labels " + ens_label.size()); return ens_label; } public static void main(String[] args) { String file = "c:\\aster_05082003.hdr"; if (args.length > 0) file = args[0]; try { // Load the image Image source = (Image) new ImageLoader().process(file); new Viewer2D().process(source, "Image " + file); Image source2 = (Image) new Crop2D().process(source, 0, 0, 300, 300); // Image source2 = Crop.process(source,0,50,700,350); new Viewer2D().process(source2, "Image " + file); Image result = (Image) new TextureCharacterization().process(source2, 5); new Viewer2D().process(result, "Result"); new ImageSave().process(result, "c:\\resulat.tiff"); new ImageSave().process(source, "c:\\source.tiff"); } catch (InvalidTypeOfParameterException e) { e.printStackTrace(); } catch (AlgorithmException e) { e.printStackTrace(); } catch (InvalidNumberOfParametersException e) { e.printStackTrace(); } } }