Add Functor module with FunctorImageFilter
Compare changes
Files
12+ 427
− 0
This MR introduces a new Functor
module, which contains the FunctorImageFilter
.
It is the same as MR !268 (closed) with squashed commit and a better documentation.
For examples of use, please refer to the test of the class.
Prototype for this filter is as follows : FunctorImageFilter<TFunction,TNameMap = void>
.
Where TFunction
can be any lambda, free function, or class member operator()
, with any number of arguments.
Let R (T1 t1, T2 t2 ..., TN tn) (const)
be TFunction
signature. T1, T2, ...TN
can be:
itk::FixedArray
, itk::RGBPixel
, itk::RGBAPixel
itk::VariableLengthVector
itk::Neighborhood
of any of the aboveR
can be:
itk::FixedArray
, itk::RGBPixel
, itk::RGBAPixel
itk::VariableLengthVector
Note that the following operator prototype is also supported: void (R& return, T1 t1, T2 t2 ..., TN tn) (const)
FunctorImageFilter
will automatically deduce the correct image type from return type and arguments of the function or operator()
, and will offer setters of the form SetVariadicInput<N>(...)
excepting the correct type for Nth input.
Note that one can also use the SetVariadicInputs(in1, in2, in3 ...)
variadic method to set all inputs at once.
VectorImage
If the TFunction
produces a VariableLengthVector
, then it should also provide a OutputSize()
method which will be called by FunctorImageFilter
to allocate the correct number of bands in output image.
Full prototype of OutputSize()
method is constexpr size_t OutputSize(const std::array<size_t, N> inputsNbBands) const
with N being the number of argument of the functor. inputsNbBands
will contain the number of bands for each input which can be used to derive the output number of bands. However, if the number of bands in input is not relevant to derive the number of output band, the following simpler signature can be used instead constexpr size_t OutputSize(...) const
.
If a lambda returning a VariableLengthVector
is used, one can not add the OutputSize()
method but the NumberOfOutputBandsDecorator
template class can be used to wrap the lambda and still use the filter.
Last, for the sake of backward compatibility, SetInput1()
, ..., SetInput10()
are also defined (if and only if the number of arguments in the functor is high enough).
Functor can be retrieved with GetFunctor()
(returns a const reference) or GetModifiableFunctor()
(returns a non-const reference AND calls Modified()
on filter).
In order to ease the use of the filter by users, it is possible to name input with tags instead of indices.
In that case TNameMap
is not void, but a std::tuple
of tags (i.e. empty classes):
struct tag1{};
struct tag2{};
If TNameMap = std::tuple<tag1,tag2>
then FunctorImageFilter
will also support settings input as follows : SetVariadicNamedInput<tag1>(in)
or SetVariadicNamedInput(tag1{},in)
... A good practice could be that this name mapping is provided by the functor itself.
If one of the arguments of the functor maps to itk::Neighborhood
the corresponding input will automatically be padded to the filter radius, which can be changed using SetRadius()
.
The FunctorImageFilter
offers two free functions that make it very easy to create ready to use instances of the filter:
// Simple case
SimpleFunctor f1;
auto filter1 = NewFunctorFilter(f1);
filter1->SetVariadicInputs(in1,...,inN);
filter1->Update();
// Functor With Radius
FunctorWithRadius f2;
auto filter2 = NewFunctorFilter(f1 {{3,3}}); // passing the radius directly
filter2->SetVariadicInputs(in1,...,inN);
filter2->Update();
// Lambda returning a VariableLengthVector of 3 bands
auto lambdaWithVariableLengthVector = [](const double &){return itk::VariableLengthVector<double> res(3); return res;};
auto filter2 = NewFunctorFilter(lambdaWithVariableLengthVector,3); // passing the number of output bands directly
filter2->SetVariadicInputs(in1);
filter2->Update();
Of course one can also directly use FunctorImageFilter
typedef to create the filter through the classical New()
static method.
VariableLengthVector
:
void operator(TOut & out, ...) const
(more efficient).OutputSize()
method if functor produces a VariableLengthVector
SetInputRed()
, SetInputMask()
, SetInputHH()
...), create a set of corresponding tags somewhere (i.e. struct red{};
...)template <typename TInputImage1, typename TInputImage2, typename TOuputImage>
using TheFunctorFilter = FunctorImageFilter< TheFunctor < typename TInputImage1::PixelType,
typename TInputImage2::PixelType,
typename TOutputImage::PixelType>,
std::tuple<tag1,tag2> >;
SetInputTag1()
by SetVariadicNamedInput<tag1>()
SetAlpha()
by GetModifiableFunctor().SetAlpha()
I tried to document the code as best as I could. If something is missing, please tell me I will fix it.
An extensive test suite has been added to cover all possible cases, with a lot of static_assert
. Most cases are also covered in the test with real functors.
This will not work with:
operator()
operator()
methodThe copyright owner is CNES and has signed the ORFEO ToolBox Contributor License Agreement.
Thanks to Jordi for helping starting this.
Check before merging: