Skip to content

Named inputs in FunctorImageFilter

Julien Michel requested to merge functor_filter_named_inputs into functorfilter

This MR is an addition to the main MR !268 (closed) which is the target branch.

It introduces a new intermediate filter called VariadicNamedInputsImageFilter which allows to statically name inputs of the filter, in the following manner:

// Test VariadicNamedInputsImageFilter
struct xs {}; // tag for xs input
struct pan {}; // tag for pan input
using Names = std::tuple<xs,pan>; // input mapping type
auto filterWithNames = otb::VariadicNamedInputsImageFilter<VectorImageType, Names, VectorImageType,ImageType>::New();
filterWithNames->SetVNamedInput<xs>(vimage);
filterWithNames->SetVNamedInput<pan>(image);
std::cout<<filterWithNames->GetVNamedInput<xs>()<< filterWithNames->GetVNamedInput<pan>()<<std::endl;

FunctorImageFilter now has a second template parameter defaulted to void, to hold this mapping. If the parameter value is void, superclass is VariadicInputsImageFilter, and behavior is the same as in !268 (closed). Otherwise it is VariadicNamedInputsImageFilter and the parameter is used to enable the SetVNamedInput<>() setters.

Why all this ? One issue we ran into when actually trying to refactor old otb code with the new FunctorImageFilter is that most functor usage in OTB imply the definition of a new Filter class, which is doing:

  • Setting the number of output bands (now covered by FunctorImageFilter)
  • Passing parameters to the functor (can be easily replaced by filter->GetFunctor().SetAlpha()).
  • Exposing meaningful name for input setters: for instance SetInput1() -> SetInputMask()

The latter is important, because otherwise you are left with guessing what is the order of inputs (which is derived from the functor).

Now, with the proposed named inputs interface, one could remove completely the definition of the class, and simply doing (example from the polarimetry module):

namespace polarimetry_tags
{
struct hh {};
struct hv {};
struct vh {};
struct vv {};
}
// This is the entire declaration of SinclairToCovarianceMatrixFilter
template <typename TInputImage, typename TOutputImage> SinclairToCovarianceMatrixFilter
= FunctorImageFilter< Functor::SinclairToCovarianceMatrixFunctor <typename TInputImage::PixelType,                                                                 
                                                                  typename TOutputImage::PixelType> ,
                                                                  std::tuple<polarimetry_tags::hh,
                                                                             polarimetry_tags::hv,
                                                                             polarimetry_tags::vh,
                                                                             polarimetry_tags::vv> >;
// This is how to use it
using namespace polarimetry_tags;
auto filter = SinclairToCovarianceMatrixFilter<InputImageType,OutputImageType>::New();
filter->SetVNamedInput<hh>(in1);
filter->SetVNamedInput<hv>(in2);
// ... Of course previous SetVinput<0>() SetVInput<1>() or even SetVInputs(in1,in2,in3,in4) still work

This would save a lot of code and be a real helper to refactor some Modules (for instance the radiometric indices).

The code is compiling and working, but I would like to get some feedback on this idea, hence the MR.

Edited by Julien Michel

Merge request reports