ImageJ2: convert ImagePlus to Dataset


#1

Hey guys,

I’m trying to convert an ImagePlus to a Dataset. Maybe there is an easy way, but don’t see it. Furthermore, when using the convert service, I get an error message, I don’t understand. Furthermore, it’s hard to write a minimal working example. Nevertheless, maybe somebody knows where this error comes from. It might have something to do with co-existence of IJ1 and IJ2…

This is the code I’m trying to execute:

Dataset dataset = ij.convert().convert(new ImgPlus(ImageJFunctions.wrap(imp)), Dataset.class);

And this is the erorr message being thrown:

Exception in thread "Run$_main" java.lang.NullPointerException
	at net.imagej.legacy.convert.ImagePlusToImageDisplayConverter.canConvert(ImagePlusToImageDisplayConverter.java:75)
	at net.imagej.legacy.convert.ImagePlusToImageDisplayConverter.canConvert(ImagePlusToImageDisplayConverter.java:69)
	at net.imagej.legacy.convert.ImagePlusToImageDisplayConverter.canConvert(ImagePlusToImageDisplayConverter.java:81)
	at org.scijava.convert.AbstractConverter.canConvert(AbstractConverter.java:89)
	at org.scijava.convert.AbstractConverter.supports(AbstractConverter.java:144)
	at org.scijava.convert.AbstractConverter.supports(AbstractConverter.java:69)
	at org.scijava.plugin.HandlerService.getHandler(HandlerService.java:60)
	at org.scijava.convert.AbstractConvertService.getHandler(AbstractConvertService.java:67)
	at org.scijava.convert.AbstractConvertService.convert(AbstractConvertService.java:127)

#2

Hello again,

I think this is a bug in imagej-legacy. I filed a PR to fix it:

Cheers,
Robert


#3

I recall getting the same error, but searching through my scripts did not seem to show a workaround.

However! This seems to work. I tried it with a couple of the sample images (clown, bridge, mitosis).


#4

@haesleinhuepf The following Groovy script works for me:

#@ ConvertService convert
#@ ImagePlus imp

dataset = convert.convert(imp, net.imagej.Dataset.class)
println("Got the ImagePlus: " + imp)
println("Converted it to Dataset: " + dataset)
println("Dataset axes:")
for (d = 0; d < dataset.numDimensions(); d++) {
	println("\t" + d + ": " + dataset.axis(d).type() + " " + dataset.dimension(d))
}

With the Mitosis sample open, it prints:

Got the ImagePlus: img["mitosis.tif" (-7), 16-bit, 171x196x2x5x51]
Converted it to Dataset: mitosis.tif
Dataset axes:
	0: X 171
	1: Y 196
	2: Channel 2
	3: Z 5
	4: Time 51

Of course, you don’t have to explicitly invoke the converter in this particular case; you could just put #@ Dataset dataset in the script parameters as well, to have the Dataset version of the image. However, the script does illustrate how to do explicit conversion.


#5

Hey @ctrueden ,

unfortunately I work in an environment, where there is no ImageJ instance and no script editor. In order to run an ImageJ plugin (CSBDeep) I create an instance of net.imagej.ImageJ. Then, I tried to convert an arriving ImagePlus (or RandomAccessibleInterval) to a Dataset in order to feed it to ij.command().run(). Then, this error comes up while conversion.

However, the suggested PR fixes the issue in imagej-legacy. Do you have any idea when/why legacyService.getIJ1Helper() is null?

Thanks for your support!

Robert


#6

Hey @ctrueden,

I just saw your comments on the PR. I test it soon and will report back on github.

Thanks a lot!


#7

Just for documentation: The issue appears if one has several net.imagej.ImageJ instances and uses legacy code hidden in the second instance. You can prevent it by not using several ImageJs at a time. A better fix is one the way…


#8

Yes, exactly. Only one org.scijava.Context at a time can have a working LegacyService. If you create a second (or third or fourth…) one, it will have a half-baked LegacyService where the IJ1Helper is null.

If you are in a Java environment where an ImageJ2 has already been spun up, including the legacy layer, but you do not have access to the already-existing Context (or ImageJ gateway wrapping it), here is a hack you can use to ask (the patched) ImageJ1 for it:

Context context = (Context) IJ.runPlugIn("org.scijava.Context", "");
net.imagej.ImageJ ij = new net.imagej.ImageJ(context);
// AND/OR:
ConvertService convertService = context.service(ConvertService.class);

But please only use this trick in scenarios where it is impossible to keep a handle on the Context started elsewhere. It only works to retrieve the SciJava context associated with the currently-running ImageJ1.