Friedrich-Alexander-Universität
Friedrich-Alexander-Universität
Stanford Radiology

Wrap ITK

Wrapping ITK for use with Java is not straight forward and varies with the system setup. Up to now we were able to build ITK for Windows 32bit only, due to limitations in the toolchain. Indications on how to build ITK for 64bit Windows and/or 32/64bit Linux are highly appreciated. While several comments and questions can be found on distinct mailing lists, there is no real "how to" and it may take severe problem-solving before the error stated in the question can finally be reproduced. As a consequence, we'd like to present our experiences with building ITK with Java wrappers.

You will need:

 

  • Opens external link in new windowCMake 2.8 or higher 
  • Opens external link in new windowITK 4.1 (Other versions >ITKv4 may work but have not been tested, however, there was no WRAP_JAVA option in ITKv4.6)
  • Opens external link in new windowVisual Studio 2008 (we used the Express edition). There used to be incompatibilities of GCC_XML with MSVC 10, leading to the impossibility to build ITK for 64bit. Opens external link in new windowThis message on the GCC_XML mailing list suggests a fix for use of GCC_XML with VS2010 and therefore 64bit, we have not yet got it to work. You actually can build GCC_XML for 64Bit with VS2010 but the ITK build won't work. Details on the issue Opens external link in new windowcan be found here.
  • Opens external link in new windowSWIG 1.3.38 (newer versions may work, but has not been tested). We did not build it ourselves but used the SWIGwin download with precompiled binaries.
  • Opens external link in new windowGCC_XML 0.9 (to be checked out and compiled)
  • Java SDK 1.8 for 64bit. Although building 32bit ITK a 32bit Java SDK results in heap space errors for some ITK modules.

 Let the fun begin.

 

  1. Extract the ITK sources into ../ITK-4.1/src and configure CMake to build into .../ITK-4.1/build/release for 32bit with Visual Studio 2008 and MSVC 9 in Release mode. 
  2. This is crucial for GCC_XML to work: go to ".../ITK-4.1/src/Wrapping/Generators/GccXML/" and open the "CMakeLists.txt". At line 166 stating "get_directory_property(include_dir_list INCLUDE_DIRECTORIES)" append the following line of code: "list( REMOVE_DUPLICATES include_dir_list )" to remove duplicate dependencies in the .inc include files, leading to errors. If you have not done this, you will most likely get the following error message in your log-files of the build: "Filename or extension too long.". 
  3. In CMake disable BUILD_TESTING and BUILD_EXAMPLES, but enable BUILD_SHARED_LIBRARIES and ITK_WRAP_JAVA. Click Configure.
  4. Check that the newly available flags for the Java SDK point to the correct files. Again, make sure to use a 64bit Version of the Java SDK or expect to find errors concerning heap space in the build-logs.
  5. Check ITK_USE_SYSTEM_GCCXML and set GCCXML to the prebuilt executable.
  6. Check ITK_USE_SYSTEM_SWIG and SWIG_EXECUTABLE to the precompiled swig.exe. 
  7. Configure
  8. Check that SWIG_DIR and SWIG_VERSION have been correctly determined, and correct else.
  9. Configure one last time and then Generate the project.
  10. Open the .sln in Visual Studio and right-click BUILD_ALL and choose Build. The project should now compile smoothly and after about 3 hours you should find the .jars in ".../ITK-4.1/build/release/lib/", and the corresponding .dlls in ".../ITK-4.1/build/release/lib/release/".
  11. Open your Eclipse project using a 32Bit version of Java (this is important, 64bit will not work as the ITK libraries were compiled for 32bit) and add the needed .jars to the build path. 
  12. As a last step add -Djava.library.path="C:\ItkVtk\ITK-4_1\build\release\lib\Release" as a VM argument in the run-configurations.

You should now be all set (test code is appended). Due to the restrictions introduced with the need for 32bit Java, a possibility to wrap it for 64bit would be highly appreciated. 

Note: We obtained errors for the ITK Level Set module and were not able to wrap it. This might work for later versions of ITK. 

We might be able to provide pre-compiled binaries and some minimal support. Please contact: Opens window for sending emailmathias.unberath(at)fau.de

 

 

Test Code

import org.itk.itkanisotropicsmoothing.itkCurvatureAnisotropicDiffusionImageFilterIF2IF2;

import org.itk.itkcommon.itkImageUC2;

import org.itk.itkcommon.itkIndex2;

import org.itk.itkfastmarching.itkFastMarchingImageFilterIF2IF2;

import org.itk.itkfastmarching.itkLevelSetNodeF2;

import org.itk.itkfastmarching.itkVectorContainerUILSNF2;

import org.itk.itkimagefilterbase.itkCastImageFilterIF2IUC2;

import org.itk.itkimagefilterbase.itkCastImageFilterIUC2IF2;

import org.itk.itkimagegradient.itkGradientMagnitudeImageFilterIF2IF2;

import org.itk.itkimageintensity.itkSigmoidImageFilterIF2IF2;

import org.itk.itkioimagebase.itkImageFileReaderIUC2;

import org.itk.itkioimagebase.itkImageFileWriterIUC2;


public class itkImageIO {


// use .png images for this example

// more information: 

public static void main( String argv[] )

 {

String inFile = argv[0];

String outFile = argv[1];

   itkImageFileReaderIUC2 reader = new itkImageFileReaderIUC2();

   itkImageFileWriterIUC2 writer = new itkImageFileWriterIUC2();


   reader.SetFileName( inFile );

   reader.Update();

   itkImageUC2 img = reader.GetOutput();

   int sx = (int) img.GetLargestPossibleRegion().GetSize().GetElement(0);

   int sy = (int) img.GetLargestPossibleRegion().GetSize().GetElement(1);

   System.out.println("Dim x: " + Integer.valueOf(sx) + "\tDim y: " + Integer.valueOf(sy));

   

    // cast unsigned char image to float for active contour level set segmentation

   System.out.println("Casting to float.");

   itkCastImageFilterIUC2IF2 castFloat = new itkCastImageFilterIUC2IF2();

   castFloat.SetInput(reader.GetOutput());

   castFloat.Update();

   // instantiate objects

   //smoothing

   System.out.println("Smoothing image.");

   itkCurvatureAnisotropicDiffusionImageFilterIF2IF2 uniso = new itkCurvatureAnisotropicDiffusionImageFilterIF2IF2();

   uniso.SetInput(castFloat.GetOutput());

   uniso.SetTimeStep(0.125);

   uniso.SetNumberOfIterations(5);

   uniso.SetConductanceParameter(9);

   uniso.Update();

   //gradient and sigmoid

   System.out.println("Calculating gradient magnitude.");

   itkGradientMagnitudeImageFilterIF2IF2 gradMag = new itkGradientMagnitudeImageFilterIF2IF2();

   gradMag.SetInput(uniso.GetOutput());

   gradMag.Update();

   System.out.println("Applying sigmoid filter.");

   itkSigmoidImageFilterIF2IF2 sigmoid = new itkSigmoidImageFilterIF2IF2();

   sigmoid.SetInput(gradMag.GetOutput());

   sigmoid.SetAlpha(-0.3);

   sigmoid.SetBeta(2);

   sigmoid.SetOutputMinimum(0.0f);

   sigmoid.SetOutputMaximum(1.0f);

   sigmoid.Update();

   //fast marching as level set initialization for active contours level set filter

   System.out.println("Starting fast marching image filter.");

   itkFastMarchingImageFilterIF2IF2 fast = new itkFastMarchingImageFilterIF2IF2();

   fast.SetInput(sigmoid.GetOutput());

   //56 92 5 1 -0,3 2,0 10

   itkIndex2 idx = new itkIndex2();

   itkLevelSetNodeF2 node = new itkLevelSetNodeF2();

   idx.SetElement(0, 56);

   idx.SetElement(1, 92);

   node.SetIndex(idx);

   node.SetValue(-5);

   itkVectorContainerUILSNF2 container = new itkVectorContainerUILSNF2();

   container.Initialize();

   container.InsertElement(0, node);    

   fast.SetTrialPoints(container);

   fast.SetSpeedConstant(1.0f);

   fast.SetOutputSize(castFloat.GetOutput().GetLargestPossibleRegion().GetSize());

   fast.Update();

   //cast back to unsigned char

   itkCastImageFilterIF2IUC2 castUC = new itkCastImageFilterIF2IUC2();

   castUC.SetInput(fast.GetOutput());

   castUC.Update();

   //write to output

   writer.SetFileName( outFile );

   writer.SetInput( castUC.GetOutput() );

   writer.Update();

 }

}