CAUTION: This model is computationally heavy. It is not recommended to use it on lower-end computers.
";
+ public static final String INPUT_IMAGE_AXES = "xyc";
/**
* Create an instance of the model that loads the model and encodes an image
*/
public SAM2Large() {
+ this.isHeavy = true;
+ this.fullName = "SAM-2: Segment Anything Model 2 (Large)";
+ this.githubLink = "https://github.com/facebookresearch/segment-anything-2";
+ this.paperLink = "https://ai.meta.com/research/publications/sam-2-segment-anything-in-images-and-videos/";
+ this.githubName = "https://github.com/facebookresearch/segment-anything-2";
+ this.paperName = "SAM 2: Segment Anything in Images and Videos";
+ this.speedRank = 3;
+ this.performanceRank = 3;
+ this.size = 155.9;
this.manager = Sam2EnvManager.create(Sam2EnvManager.DEFAULT_DIR, "large");
}
@@ -102,14 +101,6 @@ public String getName() {
return FULL_NAME;
}
- @Override
- /**
- * {@inheritDoc}
- */
- public String getDescription() {
- return HTML_DESCRIPTION + (!this.isInstalled() ? SAMModel.HTML_NOT_INSTALLED : CAUTION_STRING);
- }
-
@Override
/**
* {@inheritDoc}
diff --git a/src/main/java/ai/nets/samj/communication/model/SAM2Small.java b/src/main/java/ai/nets/samj/communication/model/SAM2Small.java
index 41db326..3c74909 100644
--- a/src/main/java/ai/nets/samj/communication/model/SAM2Small.java
+++ b/src/main/java/ai/nets/samj/communication/model/SAM2Small.java
@@ -75,22 +75,21 @@ public void error(String text) {
* Axes order required for the input image by the model
*/
public static final String INPUT_IMAGE_AXES = "xyc";
-
- private static final String HTML_DESCRIPTION = "SAM-2: Segment Anything Model 2 CAUTION: This model is computationally heavy. It is not recommended to use it on lower-end computers.
";
-
+
/**
* Create an instance of the model that loads the model and encodes an image
*/
public SAM2Small() {
+ this.isHeavy = true;
+ this.fullName = "SAM-2: Segment Anything Model 2 (Small)";
+ this.githubLink = "https://github.com/facebookresearch/segment-anything-2";
+ this.paperLink = "https://ai.meta.com/research/publications/sam-2-segment-anything-in-images-and-videos/";
+ this.githubName = "https://github.com/facebookresearch/segment-anything-2";
+ this.paperName = "SAM 2: Segment Anything in Images and Videos";
+ this.speedRank = 3;
+ this.performanceRank = 3;
+ this.size = 184.3;
this.manager = Sam2EnvManager.create(Sam2EnvManager.DEFAULT_DIR, "small");
}
@@ -102,14 +101,6 @@ public String getName() {
return FULL_NAME;
}
- @Override
- /**
- * {@inheritDoc}
- */
- public String getDescription() {
- return HTML_DESCRIPTION + (!this.isInstalled() ? SAMModel.HTML_NOT_INSTALLED : CAUTION_STRING);
- }
-
@Override
/**
* {@inheritDoc}
diff --git a/src/main/java/ai/nets/samj/communication/model/SAM2Tiny.java b/src/main/java/ai/nets/samj/communication/model/SAM2Tiny.java
index a9df324..39f7109 100644
--- a/src/main/java/ai/nets/samj/communication/model/SAM2Tiny.java
+++ b/src/main/java/ai/nets/samj/communication/model/SAM2Tiny.java
@@ -74,22 +74,22 @@ public void error(String text) {
/**
* Axes order required for the input image by the model
*/
- public static final String INPUT_IMAGE_AXES = "xyc";
-
- private static final String HTML_DESCRIPTION = "SAM-2: Segment Anything Model 2 CAUTION: This model is"
+ + " computationally heavy. It is not recommended to use it on lower-end computers.
";
+
+ protected static String HTML_MODEL_FORMAT = ""
+ + "This model is not installed yet.
";
@@ -56,11 +95,6 @@ public abstract class SAMModel {
* @return the axes order required for the input image to the model
*/
public abstract String getInputImageAxes();
- /**
- *
- * @return a text describing the model.
- */
- public abstract String getDescription();
/**
*
* @return the {@link SamEnvManagerAbstract} used to install this model
@@ -158,6 +192,20 @@ void setImage(final RandomAccessibleInterval image, final SAMJLogger useThisL
* Notify the User Interface that the model has been closed
*/
public abstract void notifyUiHasBeenClosed();
+
+ /**
+ *
+ * @return a text describing the model.
+ */
+ public String getDescription() {
+ String description = String.format(HTML_MODEL_FORMAT, fullName, "" + size,
+ "" + speedRank, "" + performanceRank, githubLink, githubName, paperLink, paperName);
+ boolean installed = this.isInstalled();
+ description += this.isHeavy & installed ? CAUTION_STRING : "";
+ description += installed ? "" : HTML_NOT_INSTALLED;
+ return description;
+ }
+
/**
*
* @return true or false whether all the things needed to run the model are already installed or not.
diff --git a/src/main/java/ai/nets/samj/gui/HTMLPane.java b/src/main/java/ai/nets/samj/gui/HTMLPane.java
index 9f76f03..6b26cc1 100644
--- a/src/main/java/ai/nets/samj/gui/HTMLPane.java
+++ b/src/main/java/ai/nets/samj/gui/HTMLPane.java
@@ -8,103 +8,136 @@
import javax.swing.text.Document;
/**
- * This class extends the Java JEditorPane to make a easy to use panel to
+ * This class extends the Java JEditorPane to make an easy-to-use panel to
* display HTML information.
*
- * @author Daniel Sage, Biomedical Imaging Group, EPFL, Lausanne, Switzerland.
- *
*/
public class HTMLPane extends JEditorPane {
- private String html = "";
- private String header = "";
- private String footer = "";
- private Dimension dim;
- private String font = "verdana";
- private String color = "#222222";
- private String background = "#f8f8f8";
+ private String html = "";
+ private String header = "";
+ private String footer = "";
+ private Dimension dim;
+ private String font = "Segoe UI";
+ private String color = "#333333";
+ private String background = "#FFFFFF";
- public HTMLPane() {
- create();
- }
+ public HTMLPane() {
+ create();
+ }
- public HTMLPane(String font) {
- this.font = font;
- create();
- }
+ public HTMLPane(String font) {
+ this.font = font;
+ create();
+ }
- public HTMLPane(int width, int height) {
- this.dim = new Dimension(width, height);
- create();
- }
+ public HTMLPane(int width, int height) {
+ this.dim = new Dimension(width, height);
+ create();
+ }
- public HTMLPane(String font, int width, int height) {
- this.font = font;
- this.dim = new Dimension(width, height);
- create();
- }
+ public HTMLPane(String font, int width, int height) {
+ this.font = font;
+ this.dim = new Dimension(width, height);
+ create();
+ }
- public HTMLPane(String font, String color, String background, int width, int height) {
- this.font = font;
- this.dim = new Dimension(width, height);
- this.color = color;
- this.background = background;
- create();
- }
+ public HTMLPane(String font, String color, String background, int width, int height) {
+ this.font = font;
+ this.dim = new Dimension(width, height);
+ this.color = color;
+ this.background = background;
+ create();
+ }
- @Override
- public String getText() {
- Document doc = this.getDocument();
- try {
- return doc.getText(0, doc.getLength());
- }
- catch (BadLocationException e) {
- e.printStackTrace();
- return getText();
- }
- }
+ @Override
+ public String getText() {
+ Document doc = this.getDocument();
+ try {
+ return doc.getText(0, doc.getLength());
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ return getText();
+ }
+ }
- public void clear() {
- html = "";
- append("");
- }
+ public void clear() {
+ html = "";
+ append("");
+ }
- private void create() {
- header += "\n";
- header += "\n";
- header += "\n";
- header += "\n";
- header += "\n";
- header += "\n";
- header += "\n";
- header += "\n";
- header += "\n";
- footer += "\n";
- setEditable(false);
- setContentType("text/html; charset=ISO-8859-1");
- }
+ private void create() {
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ footer += "\n";
+ setEditable(false);
+ setContentType("text/html; charset=UTF-8");
+ }
- public void append(String content) {
- html += content;
- setText(header + html + footer);
- if (dim != null) {
- setPreferredSize(dim);
- }
- setCaretPosition(0);
- }
+ public void append(String content) {
+ html += content;
+ setText(header + html + footer);
+ if (dim != null) {
+ setPreferredSize(dim);
+ }
+ setCaretPosition(0);
+ }
- public void append(String tag, String content) {
- html += "<" + tag + ">" + content + "" + tag + ">";
- setText(header + html + footer);
- if (dim != null) {
- setPreferredSize(dim);
- }
- setCaretPosition(0);
- }
+ public void append(String tag, String content) {
+ html += "<" + tag + ">" + content + "" + tag + ">";
+ setText(header + html + footer);
+ if (dim != null) {
+ setPreferredSize(dim);
+ }
+ setCaretPosition(0);
+ }
- public JScrollPane getPane() {
- JScrollPane scroll = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
- scroll.setPreferredSize(dim);
- return scroll;
- }
+ public JScrollPane getPane() {
+ JScrollPane scroll = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ scroll.setPreferredSize(dim);
+ return scroll;
+ }
}
diff --git a/src/main/java/ai/nets/samj/gui/HTMLPane2.java b/src/main/java/ai/nets/samj/gui/HTMLPane2.java
new file mode 100644
index 0000000..0006365
--- /dev/null
+++ b/src/main/java/ai/nets/samj/gui/HTMLPane2.java
@@ -0,0 +1,110 @@
+package ai.nets.samj.gui;
+
+import java.awt.Dimension;
+
+import javax.swing.JEditorPane;
+import javax.swing.JScrollPane;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+
+/**
+ * This class extends the Java JEditorPane to make a easy to use panel to
+ * display HTML information.
+ *
+ * @author Daniel Sage, Biomedical Imaging Group, EPFL, Lausanne, Switzerland.
+ *
+ */
+public class HTMLPane2 extends JEditorPane {
+
+ private String html = "";
+ private String header = "";
+ private String footer = "";
+ private Dimension dim;
+ private String font = "verdana";
+ private String color = "#222222";
+ private String background = "#f8f8f8";
+
+ public HTMLPane2() {
+ create();
+ }
+
+ public HTMLPane2(String font) {
+ this.font = font;
+ create();
+ }
+
+ public HTMLPane2(int width, int height) {
+ this.dim = new Dimension(width, height);
+ create();
+ }
+
+ public HTMLPane2(String font, int width, int height) {
+ this.font = font;
+ this.dim = new Dimension(width, height);
+ create();
+ }
+
+ public HTMLPane2(String font, String color, String background, int width, int height) {
+ this.font = font;
+ this.dim = new Dimension(width, height);
+ this.color = color;
+ this.background = background;
+ create();
+ }
+
+ @Override
+ public String getText() {
+ Document doc = this.getDocument();
+ try {
+ return doc.getText(0, doc.getLength());
+ }
+ catch (BadLocationException e) {
+ e.printStackTrace();
+ return getText();
+ }
+ }
+
+ public void clear() {
+ html = "";
+ append("");
+ }
+
+ private void create() {
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ header += "\n";
+ footer += "\n";
+ setEditable(false);
+ setContentType("text/html; charset=ISO-8859-1");
+ }
+
+ public void append(String content) {
+ html += content;
+ setText(header + html + footer);
+ if (dim != null) {
+ setPreferredSize(dim);
+ }
+ setCaretPosition(0);
+ }
+
+ public void append(String tag, String content) {
+ html += "<" + tag + ">" + content + "" + tag + ">";
+ setText(header + html + footer);
+ if (dim != null) {
+ setPreferredSize(dim);
+ }
+ setCaretPosition(0);
+ }
+
+ public JScrollPane getPane() {
+ JScrollPane scroll = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ scroll.setPreferredSize(dim);
+ return scroll;
+ }
+}
diff --git a/src/main/java/ai/nets/samj/gui/components/ModelDrawerPanel.java b/src/main/java/ai/nets/samj/gui/components/ModelDrawerPanel.java
index 09fbe03..5c01332 100644
--- a/src/main/java/ai/nets/samj/gui/components/ModelDrawerPanel.java
+++ b/src/main/java/ai/nets/samj/gui/components/ModelDrawerPanel.java
@@ -3,6 +3,7 @@
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
+import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
@@ -31,7 +32,7 @@ public class ModelDrawerPanel extends JPanel implements ActionListener {
private JLabel drawerTitle = new JLabel();
private JButton install = new JButton("Install");
private JButton uninstall = new JButton("Uninstall");
- HTMLPane html = new HTMLPane("Arial", "#000", "#CCCCCC", 200, 200);
+ HTMLPane html = new HTMLPane("Segoe UI", "#333333", "#FFFFFF", 200, 200);
private SAMModel model;
private ModelDrawerPanelListener listener;
@@ -39,6 +40,8 @@ public class ModelDrawerPanel extends JPanel implements ActionListener {
private Thread modelInstallThread;
private Thread infoThread;
private Thread installedThread;
+ private Thread loadingAnimationThread;
+ private volatile boolean isLoading = false;
private static final String MODEL_TITLE = "%s";
@@ -55,8 +58,13 @@ public static ModelDrawerPanel create(int hSize, ModelDrawerPanelListener listen
private void createDrawerPanel() {
this.setLayout(new BorderLayout());
- this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ this.setBorder(BorderFactory.createEtchedBorder());
+ drawerTitle.setFont(new Font("Segoe UI", Font.BOLD, 20));
+ drawerTitle.setForeground(new Color(50, 50, 50));
drawerTitle.setText(String.format(MODEL_TITLE, " "));
+ drawerTitle.setHorizontalAlignment(JLabel.CENTER); // Center the title
+ //drawerTitle.setFont(new Font("Arial", Font.BOLD, 18)); // Set a modern font and size
+ drawerTitle.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); // Add padding
this.add(drawerTitle, BorderLayout.NORTH);
this.add(createInstallModelComponent(), BorderLayout.SOUTH);
html.append("Model description");
@@ -69,6 +77,7 @@ private void createDrawerPanel() {
this.setPreferredSize(new Dimension(hSize, 0)); // Set preferred width
}
+
// Method to create the install model component
private JPanel createInstallModelComponent() {
JPanel thirdComponent = new JPanel();
@@ -115,9 +124,14 @@ private void setTitle(String title) {
private void setInfo() {
html.clear();
+ startLoadingAnimation("Loading info");
infoThread =new Thread(() -> {
String description = model.getDescription();
- SwingUtilities.invokeLater(() -> html.append("p", description));
+ stopLoadingAnimation();
+ SwingUtilities.invokeLater(() -> {
+ html.clear();
+ html.append("p", description);
+ });
});
infoThread.start();
}
@@ -167,10 +181,39 @@ private void uninstallModel() {
});
}
- public interface ModelDrawerPanelListener {
-
- void setGUIEnabled(boolean enabled);
+ private void startLoadingAnimation(String message) {
+ stopLoadingAnimation(); // Ensure any previous animation is stopped
+ isLoading = true;
+ loadingAnimationThread = new Thread(() -> {
+ int dotCount = 0;
+ String[] dots = {".", "..", "...", ""};
+ while (isLoading) {
+ String currentTime = java.time.LocalTime.now()
+ .format(java.time.format.DateTimeFormatter.ofPattern("HH:mm:ss"));
+ String displayMessage = String.format("%s -- %s%s", currentTime, message, dots[dotCount % dots.length]);
+ dotCount++;
+ SwingUtilities.invokeLater(() -> {
+ html.clear();
+ html.append("p", displayMessage);
+ });
+ try {
+ Thread.sleep(300); // Update every half second
+ } catch (InterruptedException e) {
+ // Thread was interrupted
+ break;
+ }
+ }
+ });
+ loadingAnimationThread.start();
+ }
+
+ private void stopLoadingAnimation() {
+ isLoading = false;
+ if (loadingAnimationThread != null && loadingAnimationThread.isAlive()) {
+ loadingAnimationThread.interrupt();
+ }
}
+
private void interruptThreads() {
if (infoThread != null)
@@ -180,5 +223,10 @@ private void interruptThreads() {
if (modelInstallThread != null)
this.modelInstallThread.interrupt();
}
+
+ public interface ModelDrawerPanelListener {
+
+ void setGUIEnabled(boolean enabled);
+ }
}