diff --git a/src/hk/microos/data/Flags.java b/src/hk/microos/data/Flags.java index 4bfaaeb..8cfa30f 100644 --- a/src/hk/microos/data/Flags.java +++ b/src/hk/microos/data/Flags.java @@ -1,7 +1,7 @@ package hk.microos.data; public class Flags { - public static boolean GLOABAL_DEBUG = true; + public static boolean GLOABAL_DEBUG = false; public static boolean FUNC_INVOKE_PRINT = true; public static double minStroke = 2; public static double maxStroke = 5; diff --git a/src/hk/microos/data/LinearLine.java b/src/hk/microos/data/LinearLine.java index 3fc94be..be1cb88 100644 --- a/src/hk/microos/data/LinearLine.java +++ b/src/hk/microos/data/LinearLine.java @@ -1,6 +1,5 @@ package hk.microos.data; -import java.util.ArrayList; import hk.microos.tools.UniversalTool; diff --git a/src/hk/microos/frames/MainFrame.java b/src/hk/microos/frames/MainFrame.java index 7792b97..4787943 100644 --- a/src/hk/microos/frames/MainFrame.java +++ b/src/hk/microos/frames/MainFrame.java @@ -9,9 +9,7 @@ import javax.swing.border.EmptyBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.DefaultTableModel; - import hk.microos.data.Ellipse; import hk.microos.data.Flags; import hk.microos.data.MyImage; @@ -20,28 +18,23 @@ import hk.microos.tools.ImageTool; import hk.microos.tools.TableHelper; import hk.microos.tools.UniversalTool; - import javax.swing.GroupLayout; import javax.swing.GroupLayout.Alignment; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.ListSelectionModel; - import java.awt.Dimension; import java.awt.Color; import javax.swing.ScrollPaneConstants; import javax.swing.JButton; import javax.swing.JFileChooser; - import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; -import java.awt.image.BufferedImage; import java.io.File; -import java.nio.file.PathMatcher; import java.util.ArrayList; import java.util.HashMap; @@ -69,13 +62,14 @@ public class MainFrame extends JFrame { private JButton btnReadImageList; private int leftTableSelectedRow = -1; - + private HashMap pathImgPair = null; private HashMap> pathStaticElpsesPair = null; private JButton btnReadAnnotations; private String annotContentPrefix = null; private String annotContentSuffix = null; private JButton btnOutputAnnotation; + /** * Launch the application. */ @@ -87,8 +81,8 @@ public void run() { MainFrame frame = new MainFrame(); // frame.recordedOpenPath = // System.getProperty("user.home")+"/Desktop"; -// frame.recordedImgPath = -// "/Users/microos/Downloads/originalPics/imgPath.txt"; + // frame.recordedImgPath = + // "/Users/microos/Downloads/originalPics/imgPath.txt"; // frame.recordedAnnotPath = System.getProperty("user.home") // + "/Desktop"; @@ -126,35 +120,30 @@ public MainFrame() { JScrollPane rightScrollPanel = new JScrollPane(); GroupLayout gl_contentPane = new GroupLayout(contentPane); - gl_contentPane.setHorizontalGroup( - gl_contentPane.createParallelGroup(Alignment.LEADING) - .addGroup(gl_contentPane.createSequentialGroup() - .addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING) + gl_contentPane.setHorizontalGroup(gl_contentPane.createParallelGroup(Alignment.LEADING).addGroup(gl_contentPane + .createSequentialGroup() + .addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING) .addComponent(toolPanel, GroupLayout.DEFAULT_SIZE, 1174, Short.MAX_VALUE) - .addGroup(gl_contentPane.createSequentialGroup() - .addGap(3) - .addComponent(leftScrollPanel, GroupLayout.PREFERRED_SIZE, 230, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(scrollPanel, GroupLayout.PREFERRED_SIZE, 643, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(rightScrollPanel, GroupLayout.PREFERRED_SIZE, 286, GroupLayout.PREFERRED_SIZE))) - .addContainerGap()) - ); - gl_contentPane.setVerticalGroup( - gl_contentPane.createParallelGroup(Alignment.TRAILING) - .addGroup(gl_contentPane.createSequentialGroup() - .addComponent(toolPanel, GroupLayout.PREFERRED_SIZE, 38, GroupLayout.PREFERRED_SIZE) - .addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING) - .addGroup(gl_contentPane.createSequentialGroup() - .addPreferredGap(ComponentPlacement.RELATED) - .addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING) - .addComponent(leftScrollPanel, GroupLayout.PREFERRED_SIZE, 516, GroupLayout.PREFERRED_SIZE) - .addComponent(scrollPanel, GroupLayout.DEFAULT_SIZE, 535, Short.MAX_VALUE))) - .addGroup(gl_contentPane.createSequentialGroup() - .addGap(14) - .addComponent(rightScrollPanel, GroupLayout.DEFAULT_SIZE, 527, Short.MAX_VALUE))) - .addContainerGap()) - ); + .addGroup(gl_contentPane.createSequentialGroup().addGap(3) + .addComponent(leftScrollPanel, GroupLayout.PREFERRED_SIZE, 230, + GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(scrollPanel, GroupLayout.PREFERRED_SIZE, 643, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED).addComponent(rightScrollPanel, + GroupLayout.PREFERRED_SIZE, 286, GroupLayout.PREFERRED_SIZE))) + .addContainerGap())); + gl_contentPane.setVerticalGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING).addGroup(gl_contentPane + .createSequentialGroup() + .addComponent(toolPanel, GroupLayout.PREFERRED_SIZE, 38, GroupLayout.PREFERRED_SIZE) + .addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING) + .addGroup(gl_contentPane.createSequentialGroup().addPreferredGap(ComponentPlacement.RELATED) + .addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING) + .addComponent(leftScrollPanel, GroupLayout.PREFERRED_SIZE, 516, + GroupLayout.PREFERRED_SIZE) + .addComponent(scrollPanel, GroupLayout.DEFAULT_SIZE, 535, Short.MAX_VALUE))) + .addGroup(gl_contentPane.createSequentialGroup().addGap(14).addComponent(rightScrollPanel, + GroupLayout.DEFAULT_SIZE, 527, Short.MAX_VALUE))) + .addContainerGap())); button = new JButton("TEST"); button.setVisible(false); @@ -180,7 +169,7 @@ public void actionPerformed(ActionEvent e) { } }); toolPanel.add(btnReadAnnotations); - + btnOutputAnnotation = new JButton("Output Annotation"); btnOutputAnnotation.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -249,23 +238,24 @@ public void valueChanged(ListSelectionEvent e) { } }); } - void rightTableOnClick(ListSelectionEvent e){ + + void rightTableOnClick(ListSelectionEvent e) { if (e.getValueIsAdjusting()) return; - + int rowIdx = coordListTH.getSelectedRowIndex(); - + cm.clickOnRightTable(rowIdx); } + void leftTableOnClick(ListSelectionEvent e) { if (e.getValueIsAdjusting()) return; leftTableSelectedRow = imgListTH.getSelectedRowIndex(); if (leftTableSelectedRow == -1) return; - int id = (int) imgListTH.getValueAt(leftTableSelectedRow, 0); String path = imgListTH.getBehindRowDataAt(leftTableSelectedRow); - MyImage mim = UniversalTool.getMyImageFromPathImgPair(path,pathImgPair); + MyImage mim = UniversalTool.getMyImageFromPathImgPair(path, pathImgPair); boolean changed = imagePanel.setCurrentImage(mim); // display coords on the right setRightPanelCoords(mim); @@ -276,8 +266,8 @@ void leftTableOnClick(ListSelectionEvent e) { } void setRightPanelCoords(MyImage mim) { - //call this will update right panel with image's staticEllipse/Ellipse - //use null as the arg will use a selectedRow as target image + // call this will update right panel with image's staticEllipse/Ellipse + // use null as the arg will use a selectedRow as target image if (mim == null) { if (leftTableSelectedRow == -1) { System.err.println("bad-0 at setRightPanelCoords"); @@ -289,9 +279,8 @@ void setRightPanelCoords(MyImage mim) { System.err.println("bad-1 at setRightPanelCoords"); return; } - - } + } // 1 load static ellipse into the table // when pathElpsesPair set and ArrayList staticElps; @@ -303,7 +292,7 @@ void setRightPanelCoords(MyImage mim) { // 2 load drawn ellipse into the table coordListTH.fillRightTable(mim.getStaticElpsesStrings(), mim.getElpsesStrings()); } - + void updateImagePanelSize(MyImage mim) { if (defaultScrollW == -1) defaultScrollW = scrollPanel.getWidth(); @@ -340,7 +329,7 @@ void loadImageList() { } else { pathImgPair = IOTool.filterImageList(imgList, this); - if(pathImgPair.size() == 0){ + if (pathImgPair.size() == 0) { pathImgPair = null; return; } @@ -362,20 +351,22 @@ void fillImageNameTable() { void testTable() { System.out.println(imgListTH.getTable().hashCode() == imgNameTable.hashCode()); } + void loadAnnotList() { if (pathImgPair == null) { // no images loaded, abort return; } - if(annotContentPrefix == null){ - String s = JOptionPane.showInputDialog(this, "Please set a prefix string for your annotation image path.\n(leave empty or cancel if not necessary)", "Prefix", JOptionPane.QUESTION_MESSAGE); - annotContentPrefix = s==null? "" : s; - - s = JOptionPane.showInputDialog(this, "Please set a suffix(usually is image format extention) for your annotation image path.\n(leave empty or cancel if not necessary)", "Suffix", JOptionPane.QUESTION_MESSAGE); - annotContentSuffix = s==null? "" : s; - - - + if (annotContentPrefix == null) { + String s = JOptionPane.showInputDialog(this, + "Please set a prefix string for your annotation image path.\n(leave empty or cancel if not necessary)", + "Prefix", JOptionPane.QUESTION_MESSAGE); + annotContentPrefix = s == null ? "" : s; + + s = JOptionPane.showInputDialog(this, + "Please set a suffix(usually is image format extention) for your annotation image path.\n(leave empty or cancel if not necessary)", + "Suffix", JOptionPane.QUESTION_MESSAGE); + annotContentSuffix = s == null ? "" : s; } JFileChooser fc = new JFileChooser(recordedAnnotPath); // fc.setFileSelectionMode(JFileChooser.FILES_ONLY); @@ -402,32 +393,87 @@ void loadAnnotList() { } if (noError == false) { + pathStaticElpsesPair = null; annotContentPrefix = annotContentSuffix = null; // parse failed JOptionPane .showMessageDialog(this, - String.format("Failed to parse the file: \"%s\"\n\n" + "Error:\n%s", + String.format("Failed to parse the file: \"%s\"\n\nError Info:\n%s", f.getAbsolutePath(), errMessage), "Parsing failed", JOptionPane.ERROR_MESSAGE); + return; } else { // // parse successes, reset // // // put these annotations to mImg.ellispe_static + int failedNum = 0; + int foundNum = 0; + ArrayList failed = new ArrayList<>(); for (String p : pathImgPair.keySet()) { ArrayList elpses = pathStaticElpsesPair.get(p); if (elpses != null) {// annotation list contains this // image's annotations MyImage mim = UniversalTool.getMyImageFromPathImgPair(p, pathImgPair); mim.setElpsesStatic(elpses); + foundNum++; // update mark nums } else { - // System.err.println(String.format("%s not found in - // [pathElpsesPair], abort\n", p)); + failedNum++; + if (failedNum < 10) { + failed.add(p); + } +// System.err.println(String.format("%s not found in " + "[pathElpsesPair], abort\n", p)); } } + if (failedNum == pathImgPair.size()) { + // all failed + + + String m = "Did not found any matched images for the annotation file you selected.\n"; + m += "Please check the paths in your annotation file.\n"; + m += "To match an annotation with a loaded image,\n"; + m += "make sure two paths are identical to each other.\n"; + m += "Maybe a carefully-set prefix and suffix will help."; + String p = annotContentPrefix == null ? "" : annotContentPrefix; + String s = annotContentSuffix == null ? "" : annotContentSuffix; + + if (pathStaticElpsesPair != null && pathStaticElpsesPair.size() != 0) { + m += "\n\nCurrent path concatenated with prefix and sufix:\n"; + m += String.format("Prefix = \"%s\"\n", p); + m += String.format("Suffix = \"%s\"\n", s); + m += ("Concatenated: "+pathStaticElpsesPair.keySet().iterator().next()); + } else { + m += "\n\nYour current prefix and sufix:\n"; + m += String.format("Prefix = \"%s\"\n", p); + m += String.format("Suffix = \"%s\"\n", s); + } + + JOptionPane.showMessageDialog(this, m, "Not found any matched annotations", + JOptionPane.WARNING_MESSAGE); + annotContentPrefix = annotContentSuffix = null; + pathStaticElpsesPair = null; + return; + } + if(failedNum != 0){ + String m = "Did not found any match annotations for the following loaded images:\n"; + if(failed.size() < failedNum){ + m += String.format("(%d listed, %d in total)\n", failed.size(), failedNum); + }else{ + m += String.format("(num of images has no annotations: %d)\n", failed.size() ); + } + int i = 1; + for (String fal : failed) { + m += String.format("%2d [%s]\n", i, fal); + i++; + } + JOptionPane.showMessageDialog(this, m, "Some images do not have annotations", + JOptionPane.WARNING_MESSAGE); + } + marksLoadAnnotationUpdate(); imagePanel.repaint(); freezeReadAnnotationBtn(); + JOptionPane.showMessageDialog(this, String.format("Load annotations for %d images.", foundNum)); // // reset // pathImgPair = null; // leftTableSelectedRow = -1; @@ -435,7 +481,7 @@ void loadAnnotList() { } } - }else{ + } else { annotContentPrefix = annotContentSuffix = null; } } @@ -479,42 +525,47 @@ public void marksLoadAnnotationUpdate() { } public void marksUpdatedAtSelectedImage(MyImage mim) { - + if (leftTableSelectedRow == -1) { System.err.println("marking on non-loaded image?"); } imgListTH.setValueAt(leftTableSelectedRow, 2, mim.getMarkNumString()); setRightPanelCoords(mim); } - public void freezeReadImageListBtn(){ + + public void freezeReadImageListBtn() { this.btnReadImageList.setEnabled(false); } - public void freezeReadAnnotationBtn(){ + + public void freezeReadAnnotationBtn() { this.btnReadAnnotations.setEnabled(false); } - public HashMap getPathImgPair(){ + + public HashMap getPathImgPair() { return pathImgPair; } - void outputAnnotations(){ - if(pathImgPair == null){ - return; //even no image loaded? abort + + void outputAnnotations() { + if (pathImgPair == null) { + return; // even no image loaded? abort } - if(Flags.numNewEllipse <= 0){ - JOptionPane.showMessageDialog(this, "You did not mark any annotations, nothing to output.","Nothing to output",JOptionPane.WARNING_MESSAGE); + if (Flags.numNewEllipse <= 0) { + JOptionPane.showMessageDialog(this, "You did not mark any annotations, nothing to output.", + "Nothing to output", JOptionPane.WARNING_MESSAGE); return; } - //open a chooser - //make it a .txt file + // open a chooser + // make it a .txt file // ask: output only the new Ellipse or both new and static - + JFileChooser fc = new JFileChooser(recordedSavePath); // fc.setFileSelectionMode(JFileChooser.FILES_ONLY); int res = fc.showOpenDialog(this); if (res == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); recordedImgPath = f.getParent(); - IOTool.outputEllipse(pathImgPair, f.getAbsolutePath(),pathStaticElpsesPair != null,this); - + IOTool.outputEllipse(pathImgPair, f.getAbsolutePath(), pathStaticElpsesPair != null, this); + } } } diff --git a/src/hk/microos/frames/MyImagePanel.java b/src/hk/microos/frames/MyImagePanel.java index 9c09269..548ecef 100644 --- a/src/hk/microos/frames/MyImagePanel.java +++ b/src/hk/microos/frames/MyImagePanel.java @@ -8,11 +8,8 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; import java.util.ArrayList; - import javax.swing.JPanel; import javax.swing.JScrollPane; -import javax.swing.plaf.synth.SynthSpinnerUI; - import hk.microos.data.Ellipse; import hk.microos.data.Flags; import hk.microos.data.LinearLine; @@ -28,6 +25,7 @@ * */ +@SuppressWarnings("serial") public class MyImagePanel extends JPanel { private MyImage mImg = null; MainFrame mainFrame = null; @@ -49,7 +47,6 @@ public class MyImagePanel extends JPanel { private int highlightedStaticEllipseIdx = -1; public MyImagePanel(MainFrame mainFrame, JScrollPane fatherPanel) { this.mainFrame = mainFrame; - this.fatherPanel = fatherPanel; } @@ -131,7 +128,7 @@ public void drawStaticEllipses(Graphics2D g2d) { Ellipse2D.Double ed = e.getErectedEllipse2D(); if(i == highlightedStaticEllipseIdx){ - g2d.setColor(Color.red); + g2d.setColor(Color.CYAN); }else{ g2d.setColor(Color.black); } diff --git a/src/hk/microos/test/TestFrame.java b/src/hk/microos/test/TestFrame.java index 0138490..64fd5ba 100644 --- a/src/hk/microos/test/TestFrame.java +++ b/src/hk/microos/test/TestFrame.java @@ -1,6 +1,5 @@ package hk.microos.test; -import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.EventQueue; @@ -8,7 +7,6 @@ import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; -import java.awt.geom.Line2D; import javax.swing.JComponent; import javax.swing.JFrame; @@ -19,6 +17,7 @@ import hk.microos.data.Point_; import hk.microos.tools.UniversalTool; +@SuppressWarnings("serial") public class TestFrame extends JFrame { private JPanel contentPane; @@ -63,7 +62,6 @@ public void paintComponent(Graphics g) { //save old transform AffineTransform old = g2d.getTransform(); - AffineTransform trf = new AffineTransform(); for (Point_ p : e.getKeyPoints()){ g2d.fill(UniversalTool.getPointOval(p, 5)); } diff --git a/src/hk/microos/test/test.java b/src/hk/microos/test/test.java index 5acfb68..7d89952 100644 --- a/src/hk/microos/test/test.java +++ b/src/hk/microos/test/test.java @@ -1,14 +1,6 @@ package hk.microos.test; -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; - -import javax.swing.JOptionPane; - -import hk.microos.data.*; -import hk.microos.tools.UniversalTool; public class test { diff --git a/src/hk/microos/tools/ClickHelper.java b/src/hk/microos/tools/ClickHelper.java index f0a2aa2..77f40d8 100644 --- a/src/hk/microos/tools/ClickHelper.java +++ b/src/hk/microos/tools/ClickHelper.java @@ -1,6 +1,5 @@ package hk.microos.tools; -import java.util.ArrayList; import hk.microos.data.Point_; import hk.microos.frames.MyImagePanel; diff --git a/src/hk/microos/tools/IOTool.java b/src/hk/microos/tools/IOTool.java index e42e100..b9bea74 100644 --- a/src/hk/microos/tools/IOTool.java +++ b/src/hk/microos/tools/IOTool.java @@ -9,10 +9,8 @@ import java.util.ArrayList; import java.util.HashMap; -import javax.print.attribute.standard.NumberOfDocuments; import javax.swing.JFrame; import javax.swing.JOptionPane; -import javax.tools.ToolProvider; import hk.microos.data.Ellipse; import hk.microos.data.Flags; @@ -50,12 +48,12 @@ public static ArrayList readText(File f) { return stringList; } - public static HashMap filterImageList(ArrayList list, JFrame dialogFatherFrame) { + public static HashMap filterImageList(ArrayList list, JFrame dialogFatherFrame) { HashMap map = new HashMap<>(); ArrayList failed = new ArrayList<>(); int failedNum = 0; for (String l : list) { - if(l.trim().equals("")){ + if (l.trim().equals("")) { continue; } if (!new File(l).exists()) { @@ -119,25 +117,39 @@ public static HashMap> readAnnotationFile(File f, Str prefix = ""; suffix = ".jpg"; + } - + System.out.println("prefix: "+prefix); + System.out.println("suffix: "+suffix); // parse annotation files int at = 0; while (at < lines.size()) { String path = prefix + lines.get(at) + suffix; at++; - - int detNum = Integer.parseInt(lines.get(at)); + int detNum = 0; + try { + detNum = Integer.parseInt(lines.get(at)); + + } catch (Exception e) { + throw new Exception(String.format("At line %d, failed to parse \"%s\" as number of annotations.\n", at, + lines.get(at))); + + } at++; - - ArrayList elpses = readNEllipse(lines, at, detNum); + + + ArrayList elpses = null; + try { + elpses = readNEllipse(lines, at, detNum); + + } catch (Exception e) { + throw new Exception(e.getMessage()); + + } + at += detNum; - if (new File(path).exists()) { - map.put(path, elpses); - } else { - System.err.println(path + " listed in annotation files not found!"); - } + map.put(path, elpses); } @@ -151,7 +163,7 @@ private static ArrayList readNEllipse(ArrayList lines, int star String line = lines.get(at); String[] splitStr = line.split(" +"); if (splitStr.length < 5) { - throw new Exception(String.format("Line %d: contains less than 5 float values.", at)); + throw new Exception(String.format("At line %d: \"%s\"\ncontains less than 5 float values.\nExpected annotation format: major,minor,angle,x,y", at,line)); } ArrayList splitFlt = new ArrayList<>(); for (String s : splitStr) { diff --git a/src/hk/microos/tools/TableHelper.java b/src/hk/microos/tools/TableHelper.java index ed0feb8..e5d7689 100644 --- a/src/hk/microos/tools/TableHelper.java +++ b/src/hk/microos/tools/TableHelper.java @@ -4,7 +4,6 @@ import java.awt.Component; import java.util.ArrayList; import java.util.Set; - import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.table.DefaultTableCellRenderer; @@ -50,6 +49,7 @@ public void setColSize(int[] colSize) { } } + @SuppressWarnings("serial") public void fillRightTable(ArrayList staticCoords, ArrayList coords) { clearAll(); // set red color as selected color diff --git a/src/hk/microos/tools/UniversalTool.java b/src/hk/microos/tools/UniversalTool.java index 4c3f945..cd8ef4c 100644 --- a/src/hk/microos/tools/UniversalTool.java +++ b/src/hk/microos/tools/UniversalTool.java @@ -3,15 +3,9 @@ import java.awt.BasicStroke; import java.awt.geom.Ellipse2D; import java.io.File; -import java.io.IOException; -import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.List; - -import javax.naming.NoInitialContextException; - import hk.microos.data.Ellipse; import hk.microos.data.Flags; import hk.microos.data.MyImage;