ImageJ ops Auto Local Threshold

Hi all,

I’m working with NetBeans IDE 8.1 to develop an ImageJ plugin which I’m currently trying to implement ImageJ’s Auto Local Threshold. I have the plugin’s dependencies set as follows in the pom.xml file:

<dependencies>
	<dependency>
		<groupId>net.imagej</groupId>
		<artifactId>ij</artifactId>
		<version>1.48s</version>
	</dependency>
</dependencies>  

When I launch this plugin in ImageJ, I’m unable to locate the AutoLocalThreshold function and use the macro recorder to generate the appropriate code. Any idea how I can change the dependencies to have access to this function/ insert the code on my own so when I finish the plugin it will work even if AutoLocalThreshold isn’t installed?

Thanks!

  • Press L for the Command Finder
  • Start typing “auto local threshold” into the search box
  • When the result pops up, resize the columns so you can fully read the “File” column.
  • It will be something like Auto_Threshold-1.16.2.jar.
  • Note also that the class begins with fiji. which means this is a Fiji plugin, not part of core ImageJ.

Therefore, we can conclude this plugin is available in the Fiji organization on GitHub. Here it is:

So your Maven dependency will be:

<dependency>
  <groupId>sc.fiji</groupId>
  <artifactId>Auto_Threshold</artifactId>
</dependency>

If you extend or import pom-fiji into your POM, you can leave off the <version> because it is managed.

P.S. Another easy way of finding the code is to visit http://search.imagej.net/ and type in “Auto Local Threshold” and click the GitHub button, and you will see the fiji/Auto_Threshold repository pop up as well.

1 Like

Okay, that makes sense for the most part. Elaborating on that though, how would I extend/import pom-fiji into my POM?

Ideally, I would like to learn how to set something up that gives me full access to fiji’s functions, not just the Auto_Threshold function so I can readily apply it to future projects.

Thanks for all the help!

Ryan

Extend

<parent>
  <groupId>sc.fiji</groupId>
  <artifactId>pom-fiji</artifactId>
  <version>24.0.0</version>
</parent>

Extending inherits everything. You will want to override several configuration blocks if you do that: “Projects wishing to use pom-fiji as a parent project need to override the <name>, <description>, <url>, <inceptionYear>, <organization>, <licenses>, <developers>, <scm>, <issueManagement> and <ciManagement> sections.”

Import

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>sc.fiji</groupId>
      <artifactId>pom-fiji</artifactId>
      <version>24.0.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Importing inherits only the version management of the Fiji components. This will let you leave off the <version> of any managed component, but will not inherit plugin configuration etc.

Which one is better?

I recommend extending pom-fiji if you are just getting started with Maven. If you already know what you are doing with Maven, and want to extend a different parent POM, then importing pom-fiji is the way to go, since Maven only supports single inheritance.

There is a component sc.fiji:fiji which inherits everything, but we have never cut a release of it. One reason is: we assumed no one would want to bring in the entire Fiji project as a dependency. It is really a lot of components. Better to cherry pick the ones you are actually using in your project.

1 Like

Great, the clarification between the two really helps! Lastly when I try and extend fiji to my plugin as shown,

I get the following error:

(C:\Users\reberya\Documents\NetBeansProjects\minimal-ij1-plugin\pom.xml) has 1 error
Non-resolvable parent POM: Failure to find sc.fiji:pom-fiji:pom:24.0.0 in http://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced and ‘parent.relativePath’ points at wrong local POM @ line 8, column 10 -> [Help 2]

The sc.fiji:pom-fiji artifact is only available from the ImageJ Maven repository—not from Maven Central. So you also need to add this block to your POM:

<repositories>
  <!-- NB: for project parent -->
  <repository>
    <id>imagej.public</id>
    <url>http://maven.imagej.net/content/groups/public</url>
  </repository>
</repositories>

Please see the ImageJ website’s Maven page for more information about using Maven with ImageJ.

You may need to invoke Maven with the -U switch (or in Eclipse: “Update Maven Project” with “Force updates of snapshots and releases” checked).

This error is my fault; I got the invocation slightly wrong for the parent. It should be:

<parent>
  <groupId>sc.fiji</groupId>
  <artifactId>pom-fiji</artifactId>
  <version>24.0.0</version>
  <relativePath/>
</parent>

The <relativePath/> is important: it says “the parent POM is not in my local directory structure here” and in particular, it is not at .. which is the default.

1 Like

@ctrueden I think I’m finally starting to understand maven a bit more, but am still unable to get the Auto Threshold function or any of the other fiji functions within my plugin. I have tried updating my POM as follows:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
		http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

        <parent>
            <groupId>sc.fiji</groupId>
            <artifactId>pom-fiji</artifactId>
             <version>24.0.0</version>
             <relativePath/>

</parent> 

    	<groupId>sc.fiji</groupId>
    	<artifactId>My_Plugin</artifactId>
    	<version>0.1.0-SNAPSHOT</version>

    	<name>My_Plugin</name>
    	<description>A Maven project implementing Fiji plugin</description>

    	<properties>
    		<main-class>My_Plugin</main-class>
    	</properties>

    	<dependencies>
    		<dependency>
    			<groupId>net.imagej</groupId>
    			<artifactId>ij</artifactId>
    		</dependency>
                    
                    <dependency>
                          <groupId>sc.fiji</groupId>
                          <artifactId>Auto_Threshold</artifactId>
                    </dependency>
                    
    	</dependencies>

    	<build>
    		<plugins>
    			<plugin>
    				<artifactId>maven-jar-plugin</artifactId>
    				<configuration>
    					<archive>
    						<manifest>
    							<mainClass>${main-class}</mainClass>
    						</manifest>
    					</archive>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
            
            <repositories>
                <!-- NB: for project parent -->
                <repository>
                     <id>imagej.public</id>
                     <url>http://maven.imagej.net/content/groups/public</url>
                </repository>
            </repositories>
            
    </project>

Thank you for your help with this, utilizing Maven has proved quite challenging for me.

How are you launching ImageJ? Like this?

Yes I am doing essentially the same format as the minimal plugin but do not automatically load a sample image or run the plugin. This is the only portion of the code I am using:

	public static void main(String[] args) {
		// set the plugins.dir property to make the plugin appear in the Plugins menu

		Class<?> clazz = Process_Pixels.class;
		String url = clazz.getResource("/" + clazz.getName().replace('.', '/') + ".class").toString();
		String pluginsDir = url.substring("file:".length(), url.length() - clazz.getName().length() - ".class".length());
		System.setProperty("plugins.dir", pluginsDir);

		// start ImageJ
		new ImageJ();

Then I typically launch my main class and manually load and image and run the plugin from the menu.

Is your source on GitHub somewhere, so that we can troubleshoot in more detail?

Yes, my source code is located here: https://github.com/reberya/My-Plugin

It is identical to the code forked from the imageJ minimal plugin outside of changes I made to the original ProcessPixels.java (now My_Plugin.java) and the pom.xml file.

Thanks again for your help!

Thanks for posting it, @reberya. I’m sorry to say I am now entering an insanely busy time for the next two months, so will not have time to help troubleshoot this further with you. I hope someone else here on the forum can take a quick look.

Hey @reberya why not to use directly the autothreshold of the image processor instead of the ij.run one??


    ImageProcessor ip2 = imp.getProcessor();
    ip2.setAutoThreshold(AutoThresholder.Method.Mean, true);

1 Like

Hi @reberya,

as pointed out by @BishopWolf you could use the ImageJ API (as described in his/her answer) but that wouldn’t solve your problem since you are still trying to use Fiji functionality. To answer your question of why is your setup is not working properly you’ll have to dig a little deeper into how to invoke plugins.

Currently, you are using IJ.run in My_Plugin.java#L40, which calls menu entries (bluntly speaking). When you execute your plugin from Netbeans and use the Command Finder in ImageJ to look for “Auto Threshold” you won’t have any luck. This is due to the fact that your main method fires up ImageJ and sets up the plugins.dir (which is the directory in which ImageJ looks for plugins) to the location where your compiled My_Plugin.class is located, see My_Plugin.java#L64-L67.

For the IJ.run mechanism to work you’d have to come up with a more sophisticated version of how to define the plugins directory which I have not tried to achieve before…

The more appropriate way to execute the Auto Threshold would be to use the Java API of the plugin that you have already added as Maven dependency by invoking Auto_Threshold.exec .

Best,
Stefan

1 Like

@BishopWolf and @stelfrich thank you both for the insight.

@BishopWolf: Like Stefan mentioned, when I tried to use the sample code that you posted I was met with the error, “img[currimage” is not a valid choice for “Redirect to:” - I’m guessing this has something to do with the program calling something it doesn’t have access to through ImageJ’s functionality?

@stelfrich: The explanation you gave regarding why the IJ.run mechanism did not work makes perfect sense. Could you elaborate a bit more on how to invoke Auto_Threshold.exec within the plugin to access its functionality?

Thanks again for the thoughts!

Ryan

1 Like

You have to define imp, at least you must have an image opened. imp is an object that implements an ImagePlus class. in case you have an image opened it is automatically assigned to imp at plugin start, otherwise you get this error

@BishopWolf

I currently have imp defined within my plugin where it should set the open image to imp. Is this what you mean?

public class My_Plugin implements PlugIn {
ImagePlus imp;

public void run (String args) {
   
 //get the image
 imp = IJ.getImage();
 imp.setTitle("currImage");
 
 //copy the image
 //segmentation

ImageProcessor ip2 = imp.getProcessor();
ip2.setAutoThreshold(AutoThresholder.Method.Mean, true); 

Even when I have imp defined like this it still gives the error message:

Thanks for the thoughts!

why did you implement PlugIn instead of PlugInFilter?? whatch my codes at https://github.com/BishopWolf/NMQC for examples, specially in the class https://github.com/BishopWolf/NMQC/blob/master/src/main/java/utils/Commons.java, the functions getThreshold line 152 and getObject line 185. I hope this helps you

That has actually nothing to do with the thresholding but is a problem with Set Measurements... in L44. I think (although I have not tested it) that it expects the title of an open image. That is, you should replace imp with imp.getTitle() and see if it works.

You can, however, also invoke methods of the ParticleAnalyzer directly. This class implements the menu entry Analyze Particles and should provide the functionality you are looking for. You can provide the measurement options through the ParticleAnalyzer(int options, int measurements, ResultsTable rt, double minSize, double maxSize, double minCirc, double maxCirc) construtor. The second argument for your case would for example be Measurements.AREA | Measurements.MEAN | Measurements.STD_DEV | Measurements.MIN_MAX | Measurements.SHAPE_DESCRIPTORS. You can find details on those constants in the Measurements Javadoc.

Best,
Stefan

1 Like

@reberya it should be sufficient to configure your Eclipse environment to run your plugin in an existing ImageJ installation to test your plugin.

Replacing all your IJ.run() calls with direct calls to the underlying libraries is overly complicated and should not be necessary for a simple plugin.

3 Likes