Simple ITK – ImageJ2 integration

As part of my larger deconvolution project I tested some of the ITK deconvolution algorithms.   It was fairly easy to integrate Simple ITK into ImageJ2 using Eclipse in an Ubuntu development environment.   Though I haven’t attempted the non-trivial task of creating distributable libraries.  I was really impressed at how simple it was to create an image processing plugin using ImageJ2 and Simple ITK so I separated it into a self contained example that can be found here.

Here are the steps I followed to create my Image2/Simple ITK plugin.  While this example is for deconvolution it should be easy to modify it for different ITK functionality.

1. Create an ImageJ2 style maven project.  There are great examples in imagej-tutrials (if you are not familiar with maven google “maven in 5 minutes”)   The “intro-to-imagej-api”, “simple-commands” and “create-a-new-op” projects are very useful.

2.  Import the project into eclipse and follow the instructions to get/build SimpleITK and to set up for Java in eclipse.

3.  Write some utilities to copy between the imagej “Img” and the itk “Image”.  Mine are here, let me know if anybody has some better ones.

4. Write an op to wrap the itk function.  An op that wraps itk Richardson Lucy is here.  It is derived from this base class.   The key is the annotation “@Parameter”.  This defines the inputs and outputs.   Then the op can be called using the op service.  In a Python script it would look something like this.

out=ops.run("RichardsonLucyITK", in, kernel, 10)

The code to convert between image formats and call itk (through the simple itk wrapper) looks like this:

        // convert input to itk Images
        Image itkImage =
         SimpleItkImagejUtilities.simple3DITKImageFromInterval(input);
        Image itkPsf = 
        SimpleItkImagejUtilities.simple3DITKImageFromInterval(kernel);

        itkRL=new RichardsonLucyDeconvolutionImageFilter();

        // call itk rl using simple itk wrapper
        Image out=itkRL.execute(itkImage, itkPsf, numIterations, 
           true, BoundaryConditionType.ZERO_PAD, 
                RichardsonLucyDeconvolutionImageFilter. 
                 OutputRegionModeType.SAME);

        T inputType=Util.getTypeFromInterval(input);

        // convert output to ImageJ Img
        output = SimpleItkImagejUtilities.simple3DITKImageToImg(
                       out, input.factory(), inputType);

5. Write a command to call the op.  A command that calls the itk Richardson Lucy op is here.  Again the key is the @Parameter annotation.  It is used to get access to services.  For example

    @Parameter
    protected OpService ops;

is a means to access the service which runs the operations.   The code to call the op is as follows:

        // get the Imgs from the dataset 
        Img<T> imgIn=(Img<T>)input.getImgPlus().getImg();
        Img<T> imgKernel=(Img<T>)kernel.getImgPlus().getImg();

        // call the op
        Img<T> imgOut = (Img<T>)(ops.run("RichardsonLucyITK", imgIn,
             imgKernel, numIterations));

        output=data.create(new ImgPlus(imgOut));

The images (Img) are retrieved from a Dataset.  It is beyond the scope of this small blog post to go into detail about Datasets but I should note that in general a dataset may contain n-dimensional data.  So a more complete example would also have code to retrieve 3D hyperslices from a possible n-dimensional space.

The nice thing is that when we use a command we get a simple GUI for free.  As shown below.

ITKRLPlugin

Leave a Reply

Your email address will not be published. Required fields are marked *