package fr.unistra.pelican.demos.applied.remotesensing; import java.awt.Container; import java.awt.GridLayout; import fr.unistra.pelican.ByteImage; import fr.unistra.pelican.Image; import fr.unistra.pelican.PelicanException; import fr.unistra.pelican.algorithms.conversion.ColorImageFromMultiBandImage; import fr.unistra.pelican.algorithms.conversion.GrayToRGB; import fr.unistra.pelican.algorithms.histogram.ContrastStretch; import fr.unistra.pelican.algorithms.histogram.ContrastStretchEachBands; import fr.unistra.pelican.algorithms.io.ImageLoader; import fr.unistra.pelican.algorithms.morphology.vectorial.VectorialDMP; import fr.unistra.pelican.algorithms.statistics.PCA; import fr.unistra.pelican.algorithms.visualisation.Viewer2D; import fr.unistra.pelican.util.vectorial.orders.*; import javax.swing.*; import java.awt.event.*; import java.io.IOException; /** * A toolbox to compute DMP for multispectral images * * @author lefevre * */ public class MultispectralDMPGUIDemo { public static void main(String[] args) { if (args.length == 0) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { launchGUI(); } }); } else launchConsole(args); } public static void launchGUI() { new MultispectralDMPGUIDemo().gui(); } public static void launchConsole(String args[]) { new MultispectralDMPGUIDemo().console(args); } final static String appName = "MultispectralDMPDemo v1.0"; String path; String filename; String outname; int order; int length; boolean debug; boolean display; Image input; Image output; VectorialOrdering[] orders; String[] orderNames; JFrame frame; JLabel inputLabel; JTextField inputText; JButton inputButton; JLabel orderLabel; JComboBox orderBox; JButton orderButton; JLabel lengthLabel; JTextField lengthText; JButton lengthButton; JButton displayButton; JButton proceedButton; JButton resultButton; JCheckBox pcaCheckbox; JCheckBox byteCheckbox; JCheckBox colorCheckbox; JCheckBox stretchCheckbox; JCheckBox verboseCheckbox; JCheckBox resultCheckbox; /** * GUI interface */ private void gui() { // Create and set up the window. frame = new JFrame(appName); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new GridLayout(6, 3)); Container panel = frame.getContentPane(); // First line : file inputLabel = new JLabel("Input image"); panel.add(inputLabel); inputText = new JTextField("filename"); panel.add(inputText); inputText.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { filename = inputText.getText(); } }); inputButton = new JButton("Browse"); panel.add(inputButton); inputButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser chooser = new JFileChooser(path); if (chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) { try { filename = chooser.getSelectedFile().getCanonicalPath(); path = chooser.getCurrentDirectory().getCanonicalPath(); } catch (IOException e1) { e1.printStackTrace(); } inputText.setText(filename); } } }); // Second line : order orderLabel = new JLabel("Vectorial Ordering"); panel.add(orderLabel); initialiseOrders(); orderBox = new JComboBox(orderNames); orderBox.setSelectedIndex(0); panel.add(orderBox); orderBox.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { order = orderBox.getSelectedIndex(); } }); orderButton = new JButton("More info"); panel.add(orderButton); orderButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(frame, "For a survey of vectorial orderings:\n" + "http://dx.doi.org/10.1016/j.patrec.2007.09.011"); } }); // Third line : length lengthLabel = new JLabel("DMP length"); panel.add(lengthLabel); lengthText = new JTextField(Integer.toString(length)); panel.add(lengthText); lengthText.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { try { length = Integer.parseInt(lengthText.getText()); } catch (NumberFormatException ex) { lengthText.grabFocus(); } } }); panel.add(new JLabel()); // Fourth line : options pcaCheckbox = new JCheckBox("PCA preprocessing"); panel.add(pcaCheckbox); byteCheckbox = new JCheckBox("Byte precision"); byteCheckbox.setSelected(true); panel.add(byteCheckbox); colorCheckbox = new JCheckBox("Pseudo-color"); panel.add(colorCheckbox); stretchCheckbox = new JCheckBox("Stretch before display"); panel.add(stretchCheckbox); verboseCheckbox = new JCheckBox("Verbose mode"); panel.add(verboseCheckbox); resultCheckbox = new JCheckBox("Display result"); panel.add(resultCheckbox); // Fifth line : actions displayButton = new JButton("Display input"); panel.add(displayButton); displayButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { load(); preprocess(); Viewer2D.exec(stretchCheckbox.isSelected() ? ContrastStretchEachBands .exec(input) : input, filename); } catch (PelicanException ex) { JOptionPane.showMessageDialog(frame, "Unable to load: " + filename); } } }); proceedButton = new JButton("Compute DMP"); panel.add(proceedButton); proceedButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (verboseCheckbox.isSelected()) debug = true; else { System.err.close(); verboseCheckbox.setEnabled(false); } display=resultCheckbox.isSelected(); outname = filename.substring(0, filename.lastIndexOf('.')); load(); preprocess(); process(); } }); resultButton = new JButton("Display result"); panel.add(resultButton); resultButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { Viewer2D.exec(stretchCheckbox.isSelected() ? ContrastStretchEachBands .exec(output) : output, orderNames[order]); } catch (Exception ex) { JOptionPane.showMessageDialog(frame, "Unable to display the result"); } } }); // Display the window. frame.pack(); frame.setVisible(true); } public MultispectralDMPGUIDemo() { path = System.getProperty("user.dir"); //path = "/home/miv/lefevre/data/teledetection/jrc"; length = 3; } /** * Console interface * * @param args * arguments */ public void console(String[] args) { initialiseOrders(); if (!checkParams(args)) return; load(); process(); } public boolean checkParams(String[] args) { System.out.println(appName); // Show help if (args.length == 1 && args[0].equalsIgnoreCase("help")) { System.out.println(help()); return false; } // Display image else if (args.length == 2 && args[0].equalsIgnoreCase("display")) { Viewer2D.exec(ImageLoader.exec(args[1]), args[0]); return false; } // Process image else if (args.length == 4 && (args[0].equalsIgnoreCase("process") || args[0] .equalsIgnoreCase("debug"))) { if (args[0].equalsIgnoreCase("debug")) debug = true; filename = args[1]; outname = filename.substring(0, filename.lastIndexOf('.')); setOrder(args[2]); length = Integer.parseInt(args[3]); return true; } error(); return false; } public void error() { System.out.println("Bad usage..."); System.out.println(help()); System.exit(0); } public String help() { return "\navailable commands:\n" + "[help] display this help\n" + "[display FILE] display the image FILE \n" + "[process FILE ORDER LENGTH] compute the DMP of size LENGTH with the vectorial ordering ORDER\n" + "[debug ...] the same as process but in verbose mode\n" + "\navailable vectorial orderings:\n" + listOrders(); } public String listOrders() { initialiseOrders(); StringBuffer s = new StringBuffer(); for (String o : orderNames) { s.append(o); for (int u = 0; u < 30 - o.length(); u++) s.append(' '); s.append("\n"); } return s.toString(); } public void initialiseOrders() { /* * * La plupart des ordres de pelican sont biensur developpes en considerant * les images couleur. Cest-a-dire ils essayent d'exploiter en particulier * les relations presentes parmi les differentes bandes (LSH). En * teledetection des telles relations sont en general soit absentes soit * presentes mais difficile voir impossible a estimer. Cest pourquoi des * methodes asymmetrique+PCA ou simplement des methodes symmetriques sont * utilises. * * Comme asymmetrique, on a le lexicographique avec toutes ses variations: * a-modulus d'Angulo, a-modulus generalise, marker based lexicographique et * a-trimmed-lexicographical extrema..entre autres. Comme symmetrique..norm * suivi de lexicographique (Rivest), distance par rapport a une reference * suivi de lexicographique (Angulo). Les autres R-ordres sont souvent des * pre-ordres. Pour l'instant cest tout ce dont je me souviens. */ orders = new VectorialOrdering[] { null, // new AlphaTrimmedLexicographicalOrdering2(0.5), // new BitMixOrdering(), // new CumulativeDistanceOrdering(), // new ExtremeOrdering(), // new PCALexicographicalOrdering(), new LexicographicalOrdering(10), // new MahalanobisBasedOrdering(input), // new MarginalOrdering(), new MarginalWithNormReplacementOrdering(), new NormBasedOrdering(), new ReducedLexicographicalOrdering(), // new ReferenceBasedDistanceOrdering(), }; orderNames = new String[orders.length]; orderNames[0] = "All !"; for (int o = 1; o < orderNames.length; o++) orderNames[o] = orders[o].getClass().getSimpleName(); } public void setOrder(String name) { initialiseOrders(); // Check the appropriate order for (int t = 0; t < orderNames.length; t++) if (name.equalsIgnoreCase(orderNames[t])) { order = t; return; } error(); order = -1; } public void load() { input = ImageLoader.exec(filename); if (input.getBDim() == 3) input.setColor(true); if (debug) Viewer2D.exec(input, filename); System.out.println("file loaded: " + filename); } public void preprocess() { if (pcaCheckbox.isSelected()) input = PCA.exec(input); if (byteCheckbox.isSelected()) input = new ByteImage(ContrastStretch.exec(input)); if (colorCheckbox.isSelected()) { if (input.getBDim() > 3) input = ColorImageFromMultiBandImage.exec(input, new int[] { 3, 2, 1 }); else if (input.getBDim() < 3) input = GrayToRGB.exec(input.getImage4D(0, Image.B)); } if (debug) System.out.println(input); } public void process() { initialiseOrders(); if (order == 0) for (int o = 1; o < orders.length; o++) { System.out.print(orderNames[o] + "..."); long t1 = System.currentTimeMillis(); apply(o); long t2 = System.currentTimeMillis(); System.out.println(((t2 - t1) / 1000) + " seconds"); } else apply(order); } public void apply(int order) { VectorialOrdering vec = orders[order]; String orderName = orderNames[order]; output = VectorialDMP.exec(input, vec, length, Image.Z); if (output.getBDim() == 3) output.setColor(true); if (debug) System.out.println(output); if (display) Viewer2D.exec(stretchCheckbox.isSelected() ? ContrastStretchEachBands .exec(output):output, orderName); // for (int z = 0; z < output.getZDim(); z++) // ImageSave.exec(output.getImage4D(z, Image.Z), outname + "-" + orderName // + "-" + z + ".tiff"); // TiffMultiplePageImageSave.exec(output, outname + "-" + orderName + ".tiff"); // Image tmp = ImageLoader.exec(outname + "-" + orderName + ".tiff"); // Viewer2D.exec(stretchCheckbox.isSelected() ? ContrastStretchEachBands // .exec(tmp) : tmp, outname + "-" + orderName); } }