Status and API of ROIs in ImageJ2 ?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Status and API of ROIs in ImageJ2 ?

Adrian Daerr
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
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: Status and API of ROIs in ImageJ2 ?

Adrian Daerr

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 <[hidden email]> 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
> [hidden email]
> http://imagej.net/mailman/listinfo/imagej-devel

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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: Status and API of ROIs in ImageJ2 ?

Adrian Daerr
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" <[hidden email]> 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 <[hidden email]> 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
>> [hidden email]
>> http://imagej.net/mailman/listinfo/imagej-devel
>
> --
> http://www.msc.univ-paris-diderot.fr/~daerr/
>
> _______________________________________________
> ImageJ-devel mailing list
> [hidden email]
> http://imagej.net/mailman/listinfo/imagej-devel

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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: Status and API of ROIs in ImageJ2 ?

Curtis Rueden
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





On Sun, Aug 23, 2015 at 6:30 AM, Adrian Daerr <[hidden email]> 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" <[hidden email]> 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 <[hidden email]> 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
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: Status and API of ROIs in ImageJ2 ?

Adrian Daerr
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 <[hidden email]> 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 <
> [hidden email]> 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" <[hidden email]> 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 <[hidden email]> 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
>>>> [hidden email]
>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>
>>>
>>> --
>>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>>
>>> _______________________________________________
>>> ImageJ-devel mailing list
>>> [hidden email]
>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>
>>
>> --
>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>
>> _______________________________________________
>> ImageJ-devel mailing list
>> [hidden email]
>> http://imagej.net/mailman/listinfo/imagej-devel
>>

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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: Status and API of ROIs in ImageJ2 ?

Adrian Daerr
In reply to this post by Curtis Rueden
Hi Curtis, hi all,

> 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. Then you would
> avoid some of the current weirdness associated with Overlay
> parameters.

This was working fine with a programmatically added rectangular
overlay/selection, but when I call getSelectionBounds on an image with
an interactively created rectangular selection it returns the whole
image dimension. It does not seem to be aware of the ROI. Below is a
MVCE to reproduce. After compiling and placing it in the plugins
folder, I start imagej, create a new image, draw a rectangular
selection using ImageJ's leftmost tool and then invoque the plugin. It
logs the following to the console:

[WARNING] ====> Roi class = ij.gui.Roi
[WARNING] ====> RECTANGLE: Roi[Rectangle, x=100, y=163, width=196,
height=112]
[INFO] image: plugin:class net.imagej.display.DefaultImageDisplay:
type=interface net.imagej.display.DataView, name=Untitled,
objects={net.imagej.display.DefaultDatasetView@757dbeaf,
net.imagej.display.DefaultOverlayView@2198a037}
[INFO] region: +0.0 +0.0, 559.0 x 559.0

I expected the region in the last line (that obtained through
OverlayService.getSelectionBounds) to coincide with the Roi mentionned
in the WARNING.

The CropImage command you mentionned does not do anything either
before calling getSelectionBounds, and cropping works fine. Do you
understand what is going on ?

Cheers,
Adrian


import net.imagej.display.ImageDisplay;
import net.imagej.display.OverlayService;

import org.scijava.command.Command;
import org.scijava.log.LogService;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import org.scijava.util.RealRect;

@Plugin(type = Command.class, menuPath = "Plugins>Foo_Bar")
public class Foo_Bar implements Command {

     @Parameter
     private ImageDisplay display;

     @Parameter
     private OverlayService overlayService;

     @Parameter
     private LogService log;

     @Override
     public void run() {
         RealRect r = overlayService.getSelectionBounds(display);
         log.info("image: "+display);
         log.info("region: +" + r.x + " +" +  r.y
                  + ", " +  r.width + " x " + r.height);
     }
}




On Mon, 24 Aug 2015 16:22:15 -0500
  Curtis Rueden <[hidden email]> 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 <
> [hidden email]> 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" <[hidden email]> 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 <[hidden email]> 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
>>>> [hidden email]
>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>
>>>
>>> --
>>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>>
>>> _______________________________________________
>>> ImageJ-devel mailing list
>>> [hidden email]
>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>
>>
>> --
>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>
>> _______________________________________________
>> ImageJ-devel mailing list
>> [hidden email]
>> http://imagej.net/mailman/listinfo/imagej-devel
>>

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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: Status and API of ROIs in ImageJ2 ?

Adrian Daerr
Hi Curtis,

OverlayService.getSelectionBounds seems to behave stranger yet. Take
the Foo_Bar test plugin source from my previous post, compile it and
place it in ImageJ's plugins directory. Start ImageJ, create a new
image (say 400x400 8bpp), draw a rectangular selection inside and
invoke Foo_Bar: as reported in my last mail it will report a
 getSelectionBounds of 399x399 instead of the expected dimension of
the rectangular selection. Now crop the image to the rectangular
selection via Image->Crop, and invoke Foo_Bar again. It will report
the same getSelectionBounds (width 399, height 399) although the
active image is now strictly smaller. It's as if the ImageDisplay
parameter was getting populated by the image before cropping (and of
course still without rectangular selection).

How is one supposed to use OverlayService.getSelectionBounds ?
What are those WARNINGs printed upon plugin invokation ?

[WARNING] ====> Roi class = ij.gui.Roi
[WARNING] ====> RECTANGLE: Roi[Rectangle, x=76, y=92, width=209,
height=160]

cheers,
Adrian


On Tue, 01 Sep 2015 20:41:30 +0200
  "Adrian Daerr" <[hidden email]> wrote:

> Hi Curtis, hi all,
>
>> 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. Then you would
>> avoid some of the current weirdness associated with Overlay
>> parameters.
>
> This was working fine with a programmatically added rectangular
>overlay/selection, but when I call getSelectionBounds on an image
>with an interactively created rectangular selection it returns the
>whole image dimension. It does not seem to be aware of the ROI. Below
>is a MVCE to reproduce. After compiling and placing it in the plugins
>folder, I start imagej, create a new image, draw a rectangular
>selection using ImageJ's leftmost tool and then invoque the plugin.
>It logs the following to the console:
>
> [WARNING] ====> Roi class = ij.gui.Roi
> [WARNING] ====> RECTANGLE: Roi[Rectangle, x=100, y=163, width=196,
>height=112]
> [INFO] image: plugin:class net.imagej.display.DefaultImageDisplay:
>type=interface net.imagej.display.DataView, name=Untitled,
>objects={net.imagej.display.DefaultDatasetView@757dbeaf,
>net.imagej.display.DefaultOverlayView@2198a037}
> [INFO] region: +0.0 +0.0, 559.0 x 559.0
>
> I expected the region in the last line (that obtained through
>OverlayService.getSelectionBounds) to coincide with the Roi
>mentionned in the WARNING.
>
> The CropImage command you mentionned does not do anything either
>before calling getSelectionBounds, and cropping works fine. Do you
>understand what is going on ?
>
> Cheers,
> Adrian
>
>
> import net.imagej.display.ImageDisplay;
> import net.imagej.display.OverlayService;
>
> import org.scijava.command.Command;
> import org.scijava.log.LogService;
> import org.scijava.plugin.Parameter;
> import org.scijava.plugin.Plugin;
> import org.scijava.util.RealRect;
>
> @Plugin(type = Command.class, menuPath = "Plugins>Foo_Bar")
> public class Foo_Bar implements Command {
>
>     @Parameter
>     private ImageDisplay display;
>
>     @Parameter
>     private OverlayService overlayService;
>
>     @Parameter
>     private LogService log;
>
>     @Override
>     public void run() {
>         RealRect r = overlayService.getSelectionBounds(display);
>         log.info("image: "+display);
>         log.info("region: +" + r.x + " +" +  r.y
>                  + ", " +  r.width + " x " + r.height);
>     }
> }
>
>
>
>
> On Mon, 24 Aug 2015 16:22:15 -0500
>  Curtis Rueden <[hidden email]> 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 <
>> [hidden email]> 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" <[hidden email]> 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 <[hidden email]> 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
>>>>> [hidden email]
>>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>>
>>>>
>>>> --
>>>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>>>
>>>> _______________________________________________
>>>> ImageJ-devel mailing list
>>>> [hidden email]
>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>
>>>
>>> --
>>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>>
>>> _______________________________________________
>>> ImageJ-devel mailing list
>>> [hidden email]
>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>
>
> --
> http://www.msc.univ-paris-diderot.fr/~daerr/

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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: Status and API of ROIs in ImageJ2 ?

Curtis Rueden
Hi Adrian,

> It's as if the ImageDisplay parameter was getting populated by the
> image before cropping

It seems that the ROI syncing between IJ1 and IJ2 is not happening as expected. When your command runs, a sync is supposed to happen during preprocessing because you have a Dataset parameter. But maybe the sync is incomplete for some reason. Sorry I don't have time to investigate it right now, though.

What are those WARNINGs printed upon plugin invokation ?

Those were debugging statements, which were erroneously set to log.warn. I fixed it [1].

Regards,
Curtis


On Fri, Sep 4, 2015 at 2:29 PM, Adrian Daerr <[hidden email]> wrote:
Hi Curtis,

OverlayService.getSelectionBounds seems to behave stranger yet. Take the Foo_Bar test plugin source from my previous post, compile it and place it in ImageJ's plugins directory. Start ImageJ, create a new image (say 400x400 8bpp), draw a rectangular selection inside and invoke Foo_Bar: as reported in my last mail it will report a getSelectionBounds of 399x399 instead of the expected dimension of the rectangular selection. Now crop the image to the rectangular selection via Image->Crop, and invoke Foo_Bar again. It will report the same getSelectionBounds (width 399, height 399) although the active image is now strictly smaller. It's as if the ImageDisplay parameter was getting populated by the image before cropping (and of course still without rectangular selection).

How is one supposed to use OverlayService.getSelectionBounds ?
What are those WARNINGs printed upon plugin invokation ?

[WARNING] ====> Roi class = ij.gui.Roi
[WARNING] ====> RECTANGLE: Roi[Rectangle, x=76, y=92, width=209, height=160]

cheers,
Adrian


On Tue, 01 Sep 2015 20:41:30 +0200

 "Adrian Daerr" <[hidden email]> wrote:
Hi Curtis, hi all,

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. Then you would
avoid some of the current weirdness associated with Overlay
parameters.

This was working fine with a programmatically added rectangular overlay/selection, but when I call getSelectionBounds on an image with an interactively created rectangular selection it returns the whole image dimension. It does not seem to be aware of the ROI. Below is a MVCE to reproduce. After compiling and placing it in the plugins folder, I start imagej, create a new image, draw a rectangular selection using ImageJ's leftmost tool and then invoque the plugin. It logs the following to the console:

[WARNING] ====> Roi class = ij.gui.Roi
[WARNING] ====> RECTANGLE: Roi[Rectangle, x=100, y=163, width=196, height=112]
[INFO] image: plugin:class net.imagej.display.DefaultImageDisplay: type=interface net.imagej.display.DataView, name=Untitled, objects={net.imagej.display.DefaultDatasetView@757dbeaf, net.imagej.display.DefaultOverlayView@2198a037}
[INFO] region: +0.0 +0.0, 559.0 x 559.0

I expected the region in the last line (that obtained through OverlayService.getSelectionBounds) to coincide with the Roi mentionned in the WARNING.

The CropImage command you mentionned does not do anything either before calling getSelectionBounds, and cropping works fine. Do you understand what is going on ?

Cheers,
Adrian


import net.imagej.display.ImageDisplay;
import net.imagej.display.OverlayService;

import org.scijava.command.Command;
import org.scijava.log.LogService;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import org.scijava.util.RealRect;

@Plugin(type = Command.class, menuPath = "Plugins>Foo_Bar")
public class Foo_Bar implements Command {

    @Parameter
    private ImageDisplay display;

    @Parameter
    private OverlayService overlayService;

    @Parameter
    private LogService log;

    @Override
    public void run() {
        RealRect r = overlayService.getSelectionBounds(display);
        log.info("image: "+display);
        log.info("region: +" + r.x + " +" +  r.y
                 + ", " +  r.width + " x " + r.height);
    }
}




On Mon, 24 Aug 2015 16:22:15 -0500
 Curtis Rueden <[hidden email]> 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 <
[hidden email]> 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" <[hidden email]> 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 <[hidden email]> 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
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


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

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


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Parameter synchronisation IJ1<->IJ2 (was: Status and API of ROIs in ImageJ2 ?)

Adrian Daerr
Dear Curtis,

Thanks for the explanation. Don't worry about debugging this, I
worked around this by using imp.getRoi() if non-null and
overlayService.getSelectionBounds() otherwise [1] (and the image
size if the latter is larger than the image [2]), which is
resilient enough to work in all cases.

regards,
Adrian


[1]
https://github.com/adaerr/pendent-drop/commit/6bd16ab181154d6c28d776f7ca935ebe961ccc44
[2]
https://github.com/adaerr/pendent-drop/commit/97a69c086ae383dae0014f74a1f15f0499330c44


On Thu, 24 Sep 2015 12:04:51 -0500
  Curtis Rueden <[hidden email]> wrote:

> Hi Adrian,
>
>> It's as if the ImageDisplay parameter was getting populated by the
>> image before cropping
>
> It seems that the ROI syncing between IJ1 and IJ2 is not happening
>as
> expected. When your command runs, a sync is supposed to happen
>during
> preprocessing because you have a Dataset parameter. But maybe the
>sync is
> incomplete for some reason. Sorry I don't have time to investigate
>it right
> now, though.
>
>> What are those WARNINGs printed upon plugin invokation ?
>
> Those were debugging statements, which were erroneously set to
>log.warn. I
> fixed it [1].
>
> Regards,
> Curtis
>
> [1]
> https://github.com/imagej/imagej-legacy/commit/2015336482fe284954d2603fede892d616d20960
>
> On Fri, Sep 4, 2015 at 2:29 PM, Adrian Daerr <
> [hidden email]> wrote:
>
>> Hi Curtis,
>>
>> OverlayService.getSelectionBounds seems to behave stranger yet. Take
>>the
>> Foo_Bar test plugin source from my previous post, compile it and
>>place it
>> in ImageJ's plugins directory. Start ImageJ, create a new image (say
>> 400x400 8bpp), draw a rectangular selection inside and invoke
>>Foo_Bar: as
>> reported in my last mail it will report a getSelectionBounds of
>>399x399
>> instead of the expected dimension of the rectangular selection. Now
>>crop
>> the image to the rectangular selection via Image->Crop, and invoke
>>Foo_Bar
>> again. It will report the same getSelectionBounds (width 399, height
>>399)
>> although the active image is now strictly smaller. It's as if the
>> ImageDisplay parameter was getting populated by the image before
>>cropping
>> (and of course still without rectangular selection).
>>
>> How is one supposed to use OverlayService.getSelectionBounds ?
>> What are those WARNINGs printed upon plugin invokation ?
>>
>> [WARNING] ====> Roi class = ij.gui.Roi
>> [WARNING] ====> RECTANGLE: Roi[Rectangle, x=76, y=92, width=209,
>> height=160]
>>
>> cheers,
>> Adrian
>>
>>
>> On Tue, 01 Sep 2015 20:41:30 +0200
>>
>>  "Adrian Daerr" <[hidden email]> wrote:
>>
>>> Hi Curtis, hi all,
>>>
>>> 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. Then you would
>>>> avoid some of the current weirdness associated with Overlay
>>>> parameters.
>>>>
>>>
>>> This was working fine with a programmatically added rectangular
>>> overlay/selection, but when I call getSelectionBounds on an image
>>>with an
>>> interactively created rectangular selection it returns the whole
>>>image
>>> dimension. It does not seem to be aware of the ROI. Below is a MVCE
>>>to
>>> reproduce. After compiling and placing it in the plugins folder, I
>>>start
>>> imagej, create a new image, draw a rectangular selection using
>>>ImageJ's
>>> leftmost tool and then invoque the plugin. It logs the following to
>>>the
>>> console:
>>>
>>> [WARNING] ====> Roi class = ij.gui.Roi
>>> [WARNING] ====> RECTANGLE: Roi[Rectangle, x=100, y=163, width=196,
>>> height=112]
>>> [INFO] image: plugin:class net.imagej.display.DefaultImageDisplay:
>>> type=interface net.imagej.display.DataView, name=Untitled,
>>> objects={net.imagej.display.DefaultDatasetView@757dbeaf,
>>> net.imagej.display.DefaultOverlayView@2198a037}
>>> [INFO] region: +0.0 +0.0, 559.0 x 559.0
>>>
>>> I expected the region in the last line (that obtained through
>>> OverlayService.getSelectionBounds) to coincide with the Roi
>>>mentionned in
>>> the WARNING.
>>>
>>> The CropImage command you mentionned does not do anything either
>>>before
>>> calling getSelectionBounds, and cropping works fine. Do you
>>>understand what
>>> is going on ?
>>>
>>> Cheers,
>>> Adrian
>>>
>>>
>>> import net.imagej.display.ImageDisplay;
>>> import net.imagej.display.OverlayService;
>>>
>>> import org.scijava.command.Command;
>>> import org.scijava.log.LogService;
>>> import org.scijava.plugin.Parameter;
>>> import org.scijava.plugin.Plugin;
>>> import org.scijava.util.RealRect;
>>>
>>> @Plugin(type = Command.class, menuPath = "Plugins>Foo_Bar")
>>> public class Foo_Bar implements Command {
>>>
>>>     @Parameter
>>>     private ImageDisplay display;
>>>
>>>     @Parameter
>>>     private OverlayService overlayService;
>>>
>>>     @Parameter
>>>     private LogService log;
>>>
>>>     @Override
>>>     public void run() {
>>>         RealRect r = overlayService.getSelectionBounds(display);
>>>         log.info("image: "+display);
>>>         log.info("region: +" + r.x + " +" +  r.y
>>>                  + ", " +  r.width + " x " + r.height);
>>>     }
>>> }
>>>
>>>
>>>
>>>
>>> On Mon, 24 Aug 2015 16:22:15 -0500
>>>  Curtis Rueden <[hidden email]> 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 <
>>>> [hidden email]> 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" <[hidden email]> 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 <[hidden email]> 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
>>>>>>> [hidden email]
>>>>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>>>>
>>>>>>>
>>>>>> --
>>>>>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>>>>>
>>>>>> _______________________________________________
>>>>>> ImageJ-devel mailing list
>>>>>> [hidden email]
>>>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>>>
>>>>>>
>>>>> --
>>>>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>>>>
>>>>> _______________________________________________
>>>>> ImageJ-devel mailing list
>>>>> [hidden email]
>>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>>
>>>>>
>>> --
>>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>>
>>
>> --
>> http://www.msc.univ-paris-diderot.fr/~daerr/
>>

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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel