[ImageJ-devel] Status and API of ROIs in ImageJ2 ?

Adrian Daerr adrian.daerr at univ-paris-diderot.fr
Thu Aug 27 10:25:55 CDT 2015


Hi Curtis,

> At this juncture, the most effective balance for most plugin
> developers is probably to use parameterized commands and/or scripts,
> but with the ImageJ1 data structures (ij.ImagePlus, etc.)

Ok, this is what I will do then.

> If all you care about is the bounding box of the active selection,
> you can just do it the same way as the ImageJ2 CropImageJ command:
> by calling OverlayService.getSelectionBounds [3].

Works great now ! When I had tried it before it had always returned
the whole image dimensions, but that was because the test code
generating the image and the selection was missing a step: after
adding the overlay (along the lines of the add-rois tutorial) I did
not select it. It returns the correct bounds now that I added the
following (taken from the source of one command in net.imageJ.plugins
[1]) just before calling the plugin:

         for (final net.imagej.display.DataView view : imageDisplay) {
             if (view instanceof net.imagej.display.OverlayView) {
                 view.setSelected(true);
             }
         }

[1] 
https://github.com/imagej/imagej-plugins-commands/blob/master/src/main/java/net/imagej/plugins/commands/display/DeselectOverlays.java?L65-L69

For the moment I use an ImagePlus in the rest of the plugin, but for
OverlayService.getSelectionBounds() I also declare an ImageDisplay as
an input parameter. I hope that the two are always populated in a way
that makes them point to the same (active?) image.

>> [..] but now the invocation of the plugin at the end of main() will
>> throw a MethodCallException with the stackTrace pasted below. How
>> can the choice of a UI make the plugin execution fail ?
> 
> In 2014, we made a conscious decision to support the ImageJ 1.x
> classes _only_ from the legacy UI.

Oh, thanks for the explanation! I'd never have guessed.

cheers,
Adrian



On Mon, 24 Aug 2015 16:22:15 -0500
  Curtis Rueden <ctrueden at wisc.edu> wrote:
> Hi Adrian,
> 
> Glad to hear you found a working solution!
> 
> The short answer about ROIs is that they have not been a focus of 
>ImageJ2
> or ImgLib2 development in recent years. Support for labelings 
>(highly
> related to ROIs) was rewritten this January [1], but a rewrite of 
>the core
> ImgLib2 ROI library [2] is still pending. And there is a substantial
> pending redesign of the ImageJ Common data model planned as well -- 
>though
> it is unlikely anyone will work on it this year.
> 
> At this juncture, the most effective balance for most plugin 
>developers is
> probably to use parameterized commands and/or scripts, but with the 
>ImageJ1
> data structures (ij.ImagePlus, etc.) -- unless you need access to a 
>new
> capability that ImageJ2 + ImgLib2 make possible (>5D images, very 
>large
> image planes, very large numbers of image planes, dynamically 
>generated
> images, images stored in places besides disk, cell-based image 
>caching,
> image types beyond uint8/uint16/float32, etc.).
> 
> That said, your feedback is very much appreciated.
> 
> And some issues will be ironed out in the next couple of weeks as we 
>revamp
> the tutorials for the upcoming ImageJ conference.
> 
>> The easiest way to give a plugin a (rectangular) roi is to ... just
>> declare a net.imagej.overlay.RectangularOverlay as an input 
>>parameter.
>> It is properly populated by the origin and extent of a rectangular
>> selection drawn on the active image.
> 
> If all you care about is the bounding box of the active selection, 
>you can
> just do it the same way as the ImageJ2 CropImageJ command: by 
>calling
> OverlayService.getSelectionBounds [3]. Then you would avoid some of 
>the
> current weirdness associated with Overlay parameters.
> 
>> If I launch the default UI, then the ROI will not show, but the 
>>plugin
>> can launch. If on the other hand I launch the "swing" UI as in the
>> tutorial, I do see the ROI
> 
> Yes, that tutorial was written when the ImageJ2 Swing UI was still 
>the
> default. It is not tested/working with the Legacy UI (which is now 
>the
> default). I will try to remedy that very soon.
> 
>> (not until I call Image>Adjust>Brightness/Contrast..., but that's a
>> minor detail),
> 
> Yes, that annoying bug has been around for quite a while. Many 
>things that
> refresh the display will do, such as pressing + then - to zoom 
>in/out.
> 
>> but now the invocation of the plugin at the end of main() will throw 
>>a
>> MethodCallException with the stackTrace pasted below. How can the
>> choice of a UI make the plugin execution fail ?
> ...
>> Caused by: java.lang.NullPointerException
>>         at Goutte_pendante.initTitle(Goutte_pendante.java:94)
> 
> In 2014, we made a conscious decision to support the ImageJ 1.x 
>classes
> _only_ from the legacy UI. You cannot use them from the Swing UI. In 
>your
> case: the ActiveImagePlusPreprocessor cannot set the active 
>ImagePlus
> because WindowManager.getCurrentImage() returns null [4], because no 
>ImageJ
> 1.x user interface exists. So it stays null and then your 
>initializer
> throws the NPE.
> 
> Regards,
> Curtis
> 
> [1]
> https://github.com/imglib/imglib2-roi/tree/imglib2-roi-0.3.2/src/main/java/net/imglib2/labeling
> 
> [2] https://github.com/imglib/imglib2-roi
> 
> [3]
> https://github.com/imagej/imagej-plugins-commands/blob/imagej-plugins-commands-0.5.1/src/main/java/net/imagej/plugins/commands/imglib/CropImage.java#L104
> 
> [4]
> https://github.com/imagej/imagej-legacy/blob/imagej-legacy-0.17.1/src/main/java/net/imagej/legacy/plugin/ActiveImagePlusPreprocessor.java#L49-L52
> 
> 
> On Sun, Aug 23, 2015 at 6:30 AM, Adrian Daerr <
> adrian.daerr at univ-paris-diderot.fr> wrote:
> 
>> Hello,
>>
>> While I am still interested in answers concerning the 
>>status/API/roadmap
>> for ROIs and overlays beyond what's on http://imagej.net/ROIs, I 
>>have
>> solved the problem at hand which was keeping me from making 
>>progress, so I
>> post the (rather obvious, once I found the net.imagej.overlay 
>>package)
>> solution here for the record and to close this thread.
>>
>> The easiest way to give a plugin a (rectangular) roi is to ...
>> just declare a net.imagej.overlay.RectangularOverlay as an input
>> parameter. It is properly populated by the origin and extent of a
>> rectangular selection drawn on the active image.
>>
>> cheers,
>> Adrian
>>
>>
>> On Wed, 19 Aug 2015 17:10:06 +0200
>>
>>  "Adrian Daerr" <adrian.daerr at univ-paris-diderot.fr> wrote:
>>
>>>
>>> Dear ImageJ developers,
>>>
>>> I have included code from the AddROIs tutorial into the main()
>>> method of my plugin (for the moment essentially one of Curtis'
>>> commands-with-preview example), to select a Rectangle before
>>> calling the plugin. The source is available here:
>>>
>>> https://gitlab.com/pendant-drop/pendant-drop
>>> (in Goutte_pendante.java)
>>>
>>> If I launch the default UI, then the ROI will not show, but the
>>> plugin can launch. If on the other hand I launch the "swing" UI
>>> as in the tutorial, I do see the ROI (not until I call
>>> Image>Adjust>Brightness/Contrast..., but that's a minor detail),
>>> but now the invocation of the plugin at the end of main() will
>>> throw a MethodCallException with the stackTrace pasted below. How
>>> can the choice of a UI make the plugin execution fail ?
>>>
>>> Is there any other way that main can set a ROI on a loaded image
>>> that the plugin, which still uses an ImagePlus as input
>>> parameter, will see when calling imp.getProcessor().getRoi() ?
>>>
>>> TIA
>>> Adrian
>>>
>>>
>>> $> mvn package
>>> $> fiji --class-path target/pendant_drop-2.0.0-SNAPSHOT.jar
>>> Goutte_pendante.class
>>> [INFO] Overriding About Pendant Drop; identifier:
>>> command:About_Pendant_Drop; jar:
>>> file:/home/adrian/Programmes/plugins_ImageJ_src/Traitement_Gouttes/target/pendant_drop-2.0.0-SNAPSHOT.jar
>>> [INFO] Overriding Pendant Drop; identifier: command:Goutte_pendante; 
>>>jar:
>>> file:/home/adrian/Programmes/plugins_ImageJ_src/Traitement_Gouttes/target/pendant_drop-2.0.0-SNAPSHOT.jar
>>> [INFO] Populating metadata
>>> [INFO] Populating metadata
>>> [INFO] Found 10 JHotDraw adapters.
>>> org.scijava.module.MethodCallException: Error executing method:
>>> Goutte_pendante#initTitle
>>>         at org.scijava.module.MethodRef.execute(MethodRef.java:73)
>>>         at
>>> org.scijava.module.AbstractModuleItem.initialize(AbstractModuleItem.java:199)
>>>         at
>>> org.scijava.module.AbstractModule.initialize(AbstractModule.java:86)
>>>         at
>>> org.scijava.command.CommandModule.initialize(CommandModule.java:147)
>>>         at
>>> org.scijava.module.process.InitPreprocessor.process(InitPreprocessor.java:60)
>>>         at
>>> org.scijava.module.ModuleRunner.preProcess(ModuleRunner.java:104)
>>>         at 
>>>org.scijava.module.ModuleRunner.run(ModuleRunner.java:156)
>>>         at 
>>>org.scijava.module.ModuleRunner.call(ModuleRunner.java:126)
>>>         at 
>>>org.scijava.module.ModuleRunner.call(ModuleRunner.java:65)
>>>         at
>>> org.scijava.thread.DefaultThreadService$2.call(DefaultThreadService.java:191)
>>>         at
>>> java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
>>>         at java.util.concurrent.FutureTask.run(FutureTask.java:138)
>>>         at
>>> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
>>>         at
>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
>>>         at java.lang.Thread.run(Thread.java:662)
>>> Caused by: java.lang.reflect.InvocationTargetException
>>>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native 
>>>Method)
>>>         at
>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>>         at
>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>>         at java.lang.reflect.Method.invoke(Method.java:597)
>>>         at org.scijava.module.MethodRef.execute(MethodRef.java:69)
>>>         ... 14 more
>>> Caused by: java.lang.NullPointerException
>>>         at Goutte_pendante.initTitle(Goutte_pendante.java:94)
>>>         ... 19 more
>>> [ERROR] Module threw exception
>>> java.lang.NullPointerException
>>>         at Goutte_pendante.cancel(Goutte_pendante.java:87)
>>>         at
>>> org.scijava.command.CommandModule.cancel(CommandModule.java:140)
>>>         at
>>> org.scijava.module.ModuleRunner.cleanupAndBroadcastCancelation(ModuleRunner.java:189)
>>>         at 
>>>org.scijava.module.ModuleRunner.run(ModuleRunner.java:161)
>>>         at 
>>>org.scijava.module.ModuleRunner.call(ModuleRunner.java:126)
>>>         at 
>>>org.scijava.module.ModuleRunner.call(ModuleRunner.java:65)
>>>         at
>>> org.scijava.thread.DefaultThreadService$2.call(DefaultThreadService.java:191)
>>>         at
>>> java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
>>>         at java.util.concurrent.FutureTask.run(FutureTask.java:138)
>>>         at
>>> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
>>>         at
>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
>>>         at java.lang.Thread.run(Thread.java:662)
>>>
>>>
>>>
>>> On Sat, 15 Aug 2015 13:14:13 +0200
>>>  Adrian Daerr <adrian.daerr at univ-paris-diderot.fr> wrote:
>>>
>>>> Hello,
>>>>
>>>> I am seizing a major rewrite of a plugin as an opportunity to switch
>>>> from ImageJ1 to ImageJ2, also to avoid concurrency issues[*], and 
>>>>now
>>>> lots of questions come up. Some concern the way ROIs are handled. 
>>>>What
>>>> has happened in this regard since
>>>>   http://imagej.net/ROIs
>>>> was last updated ?
>>>>
>>>> [*] cf discussion on the ImageJ list archived at
>>>>
>>>> http://imagej.1557.x6.nabble.com/ExtendedPlugInFilter-GenericDialog-and-synchronization-td5013333.html
>>>>
>>>> Here are two concrete questions:
>>>>
>>>> 1) My plugin relies on a rectangular ROI being drawn on the image to
>>>> know which area to include in the computation. How do I draw this 
>>>>ROI
>>>> once I have loaded the image as a dataset in the main() method that 
>>>>is
>>>> used for testing purposes ?
>>>>
>>>> public static void main(final String... args) throws Exception {
>>>>     final String testImagePath = "testImage.jpg";
>>>>
>>>>     // Launch ImageJ as usual.
>>>>     final ImageJ ij = net.imagej.Main.launch(args);
>>>>
>>>>     // Open test image.
>>>>     final Dataset dataset = ij.dataset().open(testImagePath);
>>>>
>>>>     // display the dataset
>>>>     ij.ui().show(dataset);
>>>>
>>>>     // create rectangular ROI
>>>>     //imp.setRoi(120,60,340,420);// How to do this on a dataset ?
>>>>
>>>>     // Launch the "Foo_Bar" command.
>>>>     ij.command().run(Foo_Bar.class, true);
>>>> }
>>>>
>>>> (alternatively, how would I generate a new dataset, or I guess 
>>>>something
>>>> like a "View" in ImageJ2 terminology, of the ROI sub-image of the 
>>>>original
>>>> dataset ? I could then substitute the original dataset with this 
>>>>sub-image
>>>> and have the plugin operate on the whole image by default)
>>>>
>>>> 2) The plugin preview generates overlays using java.awt.geom.Path2D,
>>>> java.awt.geom.Area and java.awt.Shape, which are then converted via
>>>> ij.gui.ShapeRoi() and ij.gui.Overlay(), assembled with 
>>>>overlay.add(),
>>>> and drawn using imp.setOverlay(). Is there a new IJ2-way to do this
>>>> (especially since the cited web page (rightly) insists on separation
>>>> of selection and visualisation shapes) ?
>>>>
>>>> TIA,
>>>> Adrian
>>>>
>>>> _______________________________________________
>>>> ImageJ-devel mailing list
>>>> ImageJ-devel at imagej.net
>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>
>>>
>>> --
>>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>>
>>> _______________________________________________
>>> ImageJ-devel mailing list
>>> ImageJ-devel at imagej.net
>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>
>>
>> --
>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>
>> _______________________________________________
>> ImageJ-devel mailing list
>> ImageJ-devel at imagej.net
>> http://imagej.net/mailman/listinfo/imagej-devel
>>

-- 
http://www.msc.univ-paris-diderot.fr/~daerr/



More information about the ImageJ-devel mailing list