imagej / imagej-legacy

ImageJ+ImageJ2 compatibility layer
https://imagej.net/libs/imagej-legacy
BSD 2-Clause "Simplified" License
16 stars 25 forks source link

Add converters between ImgLib2 RAI and ImageJ1 ImagePlus #229

Open ctrueden opened 4 years ago

ctrueden commented 4 years ago

There are converters for Dataset to/from ImagePlus (though see #186). But if you have e.g. an ArrayImg, you cannot currently convert it directly to ImagePlus with the ConvertService. We want this to be possible.

imagejan commented 4 years ago

I guess this can be done with the new AbstractDelegateConverter introduced in https://github.com/scijava/scijava-common/pull/366, right?

Which conversions need to be supported explicitly?

ctrueden commented 4 years ago

I think the delegate converter will be useful, yeah. Thanks for developing it.

For new converters needed:

  1. ImgPlus to ImagePlus – to map the metadata e.g. axes correctly.
  2. RandomAccessibleInterval to ImagePlus – for all other cases i.e. no metadata is available.
  3. ImagePlus to ImgPlus. We already have ImagePlus to Dataset, which extends Img, so if you request a conversion of an ImagePlus object to e.g. RandomAccessibleInterval, it should already work (though I didn't test just now). But because Dataset does not extend ImgPlus (inorite), that request would currently fail.

The above is just speculative—best would be to do some thorough TDD requesting all sorts of anticipated desirable conversions, and then implement the most general converters that also minimize information loss.

imagejan commented 4 years ago

For the record, this Groovy script lists current support for some of the conversions:

#@ ConvertService cs

import ij.ImagePlus
import net.imagej.Dataset
import net.imagej.ImgPlus
import net.imglib2.img.Img
import net.imglib2.RandomAccessibleInterval

println cs.supports(Dataset.class, ImagePlus.class)                  // true
println cs.supports(Dataset.class, ImgPlus.class)                    // true
println cs.supports(Dataset.class, Img.class)                        // true
println cs.supports(Dataset.class, RandomAccessibleInterval.class)   // true
println ""
println cs.supports(ImagePlus.class, Dataset.class)                  // true
println cs.supports(ImagePlus.class, ImgPlus.class)                  // false
println cs.supports(ImagePlus.class, Img.class)                      // true
println cs.supports(ImagePlus.class, RandomAccessibleInterval.class) // true
println ""
println cs.supports(ImgPlus.class, Dataset.class)                    // false
println cs.supports(ImgPlus.class, ImagePlus.class)                  // false
println cs.supports(ImgPlus.class, Img.class)                        // true
println cs.supports(ImgPlus.class, RandomAccessibleInterval.class)   // true
println ""
println cs.supports(Img.class, Dataset.class)                        // false
println cs.supports(Img.class, ImagePlus.class)                      // false
println cs.supports(Img.class, ImgPlus.class)                        // true
println cs.supports(Img.class, RandomAccessibleInterval.class)       // true
println ""
println cs.supports(RandomAccessibleInterval.class, Dataset.class)   // false
println cs.supports(RandomAccessibleInterval.class, ImagePlus.class) // false
println cs.supports(RandomAccessibleInterval.class, ImgPlus.class)   // false
println cs.supports(RandomAccessibleInterval.class, Img.class)       // false
imagejan commented 4 years ago

I started implementing a parameterized test in https://github.com/imagej/imagej-legacy/commit/fb75ae4335e9f54f84e110210349bae6e4eeb743, where different types and axis orders can be defined to be tested in ImgPlus => ImagePlus conversion.

ctrueden commented 4 years ago

See also imagej/imagej-common#74

ctrueden commented 4 years ago

And imagej/imagej-ops#54

imagesc-bot commented 4 years ago

This issue has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/net-imagej-defaultdataset/37085/3

imagesc-bot commented 2 years ago

This issue has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/save-ilastik-hdf5-files-from-java/60194/2

ctrueden commented 2 years ago

I wrote a more thorough script printing supported conversions:

image-conversions.py ```python #@ ConvertService cs import sys from ij import ImagePlus from net.imagej import Dataset, ImgPlus from net.imagej.display import DatasetView, ImageDisplay from net.imglib2.img import Img from net.imglib2 import RandomAccessibleInterval image_types = [ ImagePlus, RandomAccessibleInterval, Img, ImgPlus, Dataset, DatasetView, ImageDisplay, ] sys.stdout.write(" ") for col in image_types: sys.stdout.write("{0: <13}".format('RAI' if col == RandomAccessibleInterval else col.__name__)) print for row in image_types: sys.stdout.write("{0: <14}".format('RAI' if row == RandomAccessibleInterval else row.__name__)) for col in image_types: sys.stdout.write("yes " if cs.supports(col, row) else "NO ") print ```

And the results as of this writing:

              ImagePlus    RAI          Img          ImgPlus      Dataset      DatasetView  ImageDisplay 
ImagePlus     yes          NO           NO           NO           yes          NO           yes          
RAI           yes          yes          yes          yes          yes          NO           NO           
Img           yes          NO           yes          yes          yes          NO           NO           
ImgPlus       NO           NO           yes          yes          yes          NO           NO           
Dataset       yes          NO           NO           NO           yes          NO           NO           
DatasetView   NO           NO           NO           NO           NO           yes          NO           
ImageDisplay  yes          NO           NO           NO           NO           NO           yes        

The PyImageJ and napari-imagej projects have to bend over backwards to support image conversions that aren't supported by the ConvertService yet, so I'm motivated to make the above grid all "yes".

ctrueden commented 1 year ago

imagej/imagej-common#102 adds new converters for Dataset to DatasetView and RAI to ImageDisplay. Updated table:

              ImagePlus    RAI          Img          ImgPlus      Dataset      DatasetView  ImageDisplay 
ImagePlus     yes          NO           NO           NO           yes          NO           yes          
RAI           yes          yes          yes          yes          yes          NO           NO           
Img           yes          NO           yes          yes          yes          NO           NO           
ImgPlus       NO           NO           yes          yes          yes          NO           NO           
Dataset       yes          NO           NO           NO           yes          NO           NO           
DatasetView   NO           NO           NO           NO           yes          yes          NO           
ImageDisplay  yes          yes          yes          yes          yes          NO           yes          
ctrueden commented 1 year ago

With imagej/imagej-common#103, and specifically imagej/imagej-common@e67b5c932365842d20358c81ac5d67386ca1f2e9, I have now coded converters for all image types to/from all others, except for ij.ImagePlus since that's not available from imagej-common. But it gets us much closer to the above table becoming all yeses!

imagesc-bot commented 1 year ago

This issue has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/converting-arrayimg-to-imageplus-for-using-the-analyze-skeleton-plugin/85934/3