1
2
3
4 package de.desy.acop.video;
5
6 import java.awt.BorderLayout;
7 import java.awt.Color;
8 import java.awt.Dimension;
9 import java.awt.Font;
10 import java.awt.GridBagConstraints;
11 import java.awt.GridBagLayout;
12 import java.awt.Insets;
13 import java.awt.Rectangle;
14 import java.awt.event.ActionEvent;
15 import java.awt.event.ActionListener;
16 import java.awt.event.ItemEvent;
17 import java.awt.event.ItemListener;
18 import java.awt.image.BufferedImage;
19 import java.beans.Customizer;
20 import java.beans.PropertyChangeEvent;
21 import java.beans.PropertyChangeListener;
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.Arrays;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.concurrent.Executor;
28 import java.util.concurrent.Executors;
29
30 import javax.imageio.ImageIO;
31 import javax.swing.ImageIcon;
32 import javax.swing.JButton;
33 import javax.swing.JCheckBox;
34 import javax.swing.JComboBox;
35 import javax.swing.JFileChooser;
36 import javax.swing.JLabel;
37 import javax.swing.JPanel;
38 import javax.swing.JTabbedPane;
39 import javax.swing.JTable;
40 import javax.swing.SwingConstants;
41 import javax.swing.SwingUtilities;
42 import javax.swing.border.LineBorder;
43 import javax.swing.border.TitledBorder;
44 import javax.swing.filechooser.FileFilter;
45 import javax.swing.table.DefaultTableModel;
46
47 import com.cosylab.gui.IconCustomizer;
48 import com.cosylab.gui.components.NumberField;
49 import com.cosylab.gui.components.util.RunnerHelper;
50
51 import de.desy.acop.video.analysis.AImage;
52 import de.desy.acop.video.analysis.AnalysisMode;
53 import de.desy.acop.video.analysis.ImageAnalysisEngine;
54 import de.desy.acop.video.timageio.TImageIO;
55 import de.desy.tine.types.IMAGE;
56 import de.desy.tine.types.IMAGE.FrameHeader;
57
58
59
60
61
62
63
64
65 public class AnalysisCustomizer extends JPanel implements Customizer {
66
67 private class ServerSettingsModel extends DefaultTableModel {
68 private static final long serialVersionUID = 1L;
69 private AImage image;
70 public void setAImage(AImage image) {
71 this.image = image;
72 fireTableDataChanged();
73 }
74 public Class<?> getColumnClass(int columnIndex) {
75 return String.class;
76 }
77 public int getColumnCount() {
78 return 2;
79 }
80 public int getRowCount() {
81 return 11;
82 }
83 public boolean isCellEditable(int row, int column) {
84 return false;
85 }
86 public String getColumnName(int column) {
87 switch (column) {
88 case 0 : return "Parameter";
89 case 1 : return "Value";
90 default : return null;
91 }
92 }
93 public Object getValueAt(int row, int column) {
94 if (column == 0) {
95 switch (row) {
96 case 0 : return "ROI X";
97 case 1 : return "ROI Y";
98 case 2 : return "ROI W";
99 case 3 : return "ROI H";
100 case 4 : return "Threshold ROI X";
101 case 5 : return "Threshold ROI Y";
102 case 6 : return "Threshold ROI W";
103 case 7 : return "Threshold ROI H";
104 case 8 : return "Threshold";
105 case 9 : return "Calculate Threshold";
106 case 10 : return "Perform Fit";
107 }
108 } else if (column == 1 && image != null) {
109 switch (row) {
110 case 0 : return image.getRoiX();
111 case 1 : return image.getRoiY();
112 case 2 : return image.getRoiW();
113 case 3 : return image.getRoiH();
114 case 4 : return image.getRoi2X();
115 case 5 : return image.getRoi2Y();
116 case 6 : return image.getRoi2W();
117 case 7 : return image.getRoi2H();
118 case 8 : return image.getThreshold();
119 case 9 : return image.isCalculateThreshold();
120 case 10 : return image.isPerformFit();
121 }
122 }
123 return null;
124 }
125 }
126
127 private static final long serialVersionUID = 1L;
128 private static final String NO_BACKGROUND = "No Background";
129 private static final String INVALID_BACKGROUND = "Invalid Background";
130 private static final String VIDEO_BACKGROUND = "from video";
131 private static final int PREVIEW_DIMENSION = 100;
132 private static final Dimension FIELD_DIMENSION = new Dimension(80,21);
133 private static final Dimension LABEL_DIMENSION = new Dimension(200,25);
134 private static final String[] FILE_TYPES = new String[] {"jpg", "jpeg", "png"};
135
136 private Executor executor;
137 private AcopVideo acopVideo;
138
139 private JComboBox analysisModeCombo;
140 private JButton applyToServerButton;
141 private JButton synchronizeButton;
142 private NumberField thresholdField;
143 private NumberField roiXField;
144 private NumberField roiYField;
145 private NumberField roiWField;
146 private NumberField roiHField;
147 private NumberField roi2XField;
148 private NumberField roi2YField;
149 private NumberField roi2WField;
150 private NumberField roi2HField;
151 private JCheckBox calculateThresholdCheckBox;
152 private JCheckBox useThresholdCheckBox;
153 private JLabel numberOfPixelsLabel;
154 private JButton allButton;
155 private JButton allThresholdButton;
156 private JButton duplicateThresholdButton;
157 private JButton currentButton;
158 private JButton saveButton;
159 private JButton noneButton;
160 private JButton browseButton;
161 private JLabel backgroundLabel;
162 private JLabel fileNameLabel;
163 private JFileChooser fileChooser;
164 private JCheckBox displayNumericalValuesBox;
165 private JCheckBox performFitCheckBox;
166 private JCheckBox performSmoothCheckBox;
167 private JCheckBox displayStatisticsCheckBox;
168
169 private JTabbedPane tabPane;
170 private JPanel analysisPanel;
171 private JPanel backgroundPanel;
172 private JPanel thresholdPanel;
173 private JPanel serverSettingsPanel;
174 private ServerSettingsModel serverModel;
175
176 private File backgroundFile;
177 private double[] preciseBackground;
178 private int preciseBackgroundWidth;
179 private IMAGE backgroundImage;
180 private boolean localChanges = false;
181 private String fileName;
182 private int roiX;
183 private int roiY;
184 private int roiW;
185 private int roiH;
186 private int roi2X;
187 private int roi2Y;
188 private int roi2W;
189 private int roi2H;
190 private int imageW;
191 private int imageH;
192 private double threshold;
193 private int thresholdPoints;
194 private boolean calculateThreshold;
195 private boolean performFit;
196 private boolean performSmoothing;
197
198 private boolean appliedToServer = true;
199 private boolean suppressChanges = false;
200 private double lastThreshold = 0;
201
202 private Font plainFont;
203 private Font boldFont;
204 private Font labelPlainFont;
205 private Font labelBoldFont;
206
207 private static final String PIXELS_USED = "Pixels Used: ";
208
209
210
211
212
213
214
215 @Override
216 public void setObject(Object bean) {
217 if (!(bean instanceof AcopVideo)) {
218 throw new IllegalArgumentException("Only AcopVideo can use this Customizer.");
219 }
220 acopVideo = (AcopVideo) bean;
221
222 AnalysisMode am = acopVideo.getAnalysisMode();
223 if (am == AnalysisMode.REMOTE_ANALYSIS) fileName = VIDEO_BACKGROUND;
224 else fileName = NO_BACKGROUND;
225 getAnalysisModeCombo().setSelectedItem(am);
226 getDisplayNumericalValuesBox().setSelected(acopVideo.isDisplayNumericalValues());
227
228 AImage ai = acopVideo.getAImage();
229 if (ai != null) {
230 updateAnalysisData(ai);
231 } else {
232 resetData();
233 }
234 updateBackground();
235 acopVideo.addPropertyChangeListener(new PropertyChangeListener() {
236 @Override
237 public void propertyChange(final PropertyChangeEvent evt) {
238 SwingUtilities.invokeLater(new Runnable() {
239 public void run() {
240 if (evt.getPropertyName() == AcopVideo.PROPERTY_AIMAGE) {
241 AImage ai = (AImage) evt.getNewValue();
242 if (ai != null) {
243 updateAnalysisData(ai);
244 } else {
245 resetData();
246 }
247 } else if (evt.getPropertyName().equals(AcopVideo.DISPLAY_STATISTISC)) {
248 getDisplayStatisticsCheckBox().setSelected(acopVideo.isDisplayStatistics());
249 }
250
251 }
252 });
253
254 }
255 });
256 getDisplayStatisticsCheckBox().setSelected(acopVideo.isDisplayStatistics());
257 acopVideo.getImageAnalysisEngine().addPropertyChangeListener(ImageAnalysisEngine.PROPERTY_PRECISE_BACKGROUND, new PropertyChangeListener() {
258 @Override
259 public void propertyChange(PropertyChangeEvent evt) {
260 updateBackground();
261 }
262 });
263 acopVideo.getDisplayerManager().addPropertyChangeListener(DisplayerManager.PROPERTY_ON_SCREEN_ROI, new PropertyChangeListener() {
264 @Override
265 public void propertyChange(PropertyChangeEvent evt) {
266 Rectangle r = (Rectangle) evt.getNewValue();
267 updateData(true, imageW, imageH, r.x, r.y, r.width, r.height, roi2X, roi2Y, roi2W, roi2H, threshold,thresholdPoints,calculateThreshold, performFit,performSmoothing);
268 }
269 });
270 }
271
272 public AnalysisCustomizer() {
273 initialize();
274 }
275
276 private void initialize() {
277 setLayout(new GridBagLayout());
278
279 add(getAnalysisModeCombo(), new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(11,11,2,11),0,0));
280
281 JPanel parametersPanel = new JPanel(new GridBagLayout());
282 parametersPanel.setBorder(new TitledBorder("Analysis Parameters"));
283 parametersPanel.add(getTabPane(),new GridBagConstraints(0,0,2,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(2,2,2,2),0,0));
284 parametersPanel.add(new JLabel("Synchronize With Server:"), new GridBagConstraints(0,14,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
285 JPanel p = new JPanel(new GridBagLayout());
286 p.add(getApplyToServerButton(), new GridBagConstraints(0,15,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
287 p.add(getSynchronizeButton(), new GridBagConstraints(1,15,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
288 parametersPanel.add(p, new GridBagConstraints(0,15,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0));
289
290 add(parametersPanel, new GridBagConstraints(0,3,1,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(4,11,4,11),0,0));
291
292 add(getDisplayNumericalValuesBox(), new GridBagConstraints(0,4,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.HORIZONTAL,new Insets(2,11,11,11),0,0));
293 }
294
295 private JTabbedPane getTabPane() {
296 if (tabPane == null) {
297 tabPane = new JTabbedPane();
298 tabPane.add("Parameters", getAnalysisPanel());
299 tabPane.add("Background", getBackgroundPanel());
300 tabPane.add("Threshold", getThresholdPanel());
301 tabPane.add("Applied Settings", getServerSettingsPanel());
302 }
303 return tabPane;
304 }
305
306 private JPanel getServerSettingsPanel() {
307 if (serverSettingsPanel == null) {
308 serverSettingsPanel = new JPanel(new BorderLayout());
309 JTable table = new JTable(getServerModel());
310 serverSettingsPanel.add(table.getTableHeader(), BorderLayout.NORTH);
311 serverSettingsPanel.add(table, BorderLayout.CENTER);
312 table.setMinimumSize(new Dimension(0,0));
313 serverSettingsPanel.setMinimumSize(new Dimension(0,0));
314 }
315 return serverSettingsPanel;
316 }
317
318 private ServerSettingsModel getServerModel() {
319 if (serverModel == null) {
320 serverModel = new ServerSettingsModel();
321 }
322 return serverModel;
323 }
324
325 private JPanel getAnalysisPanel() {
326 if (analysisPanel == null) {
327 analysisPanel = new JPanel(new GridBagLayout());
328 analysisPanel.add(getDisplayStatisticsCheckBox(), new GridBagConstraints(0,0,1,1,0,1,GridBagConstraints.EAST,GridBagConstraints.NONE,new Insets(5,5,2,2),0,0));
329 analysisPanel.add(getPerformFitCheckBox(), new GridBagConstraints(1,0,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(5,2,2,5),0,0));
330 analysisPanel.add(getPerformSmoothCheckBox(), new GridBagConstraints(0,2,2,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(5,5,2,5),0,0));
331
332 analysisPanel.add(new JLabel("Region of Interest Parameters [pixels]:"), new GridBagConstraints(0,3,2,1,0,1,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(2,5,2,10),0,0));
333
334 analysisPanel.add(new JLabel("Start X:"), new GridBagConstraints(0,4,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,5,2,2),0,0));
335 analysisPanel.add(getRoiXField(), new GridBagConstraints(1,4,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
336 analysisPanel.add(new JLabel("Start Y:"), new GridBagConstraints(0,5,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,5,2,2),0,0));
337 analysisPanel.add(getRoiYField(), new GridBagConstraints(1,5,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
338 analysisPanel.add(new JLabel("Width:"), new GridBagConstraints(0,6,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,5,2,2),0,0));
339 analysisPanel.add(getRoiWField(), new GridBagConstraints(1,6,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
340 analysisPanel.add(new JLabel("Height:"), new GridBagConstraints(0,7,1,1,0,1,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,new Insets(2,5,2,2),0,0));
341 analysisPanel.add(getRoiHField(), new GridBagConstraints(1,7,1,1,0,1,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
342 analysisPanel.add(getAllButton(), new GridBagConstraints(0,8,2,1,0,1,GridBagConstraints.NORTH,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
343 }
344 return analysisPanel;
345 }
346
347 private JPanel getThresholdPanel() {
348 if (thresholdPanel == null) {
349 thresholdPanel = new JPanel(new GridBagLayout());
350 JPanel p1 = new JPanel(new GridBagLayout());
351 p1.add(new JLabel("Threshold:"), new GridBagConstraints(2,0,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(5,2,2,5),0,0));
352 p1.add(getThresholdField(), new GridBagConstraints(3,0,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(5,2,2,5),0,0));
353 p1.add(getUseTresholdCheckBox(), new GridBagConstraints(2,1,2,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,0,5),0,0));
354 p1.add(getCalculateTresholdCheckBox(), new GridBagConstraints(2,2,2,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,0,5),0,0));
355 p1.add(getNumberOfPixelsLabel(), new GridBagConstraints(2,3,2,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,23,4,5),0,0));
356 p1.add(new JLabel("Threshold Calculation Region [pixels]:"), new GridBagConstraints(2,4,2,1,0,1,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(2,2,2,5),0,0));
357 p1.add(new JLabel("Start X:"), new GridBagConstraints(2,5,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
358 p1.add(getRoi2XField(), new GridBagConstraints(3,5,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,5),0,0));
359 p1.add(new JLabel("Start Y:"), new GridBagConstraints(2,6,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
360 p1.add(getRoi2YField(), new GridBagConstraints(3,6,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,5),0,0));
361 p1.add(new JLabel("Width:"), new GridBagConstraints(2,7,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
362 p1.add(getRoi2WField(), new GridBagConstraints(3,7,1,1,0,1,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(2,2,2,5),0,0));
363 p1.add(new JLabel("Height:"), new GridBagConstraints(2,8,1,1,0,1,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
364 p1.add(getRoi2HField(), new GridBagConstraints(3,8,1,1,0,1,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,new Insets(2,2,2,5),0,0));
365
366 JPanel p = new JPanel(new GridBagLayout());
367
368 p.add(getAllThresholdButton(), new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.NORTHEAST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
369 p.add(getDuplicateThresholdButton(), new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
370 thresholdPanel.add(p1, new GridBagConstraints(0,0,1,1,0,1,GridBagConstraints.NORTH,GridBagConstraints.BOTH,new Insets(2,2,2,2),0,0));
371 thresholdPanel.add(p, new GridBagConstraints(0,1,1,1,0,0,GridBagConstraints.NORTH,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388 }
389 return thresholdPanel;
390 }
391
392 private JLabel getNumberOfPixelsLabel() {
393 if (numberOfPixelsLabel == null) {
394 numberOfPixelsLabel = new JLabel(PIXELS_USED + (0));
395 }
396 return numberOfPixelsLabel;
397 }
398
399 private JPanel getBackgroundPanel() {
400 if (backgroundPanel == null) {
401 backgroundPanel = new JPanel(new GridBagLayout());
402 backgroundPanel.add(new JLabel("Background Image:"), new GridBagConstraints(0,8,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(4,4,4,4),0,0));
403 backgroundPanel.add(getFileNameLabel(), new GridBagConstraints(0,9,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.HORIZONTAL,new Insets(4,4,8,4),0,0));
404 backgroundPanel.add(getBackgroundLabel(), new GridBagConstraints(0,10,1,4,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(4,4,4,4),0,0));
405 backgroundPanel.add(getCurrentButton(), new GridBagConstraints(1,10,1,1,0,0,GridBagConstraints.NORTH,GridBagConstraints.HORIZONTAL,new Insets(4,4,4,4),0,0));
406 backgroundPanel.add(getNoneButton(), new GridBagConstraints(1,11,1,1,0,0,GridBagConstraints.NORTH,GridBagConstraints.HORIZONTAL,new Insets(4,4,4,4),0,0));
407 backgroundPanel.add(getBrowseButton(), new GridBagConstraints(1,12,1,1,0,0,GridBagConstraints.NORTH,GridBagConstraints.HORIZONTAL,new Insets(4,4,4,4),0,0));
408 backgroundPanel.add(getSaveButton(), new GridBagConstraints(1,13,1,1,0,1,GridBagConstraints.NORTH,GridBagConstraints.HORIZONTAL,new Insets(4,4,4,4),0,0));
409 }
410 return backgroundPanel;
411 }
412
413 private JComboBox getAnalysisModeCombo() {
414 if (analysisModeCombo == null) {
415 analysisModeCombo = new JComboBox(AnalysisMode.values());
416 analysisModeCombo.addActionListener(new ActionListener() {
417 @Override
418 public void actionPerformed(ActionEvent e) {
419 AnalysisMode mode = (AnalysisMode) analysisModeCombo.getSelectedItem();
420 setAnalysisMode(mode);
421
422 if (mode == AnalysisMode.LOCAL_ANALYSIS) {
423 if (backgroundFile != null)
424 updateFileNameLabel(backgroundFile.getAbsolutePath());
425 else if (fileName == VIDEO_BACKGROUND) updateFileNameLabel(VIDEO_BACKGROUND);
426 else updateFileNameLabel(NO_BACKGROUND);
427 }
428 else if (mode == AnalysisMode.REMOTE_ANALYSIS) updateFileNameLabel(VIDEO_BACKGROUND);
429 else updateFileNameLabel(NO_BACKGROUND);
430 }
431 });
432 }
433 return analysisModeCombo;
434 }
435
436 private JButton getApplyToServerButton() {
437 if (applyToServerButton == null) {
438 applyToServerButton = new JButton("Apply");
439 applyToServerButton.setToolTipText("Apply Parameters to Server");
440 applyToServerButton.setEnabled(false);
441 applyToServerButton.addActionListener(new ActionListener() {
442 @Override
443 public void actionPerformed(ActionEvent e) {
444 applyToServer();
445 }
446 });
447 }
448 return applyToServerButton;
449 }
450
451 private JButton getSynchronizeButton() {
452 if (synchronizeButton == null) {
453 synchronizeButton = new JButton("Reload");
454 synchronizeButton.setToolTipText("Reload Parameters from Server");
455 synchronizeButton.setEnabled(false);
456 synchronizeButton.addActionListener(new ActionListener() {
457 @Override
458 public void actionPerformed(ActionEvent e) {
459 appliedToServer = true;
460 updateData(true, imageW, imageH, roiX, roiY, roiW, roiH, roi2X, roi2Y, roi2W, roi2H, threshold, thresholdPoints, calculateThreshold, performFit,performSmoothing);
461 }
462 });
463 }
464
465 return synchronizeButton;
466 }
467
468 private NumberField getThresholdField() {
469 if (thresholdField == null) {
470 thresholdField = new NumberField();
471 thresholdField.setNumberType(Double.class);
472 thresholdField.setFormat("%3.2f");
473 thresholdField.setPreferredSize(FIELD_DIMENSION);
474 thresholdField.setMinimumSize(FIELD_DIMENSION);
475 thresholdField.setMaximumSize(FIELD_DIMENSION);
476 thresholdField.addPropertyChangeListener("value", new PropertyChangeListener() {
477 @Override
478 public void propertyChange(PropertyChangeEvent evt) {
479 if (suppressChanges) return;
480 final double value = (Double) evt.getNewValue();
481 if (!Double.isNaN(value)) lastThreshold = value;
482 if (threshold == value) {
483 if (localChanges) thresholdField.setFont(getPlainFont());
484 return;
485 }
486 if (!localChanges) {
487 acopVideo.getImageAnalysisEngine().setThreshold(value);
488 }
489 else {
490 thresholdField.setFont(getBoldFont());
491 appliedToServer = false;
492 }
493 }
494 });
495 suppressChanges = true;
496 thresholdField.setValue(Double.NaN);
497 suppressChanges = false;
498 }
499 return thresholdField;
500 }
501
502 private JCheckBox getCalculateTresholdCheckBox() {
503 if (calculateThresholdCheckBox == null) {
504 calculateThresholdCheckBox = new JCheckBox("Automatic Threshold Calculation");
505 calculateThresholdCheckBox.setToolTipText("Automatic Threshold Calculation (Average Pixel Value in [Threshold ROI - ROI])");
506 calculateThresholdCheckBox.addItemListener(new ItemListener() {
507 public void itemStateChanged(ItemEvent e) {
508 if (suppressChanges) return;
509 boolean value = e.getStateChange() == ItemEvent.SELECTED;
510 if (!localChanges) {
511 acopVideo.getImageAnalysisEngine().setCalculateThreshold(value);
512 } else {
513 calculateThresholdCheckBox.setFont(getLabelBoldFont());
514 appliedToServer = false;
515 }
516 getThresholdField().setEditable(!value && getUseTresholdCheckBox().isSelected());
517 getUseTresholdCheckBox().setEnabled(!value);
518 }
519 });
520 }
521 return calculateThresholdCheckBox;
522 }
523
524 private JCheckBox getUseTresholdCheckBox() {
525 if (useThresholdCheckBox == null) {
526 useThresholdCheckBox = new JCheckBox("Apply Threshold");
527 useThresholdCheckBox.setToolTipText("Select Whether Set Threshold is Used in Calculation or Not");
528 useThresholdCheckBox.addItemListener(new ItemListener() {
529 public void itemStateChanged(ItemEvent e) {
530 if (suppressChanges) return;
531 boolean value = e.getStateChange() == ItemEvent.SELECTED;
532 if (value) {
533 acopVideo.getImageAnalysisEngine().setThreshold(lastThreshold);
534 } else {
535 acopVideo.getImageAnalysisEngine().setThreshold(Double.NaN);
536 }
537 getThresholdField().setEditable(!value);
538 }
539 });
540 useThresholdCheckBox.setEnabled(getCalculateTresholdCheckBox().isSelected());
541 }
542 return useThresholdCheckBox;
543 }
544
545
546
547 private JCheckBox getPerformFitCheckBox() {
548 if (performFitCheckBox == null) {
549 performFitCheckBox = new JCheckBox("Perform Fitting");
550 performFitCheckBox.setToolTipText("Perform Exponential + Linear Function Fit on Side View Data");
551 performFitCheckBox.addItemListener(new ItemListener() {
552 public void itemStateChanged(ItemEvent e) {
553 if (suppressChanges) return;
554 boolean value = e.getStateChange() == ItemEvent.SELECTED;
555 if (!localChanges) {
556 acopVideo.getImageAnalysisEngine().setPerformFit(value);
557 } else {
558 performFitCheckBox.setFont(getLabelBoldFont());
559 appliedToServer = false;
560 }
561 }
562 });
563 }
564 return performFitCheckBox;
565 }
566
567 private JCheckBox getPerformSmoothCheckBox() {
568 if (performSmoothCheckBox == null) {
569 performSmoothCheckBox = new JCheckBox("Perform Smoothing");
570 performSmoothCheckBox.setToolTipText("Smooth Side View Data by Averaging Values With Neighbours");
571 performSmoothCheckBox.addItemListener(new ItemListener() {
572 public void itemStateChanged(ItemEvent e) {
573 if (suppressChanges) return;
574 boolean value = e.getStateChange() == ItemEvent.SELECTED;
575 if (!localChanges) {
576 acopVideo.getImageAnalysisEngine().setPerformSmoothing(value);
577 } else {
578 performSmoothCheckBox.setFont(getLabelBoldFont());
579 appliedToServer = false;
580 }
581 }
582 });
583 }
584 return performSmoothCheckBox;
585 }
586
587 private JCheckBox getDisplayStatisticsCheckBox() {
588 if (displayStatisticsCheckBox == null) {
589 displayStatisticsCheckBox = new JCheckBox("Display Statisics");
590 displayStatisticsCheckBox.setToolTipText("Display Statistical Analysis Results");
591 displayStatisticsCheckBox.addItemListener(new ItemListener() {
592 public void itemStateChanged(ItemEvent e) {
593 if (suppressChanges) return;
594 boolean value = e.getStateChange() == ItemEvent.SELECTED;
595 acopVideo.setDisplayStatistics(value);
596 }
597 });
598 }
599 return displayStatisticsCheckBox;
600 }
601
602 private NumberField getRoiXField() {
603 if (roiXField == null) {
604 roiXField = new NumberField();
605 roiXField.setNumberType(Integer.class);
606 roiXField.setFormat("%d");
607 roiXField.setPreferredSize(FIELD_DIMENSION);
608 roiXField.setMinimumSize(FIELD_DIMENSION);
609 roiXField.setMaximumSize(FIELD_DIMENSION);
610 roiXField.setMinimum(0);
611 roiXField.addPropertyChangeListener("value", new PropertyChangeListener() {
612 @Override
613 public void propertyChange(PropertyChangeEvent evt) {
614 if (suppressChanges) return;
615 int value = ((Number) evt.getNewValue()).intValue();
616 if (roiX == value) {
617 if (localChanges) roiXField.setFont(getPlainFont());
618 return;
619 }
620 if (!localChanges) {
621 roiX = value;
622 setData();
623 }
624 else {
625 roiXField.setFont(getBoldFont());
626 appliedToServer = false;
627 }
628 }
629 });
630 }
631 return roiXField;
632 }
633
634 private NumberField getRoiYField() {
635 if (roiYField == null) {
636 roiYField = new NumberField();
637 roiYField.setNumberType(Integer.class);
638 roiYField.setFormat("%d");
639 roiYField.setPreferredSize(FIELD_DIMENSION);
640 roiYField.setMinimumSize(FIELD_DIMENSION);
641 roiYField.setMaximumSize(FIELD_DIMENSION);
642 roiYField.setMinimum(0);
643 roiYField.addPropertyChangeListener("value", new PropertyChangeListener() {
644 @Override
645 public void propertyChange(PropertyChangeEvent evt) {
646 if (suppressChanges) return;
647 int value = ((Number) evt.getNewValue()).intValue();
648 if (roiY == value) {
649 if (localChanges) roiYField.setFont(getPlainFont());
650 return;
651 }
652 if (!localChanges) {
653 roiY = value;
654 setData();
655 }
656 else {
657 roiYField.setFont(getBoldFont());
658 appliedToServer = false;
659 }
660 }
661 });
662 }
663 return roiYField;
664 }
665
666 private NumberField getRoiWField() {
667 if (roiWField == null) {
668 roiWField = new NumberField();
669 roiWField.setNumberType(Integer.class);
670 roiWField.setFormat("%d");
671 roiWField.setPreferredSize(FIELD_DIMENSION);
672 roiWField.setMinimumSize(FIELD_DIMENSION);
673 roiWField.setMaximumSize(FIELD_DIMENSION);
674 roiWField.setMinimum(0);
675 roiWField.addPropertyChangeListener("value", new PropertyChangeListener() {
676 @Override
677 public void propertyChange(PropertyChangeEvent evt) {
678 if (suppressChanges) return;
679 int value = ((Number) evt.getNewValue()).intValue();
680 if (roiW == value) {
681 if (localChanges) roiWField.setFont(getPlainFont());
682 return;
683 }
684 if (!localChanges) {
685 roiW = value;
686 setData();
687 }
688 else {
689 roiWField.setFont(getBoldFont());
690 appliedToServer = false;
691 }
692 }
693 });
694 }
695 return roiWField;
696 }
697
698 private NumberField getRoiHField() {
699 if (roiHField == null) {
700 roiHField = new NumberField();
701 roiHField.setNumberType(Integer.class);
702 roiHField.setFormat("%d");
703 roiHField.setPreferredSize(FIELD_DIMENSION);
704 roiHField.setMinimumSize(FIELD_DIMENSION);
705 roiHField.setMaximumSize(FIELD_DIMENSION);
706 roiHField.setMinimum(0);
707 roiHField.addPropertyChangeListener("value", new PropertyChangeListener() {
708 @Override
709 public void propertyChange(PropertyChangeEvent evt) {
710 if (suppressChanges) return;
711 int value = ((Number) evt.getNewValue()).intValue();
712 if (roiH == value) {
713 if (localChanges) roiHField.setFont(getPlainFont());
714 return;
715 }
716 if (!localChanges) {
717 roiH = value;
718 setData();
719 }
720 else {
721 roiHField.setFont(getBoldFont());
722 appliedToServer = false;
723 }
724
725 }
726 });
727 }
728 return roiHField;
729 }
730
731
732 private NumberField getRoi2XField() {
733 if (roi2XField == null) {
734 roi2XField = new NumberField();
735 roi2XField.setNumberType(Integer.class);
736 roi2XField.setFormat("%d");
737 roi2XField.setPreferredSize(FIELD_DIMENSION);
738 roi2XField.setMinimumSize(FIELD_DIMENSION);
739 roi2XField.setMaximumSize(FIELD_DIMENSION);
740 roi2XField.setMinimum(0);
741 roi2XField.addPropertyChangeListener("value", new PropertyChangeListener() {
742 @Override
743 public void propertyChange(PropertyChangeEvent evt) {
744 if (suppressChanges) return;
745 int value = ((Number) evt.getNewValue()).intValue();
746 if (roi2X == value) {
747 if (localChanges) roi2XField.setFont(getPlainFont());
748 return;
749 }
750 if (!localChanges) {
751 roi2X = value;
752 setData2();
753 }
754 else {
755 roi2XField.setFont(getBoldFont());
756 appliedToServer = false;
757 }
758 }
759 });
760 }
761 return roi2XField;
762 }
763
764 private NumberField getRoi2YField() {
765 if (roi2YField == null) {
766 roi2YField = new NumberField();
767 roi2YField.setNumberType(Integer.class);
768 roi2YField.setFormat("%d");
769 roi2YField.setPreferredSize(FIELD_DIMENSION);
770 roi2YField.setMinimumSize(FIELD_DIMENSION);
771 roi2YField.setMaximumSize(FIELD_DIMENSION);
772 roi2YField.setMinimum(0);
773 roi2YField.addPropertyChangeListener("value", new PropertyChangeListener() {
774 @Override
775 public void propertyChange(PropertyChangeEvent evt) {
776 if (suppressChanges) return;
777 int value = ((Number) evt.getNewValue()).intValue();
778 if (roi2Y == value) {
779 if (localChanges) roi2YField.setFont(getPlainFont());
780 return;
781 }
782 if (!localChanges) {
783 roi2Y = value;
784 setData2();
785 }
786 else {
787 roi2YField.setFont(getBoldFont());
788 appliedToServer = false;
789 }
790 }
791 });
792 }
793 return roi2YField;
794 }
795
796 private NumberField getRoi2WField() {
797 if (roi2WField == null) {
798 roi2WField = new NumberField();
799 roi2WField.setNumberType(Integer.class);
800 roi2WField.setFormat("%d");
801 roi2WField.setPreferredSize(FIELD_DIMENSION);
802 roi2WField.setMinimumSize(FIELD_DIMENSION);
803 roi2WField.setMaximumSize(FIELD_DIMENSION);
804 roi2WField.setMinimum(0);
805 roi2WField.addPropertyChangeListener("value", new PropertyChangeListener() {
806 @Override
807 public void propertyChange(PropertyChangeEvent evt) {
808 if (suppressChanges) return;
809 int value = ((Number) evt.getNewValue()).intValue();
810 if (roi2W == value) {
811 if (localChanges) roi2WField.setFont(getPlainFont());
812 return;
813 }
814 if (!localChanges) {
815 roi2W = value;
816 setData2();
817 }
818 else {
819 roi2WField.setFont(getBoldFont());
820 appliedToServer = false;
821 }
822 }
823 });
824 }
825 return roi2WField;
826 }
827
828 private NumberField getRoi2HField() {
829 if (roi2HField == null) {
830 roi2HField = new NumberField();
831 roi2HField.setNumberType(Integer.class);
832 roi2HField.setFormat("%d");
833 roi2HField.setPreferredSize(FIELD_DIMENSION);
834 roi2HField.setMinimumSize(FIELD_DIMENSION);
835 roi2HField.setMaximumSize(FIELD_DIMENSION);
836 roi2HField.setMinimum(0);
837 roi2HField.addPropertyChangeListener("value", new PropertyChangeListener() {
838 @Override
839 public void propertyChange(PropertyChangeEvent evt) {
840 if (suppressChanges) return;
841 int value = ((Number) evt.getNewValue()).intValue();
842 if (roi2H == value) {
843 if (localChanges) roi2HField.setFont(getPlainFont());
844 return;
845 }
846 if (!localChanges) {
847 roi2H = value;
848 setData2();
849 }
850 else {
851 roi2HField.setFont(getBoldFont());
852 appliedToServer = false;
853 }
854
855 }
856 });
857 }
858 return roi2HField;
859 }
860
861 private JButton getAllButton() {
862 if (allButton == null) {
863 allButton = new JButton("Select Entire Image");
864 allButton.setToolTipText("Select Entire Image for Region of Interest");
865 allButton.addActionListener(new ActionListener() {
866
867 @Override
868 public void actionPerformed(ActionEvent e) {
869 updateData(localChanges, imageW, imageH, 0, 0, imageW, imageH, roi2X, roi2Y, roi2W, roi2H, threshold, thresholdPoints,calculateThreshold,performFit,performSmoothing);
870 if (!localChanges) setData();
871 }});
872 }
873 return allButton;
874 }
875
876 private JButton getAllThresholdButton() {
877 if (allThresholdButton == null) {
878 allThresholdButton = new JButton("Select Entire Image");
879 allThresholdButton.setToolTipText("Threshold Region Is Whole Image");
880 allThresholdButton.addActionListener(new ActionListener() {
881
882 @Override
883 public void actionPerformed(ActionEvent e) {
884 updateData(localChanges, imageW, imageH, roiX, roiY, roiW, roiH, 0, 0, imageW, imageH, threshold,thresholdPoints,calculateThreshold,performFit,performSmoothing);
885 if (!localChanges) setData2();
886 }});
887 }
888 return allThresholdButton;
889 }
890
891 private JButton getDuplicateThresholdButton() {
892 if (duplicateThresholdButton == null) {
893 duplicateThresholdButton = new JButton("Copy Values from ROI");
894 duplicateThresholdButton.setToolTipText("Threshold Region Is the Same As ROI");
895 duplicateThresholdButton.addActionListener(new ActionListener() {
896
897 @Override
898 public void actionPerformed(ActionEvent e) {
899 updateData(localChanges, imageW, imageH, roiX, roiY, roiW, roiH, roiX, roiY, roiW, roiH, threshold,thresholdPoints,calculateThreshold,performFit,performSmoothing);
900 if (!localChanges) setData2();
901 }});
902 }
903 return duplicateThresholdButton;
904 }
905
906 private JButton getCurrentButton() {
907 if (currentButton == null) {
908 currentButton = new JButton("Use Current");
909 currentButton.addActionListener(new ActionListener() {
910 @Override
911 public void actionPerformed(ActionEvent e) {
912 executeTask(new Runnable() {
913 @Override
914 public void run() {
915 IMAGE im = acopVideo.getImageAnalysisEngine().getImage();
916 if (im == null) return;
917 im = im.clone();
918 fileName = VIDEO_BACKGROUND;
919 setBackgroundImage(im, false);
920 backgroundFile = null;
921 }
922 });
923 }
924 });
925 }
926 return currentButton;
927 }
928
929 private JButton getBrowseButton() {
930 if (browseButton == null) {
931 browseButton = new JButton("Load...");
932 browseButton.addActionListener(new ActionListener() {
933 @Override
934 public void actionPerformed(ActionEvent e) {
935 int option = getFileChooser().showOpenDialog(AnalysisCustomizer.this);
936 if (option == JFileChooser.APPROVE_OPTION) {
937 final File f = getFileChooser().getSelectedFile();
938 executeTask(new Runnable() {
939 @Override
940 public void run() {
941 try {
942
943 fileName = f.getAbsolutePath();
944 setBackgroundImage(TImageIO.read(f).toIMAGE(false),false);
945 backgroundFile = f;
946 } catch (IOException e1) {
947 e1.printStackTrace();
948 }
949 }
950 });
951 }
952 }
953 });
954 }
955 return browseButton;
956 }
957
958 private JButton getSaveButton() {
959 if (saveButton == null) {
960 saveButton = new JButton("Save...");
961 saveButton.addActionListener(new ActionListener() {
962 @Override
963 public void actionPerformed(ActionEvent e) {
964 int option = getFileChooser().showSaveDialog(AnalysisCustomizer.this);
965 if (option == JFileChooser.APPROVE_OPTION) {
966 final File f = getFileChooser().getSelectedFile();
967 executeTask(new Runnable() {
968 @Override
969 public void run() {
970 if (backgroundImage == null) return;
971 BufferedImage bi = ImageAnalysisEngine.toBufferedImage(backgroundImage);
972
973 List<String> ext = Arrays.asList(FILE_TYPES);
974 int dotIndex = f.getName().lastIndexOf('.');
975 String extension = FILE_TYPES[0];
976 if (dotIndex > 0 && dotIndex < f.getName().length()-2) {
977 String ex = f.getName().substring(dotIndex+1);
978 if (ext.contains(ex)) extension = ex;
979 }
980
981 try {
982 ImageIO.write(bi, extension, f);
983 } catch (IOException e1) {
984 e1.printStackTrace();
985 }
986 }
987 });
988 }
989 }
990 });
991 saveButton.setEnabled(false);
992 }
993 return saveButton;
994 }
995
996 private JButton getNoneButton() {
997 if (noneButton == null) {
998 noneButton = new JButton("Use None");
999 noneButton.addActionListener(new ActionListener() {
1000 @Override
1001 public void actionPerformed(ActionEvent e) {
1002 fileName = NO_BACKGROUND;
1003 setBackgroundImage((double[])null, 0, false);
1004 backgroundFile = null;
1005 }
1006 });
1007 }
1008 return noneButton;
1009 }
1010
1011 private JLabel getBackgroundLabel() {
1012 if (backgroundLabel == null) {
1013 backgroundLabel = new JLabel();
1014 backgroundLabel.setBorder(new LineBorder(Color.BLACK));
1015 backgroundLabel.setHorizontalAlignment(SwingConstants.CENTER);
1016 backgroundLabel.setText(NO_BACKGROUND);
1017 backgroundLabel.setPreferredSize(new Dimension(PREVIEW_DIMENSION, PREVIEW_DIMENSION));
1018 }
1019 return backgroundLabel;
1020 }
1021
1022 private JLabel getFileNameLabel() {
1023 if (fileNameLabel == null) {
1024 fileNameLabel = new JLabel("File: N/A");
1025 fileNameLabel.setHorizontalAlignment(SwingConstants.CENTER);
1026 fileNameLabel.setPreferredSize(LABEL_DIMENSION);
1027 fileNameLabel.setMinimumSize(LABEL_DIMENSION);
1028 fileNameLabel.setMaximumSize(LABEL_DIMENSION);
1029 }
1030 return fileNameLabel;
1031 }
1032
1033 private JFileChooser getFileChooser() {
1034 if (fileChooser == null) {
1035 fileChooser = new JFileChooser();
1036 fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
1037 fileChooser.setMultiSelectionEnabled(false);
1038 fileChooser.setFileFilter(new FileFilter() {
1039 List<String> ext = Arrays.asList(FILE_TYPES);
1040 @Override
1041 public boolean accept(File f) {
1042 if (f.isDirectory()) return true;
1043 String name = f.getName();
1044 int index = name.lastIndexOf('.');
1045 if (index > 0 && index < name.length()-2) {
1046 name = name.substring(index+1);
1047 if (ext.contains(name)) return true;
1048 }
1049 return false;
1050 }
1051 @Override
1052 public String getDescription() {
1053 String s = "Images (";
1054 for (Iterator<String> iterator = ext.iterator(); iterator.hasNext();) {
1055 String e = iterator.next();
1056 s += e;
1057 if (iterator.hasNext()) s += ", ";
1058 }
1059 s += ")";
1060 return s;
1061 }
1062 });
1063 }
1064 return fileChooser;
1065 }
1066
1067 private JCheckBox getDisplayNumericalValuesBox() {
1068 if (displayNumericalValuesBox == null) {
1069 displayNumericalValuesBox = new JCheckBox("Display Values");
1070 displayNumericalValuesBox.addActionListener(new ActionListener() {
1071 @Override
1072 public void actionPerformed(ActionEvent e) {
1073 acopVideo.setDisplayNumericalValues(displayNumericalValuesBox.isSelected());
1074 }
1075 });
1076 }
1077 return displayNumericalValuesBox;
1078 }
1079
1080 private void setAnalysisMode(AnalysisMode mode) {
1081 getApplyToServerButton().setEnabled(mode == AnalysisMode.REMOTE_ANALYSIS);
1082 getSynchronizeButton().setEnabled(mode == AnalysisMode.REMOTE_ANALYSIS);
1083 boolean enable = mode != AnalysisMode.NO_ANALYSIS;
1084 setSettingsEnabled(enable);
1085 localChanges = mode == AnalysisMode.REMOTE_ANALYSIS;
1086 if (!localChanges) {
1087 getRoiXField().setFont(getPlainFont());
1088 getRoiYField().setFont(getPlainFont());
1089 getRoiWField().setFont(getPlainFont());
1090 getRoiHField().setFont(getPlainFont());
1091 getRoi2XField().setFont(getPlainFont());
1092 getRoi2YField().setFont(getPlainFont());
1093 getRoi2WField().setFont(getPlainFont());
1094 getRoi2HField().setFont(getPlainFont());
1095 getThresholdField().setFont(getPlainFont());
1096 getCalculateTresholdCheckBox().setFont(getLabelPlainFont());
1097 getPerformFitCheckBox().setFont(getLabelPlainFont());
1098 getPerformSmoothCheckBox().setFont(getLabelPlainFont());
1099 }
1100 acopVideo.setAnalysisMode(mode);
1101 appliedToServer = true;
1102 }
1103
1104 private void setSettingsEnabled(boolean enable) {
1105 getThresholdField().setEnabled(enable);
1106 getCalculateTresholdCheckBox().setEnabled(enable);
1107 getPerformFitCheckBox().setEnabled(enable);
1108 getPerformSmoothCheckBox().setEnabled(enable);
1109 getDisplayStatisticsCheckBox().setEnabled(enable);
1110 getRoiXField().setEnabled(enable);
1111 getRoiYField().setEnabled(enable);
1112 getRoiWField().setEnabled(enable);
1113 getRoiHField().setEnabled(enable);
1114 getRoi2XField().setEnabled(enable);
1115 getRoi2YField().setEnabled(enable);
1116 getRoi2WField().setEnabled(enable);
1117 getRoi2HField().setEnabled(enable);
1118 getAllButton().setEnabled(enable);
1119 getAllThresholdButton().setEnabled(enable);
1120 getDuplicateThresholdButton().setEnabled(enable);
1121 getCurrentButton().setEnabled(enable);
1122 getBrowseButton().setEnabled(enable);
1123 getSaveButton().setEnabled(enable);
1124 getNoneButton().setEnabled(enable);
1125 getBackgroundLabel().setEnabled(enable);
1126 acopVideo.setCanChangeSettings(enable);
1127 }
1128
1129 private void applyToServer() {
1130 int rX = getRoiXField().getValue().intValue();
1131 int rY = getRoiYField().getValue().intValue();
1132 int rW = getRoiWField().getValue().intValue();
1133 int rH = getRoiHField().getValue().intValue();
1134 int r2X = getRoi2XField().getValue().intValue();
1135 int r2Y = getRoi2YField().getValue().intValue();
1136 int r2W = getRoi2WField().getValue().intValue();
1137 int r2H = getRoi2HField().getValue().intValue();
1138 double thr = getThresholdField().getValue().doubleValue();
1139 boolean cth = getCalculateTresholdCheckBox().isSelected();
1140 boolean fit = getPerformFitCheckBox().isSelected();
1141 boolean smooth = getPerformSmoothCheckBox().isSelected();
1142
1143 performFit = fit;
1144 performSmoothing = smooth;
1145 calculateThreshold = cth;
1146 threshold = thr;
1147
1148 roiX = rX;
1149 roiY = rY;
1150 roiW = rW;
1151 roiY = rY;
1152 acopVideo.getImageAnalysisEngine().setAnalysisParameters(
1153 threshold,rX,rY,rW,rH,r2X,r2Y,r2W,r2H,cth,fit,smooth);
1154 appliedToServer = true;
1155 }
1156
1157 private boolean updateData(boolean localChanges, int imageWidth, int imageHeight, int roiX, int roiY, int roiW, int roiH,
1158 int roi2X, int roi2Y, int roi2W, int roi2H,
1159 double threshold,int thresholdPoints,boolean calculateThreshold, boolean performFit, boolean performSmooth) {
1160 if (!appliedToServer && !localChanges) return false;
1161 suppressChanges = true;
1162 if (!localChanges) {
1163 this.roiX = roiX;
1164 this.roiY = roiY;
1165 this.roiW = roiW;
1166 this.roiH = roiH;
1167 this.roi2X = roi2X;
1168 this.roi2Y = roi2Y;
1169 this.roi2W = roi2W;
1170 this.roi2H = roi2H;
1171 this.threshold = threshold;
1172 this.calculateThreshold = calculateThreshold;
1173 this.performFit = performFit;
1174 this.performSmoothing = performSmooth;
1175 }
1176 this.thresholdPoints = thresholdPoints;
1177 this.imageW = imageWidth;
1178 this.imageH = imageHeight;
1179 getCalculateTresholdCheckBox().setSelected(calculateThreshold);
1180 getThresholdField().setEditable(!calculateThreshold && getUseTresholdCheckBox().isSelected());
1181 getPerformFitCheckBox().setSelected(performFit);
1182 getPerformSmoothCheckBox().setSelected(performSmooth);
1183 if (getUseTresholdCheckBox().isSelected()) {
1184 getThresholdField().setValue(threshold);
1185 } else {
1186 getThresholdField().setValue(Double.NaN);
1187 }
1188 if (!calculateThreshold) {
1189 getUseTresholdCheckBox().setEnabled(true);
1190 if (Double.isNaN(threshold)) {
1191 getUseTresholdCheckBox().setSelected(false);
1192 getThresholdField().setValue(Double.NaN);
1193 } else {
1194 getUseTresholdCheckBox().setSelected(true);
1195 getThresholdField().setValue(threshold);
1196 }
1197 } else {
1198 getUseTresholdCheckBox().setEnabled(false);
1199 }
1200 getRoiXField().setMaximum(imageWidth);
1201 getRoiYField().setMaximum(imageHeight);
1202 getRoiWField().setMaximum(imageWidth-roiX);
1203 getRoiHField().setMaximum(imageHeight-roiY);
1204 getRoi2XField().setMaximum(imageWidth);
1205 getRoi2YField().setMaximum(imageHeight);
1206 getRoi2WField().setMaximum(imageWidth-roi2X);
1207 getRoi2HField().setMaximum(imageHeight-roi2Y);
1208 getRoiXField().setValue(roiX);
1209 getRoiYField().setValue(roiY);
1210 getRoiWField().setValue(roiW);
1211 getRoiHField().setValue(roiH);
1212 getRoi2XField().setValue(roi2X);
1213 getRoi2YField().setValue(roi2Y);
1214 getRoi2WField().setValue(roi2W);
1215 getRoi2HField().setValue(roi2H);
1216
1217 getNumberOfPixelsLabel().setText(PIXELS_USED + (thresholdPoints));
1218
1219 getRoiXField().setFont(getPlainFont());
1220 getRoiYField().setFont(getPlainFont());
1221 getRoiWField().setFont(getPlainFont());
1222 getRoiHField().setFont(getPlainFont());
1223 getRoi2XField().setFont(getPlainFont());
1224 getRoi2YField().setFont(getPlainFont());
1225 getRoi2WField().setFont(getPlainFont());
1226 getRoi2HField().setFont(getPlainFont());
1227 getThresholdField().setFont(getPlainFont());
1228 getCalculateTresholdCheckBox().setFont(getLabelPlainFont());
1229 getPerformFitCheckBox().setFont(getLabelPlainFont());
1230 getPerformSmoothCheckBox().setFont(getLabelPlainFont());
1231 suppressChanges = false;
1232 return true;
1233 }
1234
1235 private void resetData() {
1236 suppressChanges = true;
1237 this.roiX = 0;
1238 this.roiY = 0;
1239 this.roiW = 0;
1240 this.roiH = 0;
1241 this.roi2X = 0;
1242 this.roi2Y = 0;
1243 this.roi2W = 0;
1244 this.roi2H = 0;
1245 this.imageW = 0;
1246 this.imageH = 0;
1247 this.threshold = 0;
1248 this.calculateThreshold = true;
1249 getThresholdField().setValue(Double.NaN);
1250 getCalculateTresholdCheckBox().setSelected(true);
1251 getPerformFitCheckBox().setSelected(false);
1252 getPerformSmoothCheckBox().setSelected(true);
1253 getThresholdField().setEditable(false);
1254 getUseTresholdCheckBox().setSelected(false);
1255 getRoiXField().setMaximum(0);
1256 getRoiYField().setMaximum(0);
1257 getRoiWField().setMaximum(0);
1258 getRoiHField().setMaximum(0);
1259 getRoiXField().setValue(0);
1260 getRoiYField().setValue(0);
1261 getRoiWField().setValue(0);
1262 getRoiHField().setValue(0);
1263 getRoi2XField().setMaximum(0);
1264 getRoi2YField().setMaximum(0);
1265 getRoi2WField().setMaximum(0);
1266 getRoi2HField().setMaximum(0);
1267 getRoi2XField().setValue(0);
1268 getRoi2YField().setValue(0);
1269 getRoi2WField().setValue(0);
1270 getRoi2HField().setValue(0);
1271 getNumberOfPixelsLabel().setText(PIXELS_USED + (0));
1272 suppressChanges = false;
1273 appliedToServer = true;
1274 }
1275
1276 private synchronized void setBackgroundImage(IMAGE img, boolean local) {
1277 if (img != null) {
1278 FrameHeader hdr = img.getFrameHeader();
1279 int w = hdr.aoiWidth == -1 ? hdr.sourceWidth : hdr.aoiWidth;
1280 int h = hdr.aoiHeight == -1 ? hdr.sourceHeight : hdr.aoiHeight;
1281 int[] rgb = ImageAnalysisEngine.toBufferedImage(img).getRGB(0,0,w,
1282 h,null,0,w);
1283 backgroundImage = img;
1284 preciseBackground = acopVideo.getImageAnalysisEngine().getDecoder().transform(rgb);
1285 preciseBackgroundWidth = w;
1286 } else {
1287 backgroundImage = null;
1288 preciseBackground = null;
1289 preciseBackgroundWidth = 0;
1290 }
1291 processBackground(local);
1292 }
1293
1294 private synchronized void setBackgroundImage(double[] image, int width, boolean local) {
1295 preciseBackground = image;
1296 backgroundImage = ImageAnalysisEngine.toImage(preciseBackground,width);
1297 preciseBackgroundWidth = width;
1298 processBackground(local);
1299 }
1300
1301 private void processBackground(boolean local) {
1302 updateFileNameLabel(fileName);
1303 if (preciseBackground == null || backgroundImage == null) {
1304 getBackgroundLabel().setText(NO_BACKGROUND);
1305 getBackgroundLabel().setIcon(null);
1306 } else {
1307 BufferedImage bi = ImageAnalysisEngine.toBufferedImage(preciseBackground,preciseBackgroundWidth);
1308 if (bi.getWidth() != 0 || bi.getHeight() != 0) {
1309 getSaveButton().setEnabled(true);
1310 int w1 = getBackgroundLabel().getWidth();
1311 int h1 = getBackgroundLabel().getHeight();
1312 h1 = Math.max(h1,100);
1313 w1 = Math.max(w1,100);
1314 ImageIcon icon = IconCustomizer.getScaledImage(bi, h1, w1);
1315 getBackgroundLabel().setIcon(icon);
1316 getBackgroundLabel().setText(null);
1317 } else {
1318 getBackgroundLabel().setText(INVALID_BACKGROUND);
1319 getBackgroundLabel().setIcon(null);
1320 }
1321
1322 }
1323 if (!local) acopVideo.getImageAnalysisEngine().setPreciseBackground(preciseBackground,preciseBackgroundWidth);
1324 }
1325
1326 private void updateFileNameLabel(String text) {
1327 getFileNameLabel().setText(text);
1328 getFileNameLabel().setToolTipText(text);
1329 }
1330
1331 private Font getPlainFont() {
1332 if (plainFont == null) {
1333 plainFont = getThresholdField().getFont();
1334 }
1335 return plainFont;
1336 }
1337
1338 private Font getLabelPlainFont() {
1339 if (labelPlainFont == null) {
1340 labelPlainFont = getNumberOfPixelsLabel().getFont();
1341 }
1342 return labelPlainFont;
1343 }
1344
1345 private Font getBoldFont() {
1346 if (boldFont == null) {
1347 boldFont = getPlainFont().deriveFont(Font.BOLD);
1348 }
1349 return boldFont;
1350 }
1351
1352 private Font getLabelBoldFont() {
1353 if (labelBoldFont == null) {
1354 labelBoldFont = getLabelPlainFont().deriveFont(Font.BOLD);
1355 }
1356 return labelBoldFont;
1357 }
1358
1359 private void setData() {
1360 acopVideo.getImageAnalysisEngine().setRoi(roiX, roiY, roiW, roiH);
1361 }
1362
1363 private void setData2() {
1364 acopVideo.getImageAnalysisEngine().setRoi2(roi2X, roi2Y, roi2W, roi2H);
1365 }
1366
1367 private void updateAnalysisData(AImage ai) {
1368 appliedToServer = updateData(false, ai.getImageW(), ai.getImageH(), ai.getRoiX(), ai.getRoiY(), ai.getRoiW(), ai.getRoiH(),
1369 ai.getRoi2X(), ai.getRoi2Y(), ai.getRoi2W(), ai.getRoi2H(), ai.getThreshold(),ai.getThresholdPoints(),ai.isCalculateThreshold(), ai.isPerformFit(), ai.isPerformSmoothing());
1370 getServerModel().setAImage(ai);
1371 }
1372
1373 private void updateBackground() {
1374 executeTask(new Runnable() {
1375 @Override
1376 public void run() {
1377 if (backgroundFile != null) return;
1378 double[] im = acopVideo.getImageAnalysisEngine().getPreciseBackground();
1379 int width = acopVideo.getImageAnalysisEngine().getBackgroundWidth();
1380 fileName = VIDEO_BACKGROUND;
1381 setBackgroundImage(im,width, true);
1382 }
1383 });
1384 }
1385
1386 private void executeTask(Runnable r) {
1387 if (executor == null) {
1388 executor = Executors.newSingleThreadExecutor();
1389 }
1390 executor.execute(r);
1391 }
1392
1393 public static void main(String[] args) {
1394
1395 AnalysisCustomizer customizer = new AnalysisCustomizer();
1396 RunnerHelper.runComponent(customizer,500,500);
1397 }
1398 }