5

I have written a class using ITK in CPP which reads all files in a directory and then averages them. I would like to use this class in a pipeline constructed using Python.

I had previously tried to use Swig to wrap template code but according to the swig documenation, it doesn't have template support and the type names need to explicitly specified. But when I use ITK in Python, the interface is very different to that I expect from Swig-generated template code (the type name is not specified in the function/class name at all, which is contrary to what Swig documentation says).

A small snippet from my code illustrating the usage of the class is shown below:

typedef unsigned char PixelType;
typedef itk::Image<PixelType, 2> ImageType;
typedef itk::NaryMeanImageFilter< ImageType, ImageType > FilterType; // custom class
typedef itk::ImageFileReader<ImageType> ReaderType;
typedef itk::ImageFileWriter<ImageType> WriterType;

ImageType::Pointer image = ImageType::New();
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
FilterType::Pointer filter = FilterType::New(); // custom class

for (unsigned int i = 0; i< fileNames.size(); ++i)
{
  reader->SetFileName(fileNames[i]);
  filter->SetInput(i, reader->GetOutput()); // custom class
}

writer->SetFileName(outName);
writer->SetInput(filter->GetOutput());
writer->Update();

The code for the class can be seen in the Git repository. I don't have an issue with increasing the dependencies of my project by using Boost::Python but I need a starting point to proceed. Any help would be extremely appreciated.

Thanks.

UPDATE:

Expected usage in Python would be,

readerType=itk.ImageFileReader[inputImageType]
reader=readerType.New()
filterType=itk.NaryMeanImageFilter[inputImageType,inputImageType]
filter=filterType.New()

for i in range(0, fileNames.size()):
    reader.SetFileName(fileNames[i])
    filter.SetInput(i, reader->GetOutput())
scap3y
  • 1,188
  • 10
  • 27
  • Can you please elaborate on what you have tried and what is missing with SWIG's template support? Similar to SWIG, Boost.Python cannot wrap templates, but it can wrap template instantiations. It can be extremely difficult if not impossible to integrate two binding libraries, as most have exclusive control with regards to type extraction and dispatching. Also, the git repository link 404s. – Tanner Sansbury May 18 '15 at 14:11
  • Well, I have tried to instantiate template classes using SWIG but the usage is very different (for example, in the above filter, Python usage would be itk.NaryMeanImageFilter_UC(), etc. for different data types). I would like the usage to be consistent with the different ITK modules – scap3y May 18 '15 at 14:14

2 Answers2

3

The main idea is to use the WrapITK module. It basically uses internal ITK wrapping and parsing mechanism (using GCCXML for C++ to XML parsing - to be moved to CastXML in the future) to generate the *.i files which SWIG uses to generate the Python wrapping code.

Basic idea:

  • Say you have an ITK filter 'itkDummy.h' which want to use from a Python script
  • Write a file 'itkDummy.wrap' giving the information about the pixel types and template initializations.
  • Use the WrapITK module (which is along with the ITK Python bindings) - needs to be verified because every time I tried this, I kept getting an error
  • Be happy that itkDummy can be called from Python

Reference: http://www.itk.org/Wiki/ITK/Release_4/Wrapping/BuildProcess

This is what I was looking for.

scap3y
  • 1,188
  • 10
  • 27
1

In Itk Software Guide vol. 1 (http://itk.org/ITKSoftwareGuide/html/Book1/ITKSoftwareGuide-Book1ch3.html#x34-410003.7 ) they explain that they are using their own wrapping consisting of:

  1. gccxml , that generates xml files from C++ program
  2. a script called igenerator.py , which generates .i files for swig
  3. swig

I've never done it before, but you could try to go through their wrapping pipeline to see how the generated *.i file looks like (or maybe even including your filter in your local ITK repository and see if the wrapping automatically works)

lib
  • 2,918
  • 3
  • 27
  • 53