diff --git a/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.h b/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.h
index f4adcdf7061fefe8d5e8a9d44e4271c6c2748993..1b437b593fbac35ae9de0cfa0f1eb9dca28dca16 100644
--- a/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.h
+++ b/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.h
@@ -32,20 +32,16 @@ namespace otb
 
 /**  
  * \struct IsNeighborhood 
- * Struct testing if T is a neighborhood
+ * \brief Struct testing if T is a neighborhood
+ * 
  * Provides:
  * - ValueType type set to false_type or true_type
  * - value set to true or false
- * - PixelType type to the underlying pixel type
  */
-template <class T, class Enable = void> struct IsNeighborhood{};
-
-/// Partial specialisation for scalar types
-template <class T> struct IsNeighborhood<T,typename std::enable_if<std::is_scalar<typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value >::type>
+template <class T> struct IsNeighborhood
 {
   using ValueType = std::false_type;
   static constexpr bool value = false;
-  using PixelType = T;
 };
 
 /// Partial specialisation for itk::Neighborhood<T>
@@ -53,37 +49,73 @@ template <class T> struct IsNeighborhood<itk::Neighborhood<T>>
 {
   using ValueType = std::true_type;
   static constexpr bool value = true;
-  using PixelType = T;
 };
 
+
 /// Partial specialisation for const itk::Neighborhood<T> &
 template <class T> struct IsNeighborhood<const itk::Neighborhood<T>&>
 {
   using ValueType = std::true_type;
   static constexpr bool value = true;
+};
+
+
+/**
+ * \struct PixelTypeDeduction
+ * \brief Helper struct to derive PixelType from template parameter.
+ * 
+ * T                           -> PixelType = T
+ * itk::Neighborhood<T>        -> PixelTyoe = T
+ * const itk::Neighborhood<T>& -> PixelTyoe = T
+*/
+template <class T> struct PixelTypeDeduction
+{
+  using PixelType = T;
+};
+
+/// Partial specialisation for itk::Neighborhood<T>
+template <class T> struct PixelTypeDeduction<itk::Neighborhood<T>>
+{
   using PixelType = T;
 };
 
+/// Partial specialisation for const itk::Neighborhood<T> &
+template <class T> struct PixelTypeDeduction<const itk::Neighborhood<T>&>
+{
+  using PixelType = T;
+};
+
+/** 
+ * \struct ImageTypeDeduction
+ * \brief Helper struct to derive ImageType from template parameter
+ * 
+ * T                            -> ImageType = otb::Image<T>
+ * itk::VariableLengthVector<T> -> ImageType = otb::VectorImage<T>
+ * const T &                    -> ImageType = ImageTypeDeduction<T>::ImageType
+ */
+template <class T> struct ImageTypeDeduction 
+{
+  using ImageType = otb::Image<T>;
+};
+
 /// Partial specialisation for itk::VariableLengthVector<T>
-template <class T> struct IsNeighborhood<itk::VariableLengthVector<T>>
+template <class T> struct ImageTypeDeduction<itk::VariableLengthVector<T>>
 {
-  using ValueType = std::false_type;
-  static constexpr bool value = false;
-  using PixelType = itk::VariableLengthVector<T>;
+  using ImageType = otb::VectorImage<T>;
 };
 
-/// Partial specialisation for const itk::VariableLengthVector<T> &
-template <class T> struct IsNeighborhood<const itk::VariableLengthVector<T>&>
+/// Partial specialisation for const T &
+template <class T> struct ImageTypeDeduction<const T &>
 {
-  using ValueType = std::false_type;
-  static constexpr bool value = false;
-  using PixelType = itk::VariableLengthVector<T>;
+  using ImageType = typename ImageTypeDeduction<T>::ImageType;
 };
 
+
 /**
  * \struct InputImageTraits
- * Struct allowing to derive input image types from operator()
- * arguments
+ * \brief Struct allowing to derive input image types from operator()
+ *        arguments
+ * 
  * Defines:
  * - PixelType type to the underlying pixel type
  * - ScalarType type to the underlying scalar type
@@ -96,16 +128,14 @@ template<typename T>
 struct InputImageTraits
 {
   using ArgumentType = T;
-  using PixelType = typename IsNeighborhood<typename std::remove_cv<typename std::remove_reference< ArgumentType>::type >::type>::PixelType;
-  using ScalarType = typename itk::DefaultConvertPixelTraits<PixelType>::ComponentType;
-  using ImageType = typename std::conditional<std::is_scalar<PixelType>::value,
-                                     otb::Image< ScalarType >,
-                                     otb::VectorImage< ScalarType > >::type;
+  using PixelType = typename PixelTypeDeduction<T>::PixelType;
+  using ImageType = typename ImageTypeDeduction<PixelType>::ImageType;
 };
 
 /**
  * \struct OutputImageTraits
- * Struct allowing to derive output image type from operator()
+ * \brief Struct allowing to derive output image type from operator()
+ * 
  * Defines:
  * - ScalarType type to the underlying scalar type
  * - ImageType type to the mocked up image type
@@ -116,17 +146,15 @@ template<typename T>
 struct OutputImageTraits
 {
   using ResultType = T;
-  using ScalarType = typename itk::DefaultConvertPixelTraits<ResultType>::ComponentType;
-  using ImageType =  typename std::conditional<std::is_scalar<ResultType>::value,
-                                     typename otb::Image<ScalarType>,
-                                     typename otb::VectorImage<ScalarType> >::type;
+  using ImageType = typename ImageTypeDeduction<T>::ImageType;
 };
 
 
 /**
 * \struct FunctorFilterSuperclassHelper 
-* Struct allowing to derive the superclass prototype for the
-* FunctorImageFilter class
+* \brief Struct allowing to derive the superclass prototype for the
+*        FunctorImageFilter class
+*
 * Provides the following:
 * - OutputImageType : type of the output image
 * - FilterType : correct instanciation of VariadicInputsImageFilter from
@@ -161,7 +189,7 @@ template <typename C, typename R, typename... T> struct FunctorFilterSuperclassH
 };
 
 /**
- * This helper method builds a fully functional FunctorImageFilter from a functor instance
+ * brief This helper method builds a fully functional FunctorImageFilter from a functor instance
  * 
  * Functor can be any operator() that matches the following:
  * - Accepts any number of arguments of T,
@@ -216,11 +244,11 @@ public:
 
   using InputHasNeighborhood = typename FunctorFilterSuperclassHelper<TFunction>::InputHasNeighborhood;
  
-/** Run-time type information (and related methods). */
+  /** Run-time type information (and related methods). */
   itkTypeMacro(FunctorImageFilter, ImageToImageFilter);
   
   
-/** Get the functor object.  The functor is returned by reference.
+  /** Get the functor object.  The functor is returned by reference.
    * (Functors do not have to derive from itk::LightObject, so they do
    * not necessarily have a reference count. So we cannot return a
    * SmartPointer.) */
@@ -230,7 +258,7 @@ public:
     return m_Functor;
   }
 
-/** Get the functor object.  The functor is returned by reference.
+  /** Get the functor object.  The functor is returned by reference.
    * (Functors do not have to derive from itk::LightObject, so they do
    * not necessarily have a reference count. So we cannot return a
    * SmartPointer.) */
@@ -249,18 +277,18 @@ private:
   void operator =(const Self&) = delete;
   ~FunctorImageFilter() = default;
 
-/** Overload of ThreadedGenerateData  */
-virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) override;
+  /** Overload of ThreadedGenerateData  */
+  void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) override;
 
   /**
    * Pad the input requested region by radius
    */
-  virtual void GenerateInputRequestedRegion(void) override;
+  void GenerateInputRequestedRegion(void) override;
 
   /**
    * Will use the OutputSize() method if
    */
-  virtual void GenerateOutputInformation() override;
+  void GenerateOutputInformation() override;
 
 
   // The functor member
@@ -276,6 +304,7 @@ template <typename Functor> auto NewFunctorFilter(const Functor& f, itk::Size<2>
   using PointerType = typename FilterType::Pointer;
 
   PointerType  p = new FilterType(f,radius);
+  p->UnRegister();
   return p;
 }
 
@@ -283,7 +312,7 @@ template <typename Functor> auto NewFunctorFilter(const Functor& f, itk::Size<2>
 template <typename F> struct NumberOfOutputBandsDecorator : F
 {
 public:
-  NumberOfOutputBandsDecorator(const F t, unsigned int nbComp) : F(t), m_NumberOfOutputComponents(nbComp) {}
+  constexpr NumberOfOutputBandsDecorator(const F t, unsigned int nbComp) : F(t), m_NumberOfOutputComponents(nbComp) {}
   using F::operator();
 
   constexpr size_t OutputSize(...) const
diff --git a/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.hxx b/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.hxx
index 76acef9af4b6dd6f2e6f2b8a53e30c9345c9646c..4d80e69c3057070ee44996c683fab0933554ab18 100644
--- a/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.hxx
+++ b/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.hxx
@@ -36,6 +36,8 @@ namespace functor_filter_details
 // This function sets the requested region for one image
 template<class T> int SetInputRequestedRegion(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>& radius)
 {
+  assert(img&&"Input image is a nullptr");
+
   auto currentRegion = region;
   currentRegion.PadByRadius(radius);
 
@@ -53,15 +55,11 @@ template<class T> int SetInputRequestedRegion(const T * img, const itk::ImageReg
         
     // build an exception
     itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
-    std::ostringstream msg;
-    msg << "::SetInputRequestedRegion<>()";
-    e.SetLocation(msg.str());
+    e.SetLocation("::SetInputRequestedRegion<>()");
     e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
     e.SetDataObject(nonConstImg);
     throw e;
     }
-
-  return 0;
 }
 
 template <class Tuple, size_t...Is> auto SetInputRequestedRegionsImpl(Tuple & t, const itk::ImageRegion<2> & region, std::index_sequence<Is...>,const itk::Size<2> & radius)
@@ -121,7 +119,7 @@ template <typename T> struct GetProxy{};
 
 template <typename T> struct GetProxy<itk::ImageRegionConstIterator<T> >
 {
-  static auto Get(const itk::ImageRegionConstIterator<T> & t)
+  static decltype(auto) Get(const itk::ImageRegionConstIterator<T> & t)
 {
   return t.Get();
 }
@@ -129,7 +127,7 @@ template <typename T> struct GetProxy<itk::ImageRegionConstIterator<T> >
 
 template <typename T> struct GetProxy<itk::ConstNeighborhoodIterator<T> >
 {
-  static auto Get(const itk::ConstNeighborhoodIterator<T> & t)
+  static decltype(auto) Get(const itk::ConstNeighborhoodIterator<T> & t)
 {
   return t.GetNeighborhood();
 }
@@ -183,9 +181,6 @@ void
 FunctorImageFilter<TFunction>
 ::GenerateInputRequestedRegion()
 {
-  // call the superclass' implementation of this method
-  Superclass::GenerateInputRequestedRegion();
-
   // Get requested region for output
   typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
   auto requestedRegion = outputPtr->GetRequestedRegion();
diff --git a/Modules/Filtering/ImageManipulation/test/otbFunctorImageFilter.cxx b/Modules/Filtering/ImageManipulation/test/otbFunctorImageFilter.cxx
index 4cb02775d5b147be0da775b3c7b8a877293067ff..62a895abd50ff2727c8bf25206e0a2f923e20a05 100644
--- a/Modules/Filtering/ImageManipulation/test/otbFunctorImageFilter.cxx
+++ b/Modules/Filtering/ImageManipulation/test/otbFunctorImageFilter.cxx
@@ -26,17 +26,18 @@
 #include <tuple>
 
 #include <numeric>
+#include <complex>
 
 // Example functors
 
 // N scalar images -> image
 // This functor takes N scalar image (variadic N) and returns the sum
 // of all pixels
-template <typename O, typename ...T> struct VariadicAdd
+template <typename TOut, typename ...TIns> struct VariadicAdd
 {
-  auto operator()(T... ins) const
+  auto operator()(TIns... ins) const
   {
-    std::vector<O> outVector{static_cast<O>(ins)...};
+    std::vector<TOut> outVector{static_cast<TOut>(ins)...};
 
     return std::accumulate(outVector.begin(), outVector.end(),0);
   }
@@ -81,18 +82,18 @@ template <typename v1, typename v2, typename ...vn> void concatenateVectors(v1 &
 // N  images (all types) -> vector image
 // This functor concatenates N images (N = variadic) of type
 // VectorImage and or Image, into a single VectorImage
-template<typename O, typename ...T> struct VariadicConcatenate
+template<typename TOut, typename ...TIns> struct VariadicConcatenate
 {
-  auto operator()(const T &...  ins) const
+  auto operator()(const TIns &...  ins) const
   {
-    itk::VariableLengthVector<O> out;
+    itk::VariableLengthVector<TOut> out;
     concatenateVectors(out, toVector(ins)...);
     
     return out;
   }
 
   // Must define OutputSize because output pixel is vector
-  constexpr size_t OutputSize(const std::array<size_t, sizeof...(T)> inputsNbBands) const
+  constexpr size_t OutputSize(const std::array<size_t, sizeof...(TIns)> inputsNbBands) const
   {
     return std::accumulate(inputsNbBands.begin(),inputsNbBands.end(),0);
   }
@@ -102,20 +103,20 @@ template<typename O, typename ...T> struct VariadicConcatenate
 // 1 VectorImage -> 1 VectorImage with a different size depending on a
 // parameter of the functor
 // This Functor 
-template<typename O, typename T> struct BandExtraction
+template<typename TOut, typename TIn> struct BandExtraction
 {
   BandExtraction(unsigned int indices...) : m_Indices({indices})
   {}
   
   // TODO define a constructor to initialize m_Indices  
-  auto operator()(const itk::VariableLengthVector<T> & in) const
+  auto operator()(const itk::VariableLengthVector<TIn> & in) const
   {
-    itk::VariableLengthVector<O> out(m_Indices.size());
+    itk::VariableLengthVector<TOut> out(m_Indices.size());
 
     size_t idx = 0;
     for(auto v: m_Indices)
       {
-      out[idx] = static_cast<O>(in[v]);
+      out[idx] = static_cast<TOut>(in[v]);
       ++idx;
       }
 
@@ -177,6 +178,27 @@ template<typename T> struct MaxInEachChannel
 };
 
 
+template<typename T> struct VectorModulus
+{
+  itk::VariableLengthVector<double> operator()(const itk::VariableLengthVector<std::complex<T>> & in) const
+  {
+    itk::VariableLengthVector<double> out(in.Size());
+    
+    for(auto band = 0u; band < out.Size(); ++band)
+      {
+      out[band] = std::abs(in[band]);
+      }
+    return out;
+  }
+
+  size_t OutputSize(const std::array<size_t,1> & nbBands) const
+  {
+    return nbBands[0];
+  }
+};
+
+
+// Tests of IsNeighborhood struct
 using OImage = typename otb::Image<int>;
 using Neig = typename itk::Neighborhood<int>;
 
@@ -193,11 +215,15 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
   // test functions in functor_filter_details namespace
   using VectorImageType = VectorImage<double>;
   using ImageType       = Image<double>;
+  using ComplexVectorImageType = VectorImage<std::complex<double>>;
+  using ComplexImageType = Image<std::complex<double>>;
   using RegionType      = typename ImageType::RegionType;
   using SizeType        = typename RegionType::SizeType;
   
   auto vimage = VectorImageType::New();
   auto image  = ImageType::New();
+  auto cvimage = ComplexVectorImageType::New();
+  auto cimage = ComplexImageType::New();
 
   SizeType size = {{200,200}};
   
@@ -207,11 +233,22 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
   itk::VariableLengthVector<double> v(2);
   v.Fill(0);
   vimage->FillBuffer(v);
+
+  cvimage->SetRegions(size);
+  cvimage->SetNumberOfComponentsPerPixel(2);
+  cvimage->Allocate();
+  itk::VariableLengthVector<std::complex<double>> cv(2);
+  cv.Fill(0);
+  cvimage->FillBuffer(cv);
   
   image->SetRegions(size);
   image->Allocate();
   image->FillBuffer(0);
 
+  cimage->SetRegions(size);
+  cimage->Allocate();
+  cimage->FillBuffer(0);
+
   // Test VariadicInputsImageFilter
   auto filter = otb::VariadicInputsImageFilter<VectorImageType,VectorImageType,ImageType>::New();
   filter->SetVInput<0>(vimage);
@@ -280,7 +317,18 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
   auto maxInEachChannel = NewFunctorFilter(MaxInEachChannelType{},{{3,3}});
   maxInEachChannel->SetVInputs(vimage);
   maxInEachChannel->Update();
-  
+
+  // Test FunctorImageFilter with Module (complex=
+  using ModulusType = VectorModulus<double>;
+  auto modulus = NewFunctorFilter(ModulusType{});
+  modulus->SetVInputs(cvimage);
+  modulus->Update();
+
+  auto LambdaComplex = [] (const std::complex<double> & in) {return std::arg(in);};
+  auto argFilter = NewFunctorFilter(LambdaComplex);
+  argFilter->SetVInputs(cimage);
+  argFilter->Update();
+
  return EXIT_SUCCESS;
 }