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