diff --git a/.gitignore b/.gitignore index 3d47f986c41db29ec6dc0d5036bf760b3a1cf366..8d47cace3a5bd898da9fb12bed716d60838191a4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ target/ .settings/ *.iml .project -.classpath \ No newline at end of file +.classpath +**/.DS_Store \ No newline at end of file diff --git a/pom.xml b/pom.xml index d4f3419bee216abb2d3c4f3a4d3f23827e0f0de3..82a4ff738b8bfe382d4ea39ab5ab9001f564ec6c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,19 +7,17 @@ <!-- Inherited Icy Parent POM --> <parent> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>parent-pom-plugin</artifactId> - <version>1.0.3</version> + <artifactId>pom-icy</artifactId> + <version>2.2.0</version> </parent> <!-- Project Information --> <artifactId>kmeans-color-quantization</artifactId> - <version>1.2.1</version> - - <packaging>jar</packaging> + <version>2.0.0</version> <name>KMeans Color Quantization</name> <description>Quantize a color image in any given number of colors.</description> - <url>http://icy.bioimageanalysis.org/plugin/kmeans-color-quantization/</url> + <url>https://icy.bioimageanalysis.org/plugin/kmeans-color-quantization/</url> <inceptionYear>2020</inceptionYear> <organization> @@ -53,34 +51,16 @@ </developer> </developers> - <!-- Project properties --> - <properties> - - </properties> - - <!-- Project build configuration --> - <build> - - </build> - <!-- List of project's dependencies --> <dependencies> - <!-- The core of Icy --> - <dependency> - <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>icy-kernel</artifactId> - </dependency> - <dependency> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>nherve-toolbox</artifactId> - <version>1.3.2</version> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>mask-editor</artifactId> - <version>1.2.1</version> </dependency> </dependencies> diff --git a/src/main/java/plugins/nherve/colorquantization/KMeansColorQuantization.java b/src/main/java/plugins/nherve/colorquantization/KMeansColorQuantization.java index 286fac3fad353ee0fe8df52ca1d5c9cf75e1fecf..767e55a549d61777b9378f478772d1aba1198f9f 100644 --- a/src/main/java/plugins/nherve/colorquantization/KMeansColorQuantization.java +++ b/src/main/java/plugins/nherve/colorquantization/KMeansColorQuantization.java @@ -1,59 +1,37 @@ /* - * Copyright 2010, 2011 Institut Pasteur. - * - * This file is part of ${CurrentProject}, which is an ICY plugin. - * - * ${CurrentProject} is free software: you can redistribute it and/or modify + * Copyright (c) 2010-2023. Institut Pasteur. + * + * This file is part of Icy. + * Icy is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * - * ${CurrentProject} is distributed in the hope that it will be useful, + * + * Icy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with ${CurrentProject}. If not, see <http://www.gnu.org/licenses/>. + * along with Icy. If not, see <https://www.gnu.org/licenses/>. */ + package plugins.nherve.colorquantization; -import icy.gui.component.ComponentUtil; +import icy.gui.util.ComponentUtil; import icy.gui.util.GuiUtil; import icy.main.Icy; import icy.preferences.XMLPreferences; import icy.sequence.Sequence; import icy.swimmingPool.SwimmingObject; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.lang.reflect.InvocationTargetException; -import java.text.DecimalFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.swing.Box; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.border.TitledBorder; - +import icy.system.IcyExceptionHandler; import plugins.nherve.maskeditor.MaskEditor; import plugins.nherve.toolbox.Algorithm; import plugins.nherve.toolbox.NherveToolbox; import plugins.nherve.toolbox.image.feature.DefaultClusteringAlgorithmImpl; +import plugins.nherve.toolbox.image.feature.IcySupportRegion; import plugins.nherve.toolbox.image.feature.SegmentableIcyBufferedImage; import plugins.nherve.toolbox.image.feature.Signature; -import plugins.nherve.toolbox.image.feature.IcySupportRegion; import plugins.nherve.toolbox.image.feature.clustering.KMeans; import plugins.nherve.toolbox.image.feature.descriptor.ColorPixel; import plugins.nherve.toolbox.image.feature.descriptor.DefaultDescriptorImpl; @@ -70,354 +48,343 @@ import plugins.nherve.toolbox.image.toolboxes.ColorSpaceTools; import plugins.nherve.toolbox.plugin.HelpWindow; import plugins.nherve.toolbox.plugin.SingletonPlugin; +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.reflect.InvocationTargetException; +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * The Class KMeansColorQuantization. - * + * <p> * The pixel colors extraction is not optimized as it uses a more generic * framework. If you need a quicker version, you'll have to change this part. * However, the KMeans implementation is optimized and multithreaded. - * + * * @author Nicolas HERVE - nicolas.herve@pasteur.fr */ public class KMeansColorQuantization extends SingletonPlugin implements ActionListener { - private static String HELP = "<html>" + "<p align=\"center\"><b>" + HelpWindow.getTagFullPluginName() + "</b></p>" + "<p align=\"center\"><b>" + NherveToolbox.getDevNameHtml() + "</b></p>" + "<p align=\"center\"><b>" + NherveToolbox.getCopyrightHtml() + "</b></p>" + "<hr/>" + "<p>" + HelpWindow.getTagPluginName() + NherveToolbox.getLicenceHtml() + "</p>" + "<p>" + NherveToolbox.getLicenceHtmllink() + "</p>" + "</html>"; - - private Map<Integer, Integer> indexToColorspace; - - /** The cb color space. */ - private JComboBox cbColorSpace; - - /** The bt start. */ - private JButton btStart; - - /** The tf nb cluster2. */ - private JTextField tfNbCluster2; - - /** The tf nb iteration2. */ - private JTextField tfNbIteration2; - - /** The tf stab crit2. */ - private JTextField tfStabCrit2; - - /** The cb display. */ - private JCheckBox cbDisplay; - - /** The cb send mask directly. */ - private JCheckBox cbSendMaskDirectly; - - private JButton btHelp; - - /** The currently running. */ - private Thread currentlyRunning; - - /* - * (non-Javadoc) - * - * @see plugins.nherve.toolbox.AbleToLogMessages#isDisplayEnabled() - */ - @Override - public boolean isLogEnabled() { - return cbDisplay.isSelected(); - } - - /* - * (non-Javadoc) - * - * @see plugins.nherve.toolbox.plugin.SingletonPlugin#sequenceHasChanged() - */ - @Override - public void sequenceHasChanged() { - btStart.setEnabled(hasCurrentSequence()); - } - - /* - * (non-Javadoc) - * - * @see plugins.nherve.toolbox.plugin.SingletonPlugin#sequenceWillChange() - */ - @Override - public void sequenceWillChange() { - } - - @Override - public void fillInterface(JPanel mainPanel) { - currentlyRunning = null; - - XMLPreferences preferences = getPreferences(); - int nbc2 = preferences.getInt("nbc2", 10); - int nbi2 = preferences.getInt("nbi2", 100); - double stab2 = preferences.getDouble("stab2", 0.001); - - boolean dsp = preferences.getBoolean("dsp", false); - - indexToColorspace = new HashMap<Integer, Integer>(); - cbColorSpace = new JComboBox(); - cbColorSpace.addItem(ColorSpaceTools.COLOR_SPACES[ColorSpaceTools.RGB]); - indexToColorspace.put(0, ColorSpaceTools.RGB); - cbColorSpace.addItem(ColorSpaceTools.COLOR_SPACES[ColorSpaceTools.RGB_TO_HSV]); - indexToColorspace.put(1, ColorSpaceTools.RGB_TO_HSV); - cbColorSpace.addItem(ColorSpaceTools.COLOR_SPACES[ColorSpaceTools.RGB_TO_H1H2H3]); - indexToColorspace.put(2, ColorSpaceTools.RGB_TO_H1H2H3); - ComponentUtil.setFixedSize(cbColorSpace, new Dimension(100, 25)); - - JPanel cs = GuiUtil.createLineBoxPanel(new JLabel("Color space"), Box.createHorizontalGlue(), cbColorSpace); - cs.setBorder(new TitledBorder("Color description")); - mainPanel.add(cs, BorderLayout.NORTH); - - tfNbCluster2 = new JTextField(Integer.toString(nbc2)); - ComponentUtil.setFixedSize(tfNbCluster2, new Dimension(100, 25)); - JPanel p1 = GuiUtil.createLineBoxPanel(new JLabel("Nb. clusters"), Box.createHorizontalGlue(), tfNbCluster2); - - tfNbIteration2 = new JTextField(Integer.toString(nbi2)); - ComponentUtil.setFixedSize(tfNbIteration2, new Dimension(100, 25)); - JPanel p2 = GuiUtil.createLineBoxPanel(new JLabel("Nb. max iterations"), Box.createHorizontalGlue(), tfNbIteration2); - - tfStabCrit2 = new JTextField(Double.toString(stab2)); - ComponentUtil.setFixedSize(tfStabCrit2, new Dimension(100, 25)); - JPanel p3 = GuiUtil.createLineBoxPanel(new JLabel("Stabilization criterion"), Box.createHorizontalGlue(), tfStabCrit2); - - JPanel algo = GuiUtil.createPageBoxPanel(p1, p2, p3); - algo.setBorder(new TitledBorder("KMeans clustering algorithm")); - mainPanel.add(algo, BorderLayout.CENTER); - - btHelp = new JButton(NherveToolbox.questionIcon); - btHelp.setToolTipText("Get some basic informations"); - btHelp.addActionListener(this); - cbDisplay = new JCheckBox("Log"); - cbDisplay.setSelected(dsp); - cbSendMaskDirectly = new JCheckBox("Send to editor"); - cbSendMaskDirectly.setSelected(true); - btStart = new JButton("Start"); - btStart.addActionListener(this); - btStart.setEnabled(hasCurrentSequence()); - - JPanel bottom = GuiUtil.createLineBoxPanel(new Component[] { btHelp, Box.createHorizontalGlue(), cbDisplay, cbSendMaskDirectly, Box.createHorizontalGlue(), btStart }); - mainPanel.add(bottom, BorderLayout.SOUTH); - } - - /* - * (non-Javadoc) - * - * @see plugins.nherve.toolbox.plugin.SingletonPlugin#stopInterface() - */ - @Override - public void stopInterface() { - try { - XMLPreferences preferences = getPreferences(); - - preferences.putInt("nbc2", Integer.parseInt(tfNbCluster2.getText())); - preferences.putInt("nbi2", Integer.parseInt(tfNbIteration2.getText())); - preferences.putDouble("stab2", Double.parseDouble(tfStabCrit2.getText())); - preferences.putInt("cs", cbColorSpace.getSelectedIndex()); - preferences.putBoolean("dsp", cbDisplay.isSelected()); - } catch (NumberFormatException e) { - e.printStackTrace(); - } - } - - /* - * (non-Javadoc) - * - * @see - * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - @Override - public void actionPerformed(ActionEvent e) { - JButton b = (JButton) e.getSource(); - if (b == null) { - return; - } - - if (b == btHelp) { - openHelpWindow(HELP, 400, 300); - return; - } - - if (b == btStart) { - if (hasCurrentSequence() && (currentlyRunning == null)) { - btStart.setEnabled(false); - currentlyRunning = new Thread() { - @Override - public void run() { - try { - final Sequence cs = getCurrentSequence(); - final Segmentation seg = doClustering(cs); - if (cbSendMaskDirectly.isSelected()) { - final MaskEditor me = MaskEditor.getRunningInstance(true); - currentlyRunning = null; - Runnable r = new Runnable() { - @Override - public void run() { - me.setSegmentationForSequence(cs, seg); - me.switchOpacityOn(); - btStart.setEnabled(true); - } - }; - SwingUtilities.invokeAndWait(r); - } else { - SwimmingObject result = new SwimmingObject(seg); - Icy.getMainInterface().getSwimmingPool().add(result); - currentlyRunning = null; - Runnable r = new Runnable() { - @Override - public void run() { - btStart.setEnabled(true); - } - }; - SwingUtilities.invokeAndWait(r); - } - } catch (SupportRegionException e1) { - logError(e1.getClass().getName() + " : " + e1.getMessage()); - } catch (SegmentationException e1) { - logError(e1.getClass().getName() + " : " + e1.getMessage()); - } catch (InterruptedException e1) { - logError(e1.getClass().getName() + " : " + e1.getMessage()); - } catch (InvocationTargetException e1) { - logError(e1.getClass().getName() + " : " + e1.getMessage()); - } catch (MaskException e1) { - logError(e1.getClass().getName() + " : " + e1.getMessage()); - } catch (NumberFormatException e) { - logError(e.getClass().getName() + " : " + e.getMessage()); - } catch (SignatureException e) { - logError(e.getClass().getName() + " : " + e.getMessage()); - } - } - }; - currentlyRunning.start(); - } - return; - } - - } - - /** - * Do single clustering. - * - * @param img - * the img - * @param regions - * the regions - * @param descriptor - * the descriptor - * @param algo - * the algo - * @return the segmentation - * @throws SupportRegionException - * the support region exception - * @throws SegmentationException - * the segmentation exception - */ - private Segmentation doSingleClustering(SegmentableIcyBufferedImage img, IcySupportRegion[] regions, DefaultDescriptorImpl<SegmentableIcyBufferedImage, ? extends Signature> descriptor, DefaultClusteringAlgorithmImpl<VectorSignature> algo) throws SupportRegionException, SegmentationException { - DefaultSegmentationAlgorithm<SegmentableIcyBufferedImage> segAlgo = new DefaultSegmentationAlgorithm<SegmentableIcyBufferedImage>(descriptor, algo); - segAlgo.setLogEnabled(isLogEnabled()); - - Segmentation seg = segAlgo.segment(img, regions); - - return seg; - } - - /** - * Gets the some stats. - * - * @param seg - * the seg - * @return the some stats - */ - private void getSomeStats(Segmentation seg) { - DecimalFormat df = new DecimalFormat("0"); - Algorithm.out("id;label;h1;h2;h3"); - for (Mask m : seg) { - Color rgb = m.getColor(); - double[] h1h2h3 = ColorSpaceTools.getColorComponentsD_0_255(ColorSpaceTools.RGB_TO_I1H2H3, rgb.getRed(), rgb.getGreen(), rgb.getBlue()); - log(m.getId() + ";" + m.getLabel() + ";" + df.format(h1h2h3[0]) + ";" + df.format(h1h2h3[1]) + ";" + df.format(h1h2h3[2])); - } - } - - /** - * Do clustering. - * - * @param currentSequence - * the current sequence - * @return the segmentation - * @throws SupportRegionException - * the support region exception - * @throws SegmentationException - * the segmentation exception - * @throws MaskException - * the mask exception - * @throws NumberFormatException - * the number format exception - * @throws SignatureException - * the signature exception - */ - private Segmentation doClustering(Sequence currentSequence) throws SupportRegionException, SegmentationException, MaskException, NumberFormatException, SignatureException { - Segmentation seg = null; - - seg = doClusteringKM(currentSequence); - seg.reInitColors(currentSequence.getImage(0, 0)); - if (isLogEnabled()) { - getSomeStats(seg); - } - - return seg; - } - - /** - * Do clustering km. - * - * @param currentSequence - * the current sequence - * @return the segmentation - * @throws SupportRegionException - * the support region exception - * @throws SegmentationException - * the segmentation exception - * @throws MaskException - * the mask exception - * @throws NumberFormatException - * the number format exception - * @throws SignatureException - * the signature exception - */ - private Segmentation doClusteringKM(Sequence currentSequence) throws SupportRegionException, SegmentationException, MaskException, NumberFormatException, SignatureException { - int nbc2 = Integer.parseInt(tfNbCluster2.getText()); - int nbi2 = Integer.parseInt(tfNbIteration2.getText()); - double stab2 = Double.parseDouble(tfStabCrit2.getText()); - int cs = indexToColorspace.get(cbColorSpace.getSelectedIndex()); - - log("Working on " + ColorSpaceTools.COLOR_SPACES[cs]); - - SegmentableIcyBufferedImage img = new SegmentableIcyBufferedImage(currentSequence.getFirstImage()); - - KMeans km2 = new KMeans(nbc2, nbi2, stab2); - km2.setLogEnabled(isLogEnabled()); - - Segmentation seg = null; - - DefaultDescriptorImpl<SegmentableIcyBufferedImage, ? extends Signature> col = null; - - ColorPixel cd = new ColorPixel(isLogEnabled()); - cd.setColorSpace(cs); - col = cd; - - col.setLogEnabled(isLogEnabled()); - - GridFactory factory = new GridFactory(GridFactory.ALGO_ONLY_PIXELS); - factory.setLogEnabled(isLogEnabled()); - List<IcySupportRegion> lRegions = factory.extractRegions(img); - IcySupportRegion[] regions = new IcySupportRegion[lRegions.size()]; - int r = 0; - for (IcySupportRegion sr : lRegions) { - regions[r++] = sr; - } - - seg = doSingleClustering(img, regions, col, km2); - - return seg; - } - - @Override - public Dimension getDefaultFrameDimension() { - return new Dimension(550, 300); - } + private static final String HELP = "<html>" + "<p align=\"center\"><b>" + HelpWindow.getTagFullPluginName() + "</b></p>" + "<p align=\"center\"><b>" + NherveToolbox.getDevNameHtml() + "</b></p>" + "<p align=\"center\"><b>" + NherveToolbox.getCopyrightHtml() + "</b></p>" + "<hr/>" + "<p>" + HelpWindow.getTagPluginName() + NherveToolbox.getLicenceHtml() + "</p>" + "<p>" + NherveToolbox.getLicenceHtmllink() + "</p>" + "</html>"; + + private Map<Integer, Integer> indexToColorspace; + + /** + * The cb color space. + */ + private JComboBox<String> cbColorSpace; + + /** + * The bt start. + */ + private JButton btStart; + + /** + * The tf nb cluster2. + */ + private JTextField tfNbCluster2; + + /** + * The tf nb iteration2. + */ + private JTextField tfNbIteration2; + + /** + * The tf stab crit2. + */ + private JTextField tfStabCrit2; + + /** + * The cb display. + */ + private JCheckBox cbDisplay; + + /** + * The cb send mask directly. + */ + private JCheckBox cbSendMaskDirectly; + + private JButton btHelp; + + /** + * The currently running. + */ + private Thread currentlyRunning; + + /* + * (non-Javadoc) + * + * @see plugins.nherve.toolbox.AbleToLogMessages#isDisplayEnabled() + */ + @Override + public boolean isLogEnabled() { + return cbDisplay.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see plugins.nherve.toolbox.plugin.SingletonPlugin#sequenceHasChanged() + */ + @Override + public void sequenceHasChanged() { + btStart.setEnabled(hasCurrentSequence()); + } + + /* + * (non-Javadoc) + * + * @see plugins.nherve.toolbox.plugin.SingletonPlugin#sequenceWillChange() + */ + @Override + public void sequenceWillChange() { + } + + @Override + public void fillInterface(final JPanel mainPanel) { + currentlyRunning = null; + + final XMLPreferences preferences = getPreferences(); + final int nbc2 = preferences.getInt("nbc2", 10); + final int nbi2 = preferences.getInt("nbi2", 100); + final double stab2 = preferences.getDouble("stab2", 0.001); + + final boolean dsp = preferences.getBoolean("dsp", false); + + indexToColorspace = new HashMap<>(); + cbColorSpace = new JComboBox<>(); + cbColorSpace.addItem(ColorSpaceTools.COLOR_SPACES[ColorSpaceTools.RGB]); + indexToColorspace.put(0, ColorSpaceTools.RGB); + cbColorSpace.addItem(ColorSpaceTools.COLOR_SPACES[ColorSpaceTools.RGB_TO_HSV]); + indexToColorspace.put(1, ColorSpaceTools.RGB_TO_HSV); + cbColorSpace.addItem(ColorSpaceTools.COLOR_SPACES[ColorSpaceTools.RGB_TO_H1H2H3]); + indexToColorspace.put(2, ColorSpaceTools.RGB_TO_H1H2H3); + ComponentUtil.setFixedSize(cbColorSpace, new Dimension(100, 25)); + + final JPanel cs = GuiUtil.createLineBoxPanel(new JLabel("Color space"), Box.createHorizontalGlue(), cbColorSpace); + cs.setBorder(new TitledBorder("Color description")); + mainPanel.add(cs, BorderLayout.NORTH); + + tfNbCluster2 = new JTextField(Integer.toString(nbc2)); + ComponentUtil.setFixedSize(tfNbCluster2, new Dimension(100, 25)); + final JPanel p1 = GuiUtil.createLineBoxPanel(new JLabel("Nb. clusters"), Box.createHorizontalGlue(), tfNbCluster2); + + tfNbIteration2 = new JTextField(Integer.toString(nbi2)); + ComponentUtil.setFixedSize(tfNbIteration2, new Dimension(100, 25)); + final JPanel p2 = GuiUtil.createLineBoxPanel(new JLabel("Nb. max iterations"), Box.createHorizontalGlue(), tfNbIteration2); + + tfStabCrit2 = new JTextField(Double.toString(stab2)); + ComponentUtil.setFixedSize(tfStabCrit2, new Dimension(100, 25)); + final JPanel p3 = GuiUtil.createLineBoxPanel(new JLabel("Stabilization criterion"), Box.createHorizontalGlue(), tfStabCrit2); + + final JPanel algo = GuiUtil.createPageBoxPanel(p1, p2, p3); + algo.setBorder(new TitledBorder("KMeans clustering algorithm")); + mainPanel.add(algo, BorderLayout.CENTER); + + btHelp = new JButton(NherveToolbox.questionIcon); + btHelp.setToolTipText("Get some basic informations"); + btHelp.addActionListener(this); + cbDisplay = new JCheckBox("Log"); + cbDisplay.setSelected(dsp); + cbSendMaskDirectly = new JCheckBox("Send to editor"); + cbSendMaskDirectly.setSelected(true); + btStart = new JButton("Start"); + btStart.addActionListener(this); + btStart.setEnabled(hasCurrentSequence()); + + final JPanel bottom = GuiUtil.createLineBoxPanel( + btHelp, + Box.createHorizontalGlue(), + cbDisplay, + cbSendMaskDirectly, + Box.createHorizontalGlue(), + btStart + ); + mainPanel.add(bottom, BorderLayout.SOUTH); + } + + /* + * (non-Javadoc) + * + * @see plugins.nherve.toolbox.plugin.SingletonPlugin#stopInterface() + */ + @Override + public void stopInterface() { + try { + final XMLPreferences preferences = getPreferences(); + + preferences.putInt("nbc2", Integer.parseInt(tfNbCluster2.getText())); + preferences.putInt("nbi2", Integer.parseInt(tfNbIteration2.getText())); + preferences.putDouble("stab2", Double.parseDouble(tfStabCrit2.getText())); + preferences.putInt("cs", cbColorSpace.getSelectedIndex()); + preferences.putBoolean("dsp", cbDisplay.isSelected()); + } + catch (final NumberFormatException e) { + IcyExceptionHandler.showErrorMessage(e, true); + } + } + + /* + * (non-Javadoc) + * + * @see + * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + @Override + public void actionPerformed(final ActionEvent e) { + final JButton b = (JButton) e.getSource(); + if (b == null) { + return; + } + + if (b == btHelp) { + openHelpWindow(HELP, 400, 300); + return; + } + + if (b == btStart) { + if (hasCurrentSequence() && (currentlyRunning == null)) { + btStart.setEnabled(false); + currentlyRunning = new Thread(() -> { + try { + final Sequence cs = getCurrentSequence(); + final Segmentation seg = doClustering(cs); + if (cbSendMaskDirectly.isSelected()) { + final MaskEditor me = MaskEditor.getRunningInstance(true); + currentlyRunning = null; + final Runnable r = () -> { + me.setSegmentationForSequence(cs, seg); + me.switchOpacityOn(); + btStart.setEnabled(true); + }; + SwingUtilities.invokeAndWait(r); + } + else { + final SwimmingObject result = new SwimmingObject(seg); + Icy.getMainInterface().getSwimmingPool().add(result); + currentlyRunning = null; + final Runnable r = () -> btStart.setEnabled(true); + SwingUtilities.invokeAndWait(r); + } + } + catch (final SupportRegionException | SegmentationException | InterruptedException | InvocationTargetException | MaskException | NumberFormatException | SignatureException e1) { + logError(e1.getClass().getName() + " : " + e1.getMessage()); + } + }); + currentlyRunning.start(); + } + } + + } + + /** + * Do single clustering. + * + * @param img the img + * @param regions the regions + * @param descriptor the descriptor + * @param algo the algo + * @return the segmentation + * @throws SegmentationException the segmentation exception + */ + private Segmentation doSingleClustering(final SegmentableIcyBufferedImage img, final IcySupportRegion[] regions, final DefaultDescriptorImpl<SegmentableIcyBufferedImage, ? extends Signature> descriptor, final DefaultClusteringAlgorithmImpl<VectorSignature> algo) throws SegmentationException { + final DefaultSegmentationAlgorithm<SegmentableIcyBufferedImage> segAlgo = new DefaultSegmentationAlgorithm<>(descriptor, algo); + segAlgo.setLogEnabled(isLogEnabled()); + + return segAlgo.segment(img, regions); + } + + /** + * Gets the some stats. + * + * @param seg the seg + * @return the some stats + */ + private void getSomeStats(final Segmentation seg) { + final DecimalFormat df = new DecimalFormat("0"); + Algorithm.out("id;label;h1;h2;h3"); + for (final Mask m : seg) { + final Color rgb = m.getColor(); + final double[] h1h2h3 = ColorSpaceTools.getColorComponentsD_0_255(ColorSpaceTools.RGB_TO_I1H2H3, rgb.getRed(), rgb.getGreen(), rgb.getBlue()); + log(m.getId() + ";" + m.getLabel() + ";" + df.format(h1h2h3[0]) + ";" + df.format(h1h2h3[1]) + ";" + df.format(h1h2h3[2])); + } + } + + /** + * Do clustering. + * + * @param currentSequence the current sequence + * @return the segmentation + * @throws SupportRegionException the support region exception + * @throws SegmentationException the segmentation exception + * @throws MaskException the mask exception + * @throws NumberFormatException the number format exception + * @throws SignatureException the signature exception + */ + private Segmentation doClustering(final Sequence currentSequence) throws SupportRegionException, SegmentationException, MaskException, NumberFormatException, SignatureException { + final Segmentation seg; + + seg = doClusteringKM(currentSequence); + seg.reInitColors(currentSequence.getImage(0, 0)); + if (isLogEnabled()) { + getSomeStats(seg); + } + + return seg; + } + + /** + * Do clustering km. + * + * @param currentSequence the current sequence + * @return the segmentation + * @throws SupportRegionException the support region exception + * @throws SegmentationException the segmentation exception + * @throws NumberFormatException the number format exception + */ + private Segmentation doClusteringKM(final Sequence currentSequence) throws SupportRegionException, SegmentationException, NumberFormatException { + final int nbc2 = Integer.parseInt(tfNbCluster2.getText()); + final int nbi2 = Integer.parseInt(tfNbIteration2.getText()); + final double stab2 = Double.parseDouble(tfStabCrit2.getText()); + final int cs = indexToColorspace.get(cbColorSpace.getSelectedIndex()); + + log("Working on " + ColorSpaceTools.COLOR_SPACES[cs]); + + final SegmentableIcyBufferedImage img = new SegmentableIcyBufferedImage(currentSequence.getFirstImage()); + + final KMeans km2 = new KMeans(nbc2, nbi2, stab2); + km2.setLogEnabled(isLogEnabled()); + + final Segmentation seg; + + final DefaultDescriptorImpl<SegmentableIcyBufferedImage, ? extends Signature> col; + + final ColorPixel cd = new ColorPixel(isLogEnabled()); + cd.setColorSpace(cs); + col = cd; + + col.setLogEnabled(isLogEnabled()); + + final GridFactory factory = new GridFactory(GridFactory.ALGO_ONLY_PIXELS); + factory.setLogEnabled(isLogEnabled()); + final List<IcySupportRegion> lRegions = factory.extractRegions(img); + final IcySupportRegion[] regions = new IcySupportRegion[lRegions.size()]; + int r = 0; + for (final IcySupportRegion sr : lRegions) { + regions[r++] = sr; + } + + seg = doSingleClustering(img, regions, col, km2); + + return seg; + } + + @Override + public Dimension getDefaultFrameDimension() { + return new Dimension(550, 300); + } }