Explorations of ImgLib2

by 3/15/2012 09:48:00 AM 0 comments
I'm working on a project that automates the analysis of images collected by our ESP instruments. For the analysis, I've been using ImageJ as the library for accessing and analyzing images. The ImageJ Java API is very easy to use but it's a bit crufty. There's been some work on improving it via the ImageJ2 and ImgLib projects. ImgLib2 is a very interesting library for scientific image analysis. However, it's waaaaaaaay more complex than the original ImageJ API and like many software libraries, the documentation is a bit sparse. I'll be posting a few diagrams and notes here to document the bits and pieces of ImgLib2 that I need to understand. Today's bit is about reading an image.

Read an image with imglib2

It's important to note that you have to specify the type of the image in order to read it. There's a UML diagram showing the 35 different type classes and interfaces at the bottom of this post.
import net.imglib2.img.array.ArrayImgFactory;
import net.imglib2.io.ImgOpener;
import net.imglib2.type.numeric.real.FloatType;
// ...

// Notice you need to know the type of the image before you read it
final ImgOpener io = new ImgOpener();
RandomAccessibleInterval<FloatType> img = io.openImg( "73_float.tif", 
    new ArrayImgFactory<FloatTyp>>(), new FloatType());

Read an image with ImageJ

Compare this to how I was reading images in ImageJ. With ImageJ, you don't specify the type of the image, it figures it out for you. On the other hand, ImageJ's IO wasn't reading the type of TIF images I was working with correctly. So my workaround was to read everything as a BufferedImage and then wrap it with an ImagePlus object.
import javax.imageio.ImageIO;
import java.awt.AlphaComposite;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.util.Hashtable;
import javax.media.jai.JAI

/**
 * Converts a RenderedImage into a BufferedImage. If the RenderedImage
 * is already a BufferedImage then the input argument is returned (i.e. no
 * operations are performed on the image). Found this at
 * {@link http://www.mambo.net/cgi-bin/TempProcessor/view/77}
 *
 * @param image The RenderedImage to convert
 * @return The input converted to a BufferedImage
 */
public static BufferedImage toBufferedImage(RenderedImage image) {
    if (image instanceof BufferedImage) {
        return (BufferedImage) image;
    }

    ColorModel colorModel = image.getColorModel();
    int width = image.getWidth();
    int height = image.getHeight();
    WritableRaster raster = colorModel.createCompatibleWritableRaster(width, height);
    boolean isAlphaPremultiplied = colorModel.isAlphaPremultiplied();
    Hashtable props = new Hashtable();
    String[] keys = image.getPropertyNames();

    if (keys != null) {
        for (int i = 0; i < keys.length; i++) {
            props.put(keys[i], image.getProperty(keys[i]));
        }
    }
    BufferedImage bufferedImage = new BufferedImage(colorModel, raster, isAlphaPremultiplied, props);
    image.copyData(raster);

    return bufferedImage;

}

public BufferedImage readAsBufferedImage(URL url) {
    String name = url.getFile().toLowerCase();
    // Tiff's get special handling. ImageJ was not handling them correctly.
    BufferedImage img = null;
    if (name.endsWith(".tif") || name.endsWith (".tiff")) {
        RenderedImage renderedImage = JAI.create("url", url);
        img = toBufferedImage(renderedImage)
    }
    else {
        img = ImageIO.read(url)
    }
}

// You do NOT need to know the type of the image. ImageJ figures it out for you.
ImagePlus imagePlus = new ImagePlus(url.toExternalForm(), readAsBufferedImage(url))


Type Class UML

Now in order to read an image in imglib2, you need to understand it's types. There's currently 35 classes and interfaces in the type hierarchy. Here's a diagram of the different types:
In many, many classes imglib2 uses a generic intersection type of NativeType and RealType. Here's and example method signature:
public <T extends RealType<T> & NativeType<T>> ImgPlus<T> openImg(...)
The UML for this compound type is:

ImgPlus Class UML

And here is the ImgPlus class diagram:

Navigating an ImgPlus

For navigation, imglib provides Cursor and Positionable interfaces. I won't cover their usages right now but the UML for these classes is:

Brian Schlining

Developer

Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.

0 comments: