package edu.stanford.rsl.apps.gui.blobdetection; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.JFrame; import javax.swing.JSpinner; import javax.swing.JTextPane; import javax.swing.SpinnerModel; import javax.swing.SpinnerNumberModel; import edu.stanford.rsl.conrad.utils.CONRAD; import edu.stanford.rsl.conrad.utils.XmlUtils; /** * This code was edited or generated using CloudGarden's Jigloo * SWT/Swing GUI Builder, which is free for non-commercial * use. If Jigloo is being used commercially (ie, by a corporation, * company or business for any purpose whatever) then you * should purchase a license for each developer using Jigloo. * Please visit www.cloudgarden.com for details. * Use of Jigloo implies acceptance of these licensing terms. * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR * THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED * LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE. */ public class MarkerDetection extends JFrame implements ActionListener, ChangeListener, DocumentListener { /** * */ private static final long serialVersionUID = -5274899502815414214L; private JButton jButtonRun; private MarkerDetectionWorker pWorker; private JSpinner jSpinnerGradientThreshold; private JTextPane jTextPane4; private JTextPane jTextPane3; private JTextPane jTextPane2; private JTextPane jTextPane1; private JTextPane jTextPaneBlobRadii; private JSpinner jSpinnerDistance; private JCheckBox jCheckBoxRefineAutoDetection; private JSpinner jSpinnerNumberOfBeadsToDetect; private JButton jButtonSaveResults; private JTextPane jTextPane6; private JSpinner jSpinnerNrOfIterations; private JCheckBox jCheckBoxAutomaticDetection; private JTextPane jTextPane5; private JSpinner jSpinnerCircularity; private JSpinner jSpinnerBinarizationThreshold; private boolean AutoDetectioncheckBoxChecked = false; private boolean RefinementcheckBoxChecked = false; public MarkerDetection () { initGUI(); pWorker = new MarkerDetectionWorker(); updateParameters(); } private void initGUI(){ { GridBagLayout thisLayout = new GridBagLayout(); thisLayout.rowWeights = new double[] {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}; thisLayout.rowHeights = new int[] {20, 7, 20, 20, 7, 7, 7}; thisLayout.columnWeights = new double[] {0.0, 0.1, 0.0, 0.0, 0.1, 0.1}; thisLayout.columnWidths = new int[] {154, 20, 185, 29, 20, 7}; getContentPane().setLayout(thisLayout); { jButtonRun = new JButton(); getContentPane().add(jButtonRun, new GridBagConstraints(4, 6, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jButtonRun.setText("Run Detection"); jButtonRun.addActionListener(this); } { SpinnerModel jSpinnerBinarizationThresholdModel = new SpinnerNumberModel(0.5, 0, 15, 0.1); jSpinnerBinarizationThreshold = new JSpinner(); getContentPane().add(jSpinnerBinarizationThreshold, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jSpinnerBinarizationThreshold.setModel(jSpinnerBinarizationThresholdModel); jSpinnerBinarizationThreshold.setPreferredSize(new java.awt.Dimension(61, 28)); jSpinnerBinarizationThreshold.addChangeListener(this); } { SpinnerModel jSpinnerGradientThresholdModel = new SpinnerNumberModel(0,0,1,0.01); jSpinnerGradientThreshold = new JSpinner(); getContentPane().add(jSpinnerGradientThreshold, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jSpinnerGradientThreshold.setModel(jSpinnerGradientThresholdModel); jSpinnerGradientThreshold.setPreferredSize(new java.awt.Dimension(61, 28)); jSpinnerGradientThreshold.addChangeListener(this); } { SpinnerModel jSpinnerCircularityModel = new SpinnerNumberModel(3,1,5,1); jSpinnerCircularity = new JSpinner(); getContentPane().add(jSpinnerCircularity, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jSpinnerCircularity.setModel(jSpinnerCircularityModel); jSpinnerCircularity.setPreferredSize(new java.awt.Dimension(61,28)); jSpinnerCircularity.addChangeListener(this); } { jTextPane1 = new JTextPane(); getContentPane().add(jTextPane1, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); jTextPane1.setText("Binarization Threshold"); } { jTextPane2 = new JTextPane(); getContentPane().add(jTextPane2, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); jTextPane2.setText("Low Gradient Threshold"); } { jTextPane3 = new JTextPane(); getContentPane().add(jTextPane3, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); jTextPane3.setText("Blob radii"); } { jTextPane4 = new JTextPane(); getContentPane().add(jTextPane4, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); jTextPane4.setText("Circularity Measure"); } { jTextPaneBlobRadii = new JTextPane(); getContentPane().add(jTextPaneBlobRadii, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jTextPaneBlobRadii.setText("[3.0]"); jTextPaneBlobRadii.setPreferredSize(new java.awt.Dimension(61,28)); jTextPaneBlobRadii.getDocument().addDocumentListener(this); } { jTextPane5 = new JTextPane(); getContentPane().add(jTextPane5, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); jTextPane5.setText("Distance to Reference"); } { SpinnerModel jSpinnerDistanceModel = new SpinnerNumberModel(15,1,200,10); jSpinnerDistance = new JSpinner(); getContentPane().add(jSpinnerDistance, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jSpinnerDistance.setModel(jSpinnerDistanceModel); jSpinnerDistance.setPreferredSize(new java.awt.Dimension(61, 28)); jSpinnerDistance.addChangeListener(this); } { jCheckBoxAutomaticDetection = new JCheckBox(); getContentPane().add(jCheckBoxAutomaticDetection, new GridBagConstraints(4, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); jCheckBoxAutomaticDetection.setText("Use Automatic Marker Detection"); jCheckBoxAutomaticDetection.addChangeListener(this); } { jCheckBoxRefineAutoDetection = new JCheckBox(); getContentPane().add(jCheckBoxRefineAutoDetection, new GridBagConstraints(4, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); jCheckBoxRefineAutoDetection.setText("Refine results / Set no. of beads"); jCheckBoxRefineAutoDetection.setVisible(false); jCheckBoxRefineAutoDetection.addChangeListener(this); } { SpinnerModel jSpinnerNumberOfBeadsModel = new SpinnerNumberModel(10,1,1000,1); jSpinnerNumberOfBeadsToDetect = new JSpinner(); getContentPane().add(jSpinnerNumberOfBeadsToDetect, new GridBagConstraints(5, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jSpinnerNumberOfBeadsToDetect.setModel(jSpinnerNumberOfBeadsModel); jSpinnerNumberOfBeadsToDetect.setPreferredSize(new java.awt.Dimension(61,28)); jSpinnerNumberOfBeadsToDetect.setEnabled(false); jSpinnerNumberOfBeadsToDetect.setVisible(false); jSpinnerNumberOfBeadsToDetect.addChangeListener(this); } { SpinnerModel jSpinnerNumberOfIterationsModel = new SpinnerNumberModel(1,1,250,1); jSpinnerNrOfIterations = new JSpinner(); getContentPane().add(jSpinnerNrOfIterations, new GridBagConstraints(1, 6, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jSpinnerNrOfIterations.setModel(jSpinnerNumberOfIterationsModel); jSpinnerNrOfIterations.setPreferredSize(new java.awt.Dimension(61,28)); jSpinnerNrOfIterations.addChangeListener(this); } { jTextPane6 = new JTextPane(); getContentPane().add(jTextPane6, new GridBagConstraints(0, 6, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jTextPane6.setText("No of Iterations"); } { jButtonSaveResults = new JButton(); getContentPane().add(jButtonSaveResults, new GridBagConstraints(4, 5, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jButtonSaveResults.setText("Save Results"); jButtonSaveResults.addActionListener(this); jButtonSaveResults.setVisible(false); } } { this.setSize(757, 386); } } @Override public void actionPerformed(ActionEvent arg0) { if (arg0.getSource().equals(jButtonRun)){ Thread test = new Thread(){ @Override public void run() { boolean[] wasEnabled = new boolean[getContentPane().getComponents().length]; for (int i = 0; i < getContentPane().getComponents().length; i++) { wasEnabled[i]=getContentPane().getComponents()[i].isEnabled(); getContentPane().getComponents()[i].setEnabled(false); } try { updateParameters(); // save states for (int j = 0; j < ((SpinnerNumberModel)jSpinnerNrOfIterations.getModel()).getNumber().intValue(); j++) { runDetection(); } jButtonSaveResults.setVisible(true); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } for (int i = 0; i < getContentPane().getComponents().length; i++) { if (wasEnabled[i]) getContentPane().getComponents()[i].setEnabled(true); } } }; test.start(); } if (arg0.getSource().equals(jButtonSaveResults)){ Thread test = new Thread(){ @Override public void run() { if (pWorker != null){ try { XmlUtils.exportToXML(pWorker.getMeasuredTwoDPoints()); XmlUtils.exportToXML(pWorker.getMergedTwoDPositions()); XmlUtils.exportToXML(pWorker.getReferenceThreeDPoints()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }; test.start(); } } @Override public void stateChanged(ChangeEvent arg0) { if (arg0.getSource().equals(jSpinnerBinarizationThreshold) || arg0.getSource().equals(jSpinnerGradientThreshold) || arg0.getSource().equals(jTextPaneBlobRadii) || arg0.getSource().equals(jSpinnerCircularity) || arg0.getSource().equals(jSpinnerNumberOfBeadsToDetect) || arg0.getSource().equals(jSpinnerNrOfIterations)){ Thread test = new Thread(){ @Override public void run() { updateParameters(); } }; test.start(); } if (arg0.getSource().equals(jCheckBoxAutomaticDetection)){ if (AutoDetectioncheckBoxChecked != jCheckBoxAutomaticDetection.isSelected()){ AutoDetectioncheckBoxChecked = jCheckBoxAutomaticDetection.isSelected(); if (AutoDetectioncheckBoxChecked){ pWorker = new AutomaticMarkerDetectionWorker(); jCheckBoxRefineAutoDetection.setVisible(true); jSpinnerNumberOfBeadsToDetect.setVisible(true); } else{ pWorker = new MarkerDetectionWorker(); jCheckBoxRefineAutoDetection.setVisible(false); jSpinnerNumberOfBeadsToDetect.setVisible(false); } jButtonSaveResults.setVisible(false); } } if (arg0.getSource().equals(jCheckBoxRefineAutoDetection)){ if (RefinementcheckBoxChecked != jCheckBoxRefineAutoDetection.isSelected()){ RefinementcheckBoxChecked = jCheckBoxRefineAutoDetection.isSelected(); if (RefinementcheckBoxChecked){ pWorker = new AutomaticMarkerDetectionWorker(); jSpinnerNumberOfBeadsToDetect.setEnabled(true); } else{ jSpinnerNumberOfBeadsToDetect.setEnabled(false); } updateParameters(); } } } private void updateParameters(){ if (pWorker instanceof AutomaticMarkerDetectionWorker){ ((AutomaticMarkerDetectionWorker)pWorker).setParameters(((SpinnerNumberModel)jSpinnerBinarizationThreshold.getModel()).getNumber().doubleValue(), ((SpinnerNumberModel)jSpinnerCircularity.getModel()).getNumber().doubleValue(), ((SpinnerNumberModel)jSpinnerGradientThreshold.getModel()).getNumber().doubleValue(), ((SpinnerNumberModel)jSpinnerDistance.getModel()).getNumber().doubleValue(), jTextPaneBlobRadii.getText(), RefinementcheckBoxChecked, ((SpinnerNumberModel)jSpinnerNumberOfBeadsToDetect.getModel()).getNumber().intValue()); } else{ pWorker.setParameters(((SpinnerNumberModel)jSpinnerBinarizationThreshold.getModel()).getNumber().doubleValue(), ((SpinnerNumberModel)jSpinnerCircularity.getModel()).getNumber().doubleValue(), ((SpinnerNumberModel)jSpinnerGradientThreshold.getModel()).getNumber().doubleValue(), ((SpinnerNumberModel)jSpinnerDistance.getModel()).getNumber().doubleValue(), jTextPaneBlobRadii.getText()); } } private void runDetection(){ pWorker.run(); } @Override public void changedUpdate(DocumentEvent arg0) { Thread test = new Thread(){ @Override public void run() { updateParameters(); } }; test.start(); } @Override public void insertUpdate(DocumentEvent arg0) { Thread test = new Thread(){ @Override public void run() { updateParameters(); } }; test.start(); } @Override public void removeUpdate(DocumentEvent arg0) { Thread test = new Thread(){ @Override public void run() { updateParameters(); } }; test.start(); } /** * @param args */ public static void main(String[] args) { CONRAD.setup(); MarkerDetection md = new MarkerDetection(); md.setVisible(true); //Opener op = new Opener(); //op.openImage("C:\\Users\\berger\\Desktop\\Result of WEIGHT-BEARING.XA._.9.Standing_Straight_2Legs244LbsTotal_248views_70kV_0.54uGy-2.tif").show("Result of WEIGHT-BEARING.XA._.9.Standing_Straight_2Legs244LbsTotal_248views_70kV_0.54uGy-2.tif"); //op.openImage("D:\\Data\\WeightBearing\\stanford_knee_data_jang_2013_07_08\\Weight-bearing_NO6_IR1\\Projection\\AfterPreCorrection\\WEIGHT-BEARING.XA._.9.Standing_Straight_2Legs244LbsTotal_248views_70kV_0.54uGy.tif").show(); } } /* * Copyright (C) 2010-2014 - Martin Berger * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */