EleBrixie
EleBrixie

Reputation: 11

use C++ functions in ITK pipeline

I need help for a basic (I suppose) C++ issue. I would like to use C++ functions to simplify an ITK pipeline but I don't know how to pass arguments and to obtain outputs. I've seen in ITK examples how it's possible to call from main() a function for the creation of an image

(like in this case: http://www.itk.org/Wiki/ITK/Examples/ImageProcessing/LabelGeometryImageFilter)

What I would like to do is something like this (pseudo-code):

int main ()

{

Image = reader -> GetOutput();

function1 (input, ouput) // where input is Image 

function2 (input, ouput) // where input now is the output of function1

and so on

}

void function1
{
}

void function2
{
}

Cheers

Elena

Upvotes: 1

Views: 1153

Answers (1)

lib
lib

Reputation: 2956

I have the impression that you are coming from a long "only-main" function with an ITK pipeline, and now you want to make the code more readable by splitting it in some functions, and that you are not very confident in c++. If it's not like that, probably my answer will repeat what you already know..

First, ITK has this nice pipeline structure, so that you can prepare a pipeline concatenating a filter one after another, then call update on the last filter and get the whole pipeline to process the image. If you change the input to the first filter, and call update of the last filter again,the processing starts again because the filters detect that their input has changed from the last time. A typical error of beginners (at least, it was for me), is to try to get the output of a filter right after assigning the input, without making sure that update from that filter or one after it. Anyway, you can also call update after each filter, just to make sure that everything is going well (and for an easier debugging). I'm not sure if there is a performance issue, but in my applications I haven't noticed.
So, keep this in mind when you get output from these functions!

Second, ITK smart pointers can simplify your programming, since you don't have to remember to delete them after use and you don't have to worry that they will go out of scope when returning from a function. This also means that sometimes things don't get updated as expected because they are still retaining old data (for example you have to be careful in resetting your filter inside a for loop, if it was declared outside). But usually they simplify your life.

It's not too difficult to make small pipeline inside each function: your output will just be be a pointer to the output of the last filter in the function. You can set this pointer as return value of your function (see also http://www.itk.org/Wiki/ITK/Examples/Utilities/ReturnObjectFromFunction ). Or you can pass the output image by reference (as in your pseudocode, if you pass the pointer you are already passing by reference). For a refresh of c++, see for example http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/ . Pseudocode:

int main ()
{
  ImageType::Pointer inputimage, output1, output2;
  inputimage = reader -> GetOutput();
  output1 = function1 (inputimage) // where input is Image 
  function2 (output1, output2) // where input now is the output of function1 , pass argument by reference
}

ImageType::Pointer function1 (ImageType::Pointer aInput)
 {
  somefilter::pointer filter = somefilter::new()
  filter ->SetInput( aInput);
  filter->Update(); // unless you know what you are doing (you know that youe will access the data only at the end )
  return filter->GetOutput()
 }

void function2 (ImageType::Pointer aInput, ImageType::Pointer aOutput)
 {
  somefilter::pointer filter = somefilter::new()
  filter ->SetInput( aInput);
  filter->Update(); 

  aOutput = filter->GetOutput()
 }

You can even decide to duplicate an image (so that it's independent from the pipeline which generated it) and send it to another pipeline, see http://www.itk.org/Wiki/ITK/Examples/SimpleOperations/ImageDuplicator

As a side note, you can also create your own class with itk filters as members, create the pipeline in initialization, and then just modify the input of the filter in your methods, without recreating the pipeline each time.

Upvotes: 1

Related Questions