diff --git a/Modules/Core/Functor/CMakeLists.txt b/Modules/Core/Functor/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b22e90e314ec765d319649b8fca0eb9220d835fc
--- /dev/null
+++ b/Modules/Core/Functor/CMakeLists.txt
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+#
+# This file is part of Orfeo Toolbox
+#
+#     https://www.orfeo-toolbox.org/
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+project(OTBFunctor)
+otb_module_impl()
diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.h b/Modules/Core/Functor/include/otbFunctorImageFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..7aeb4e7efc3f9ae35d00bb1eb2c3151f5f3d0640
--- /dev/null
+++ b/Modules/Core/Functor/include/otbFunctorImageFilter.h
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbFunctorImageFilter_h
+#define otbFunctorImageFilter_h
+
+#include "otbVariadicNamedInputsImageFilter.h"
+#include "otbImage.h"
+#include "otbVectorImage.h"
+#include "itkRGBPixel.h"
+#include "itkRGBAPixel.h"
+#include "itkFixedArray.h"
+#include "itkDefaultConvertPixelTraits.h"
+#include <type_traits>
+
+namespace otb
+{
+/**  
+ * \struct IsNeighborhood 
+ * \brief Struct testing if T is a neighborhood
+ * 
+ * Provides:
+ * - ValueType type set to false_type or true_type
+ * - value set to true or false
+ */
+template <class T> struct IsNeighborhood
+{
+  using ValueType = std::false_type;
+  static constexpr bool value = false;
+};
+
+/// Partial specialisation for itk::Neighborhood<T>
+template <class T> struct IsNeighborhood<itk::Neighborhood<T>>
+{
+  using ValueType = std::true_type;
+  static constexpr bool value = true;
+};
+
+
+/// 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 IsSuitableType
+ * \brief Helper struct to check if a type can be used as pixel type.
+ *
+ * ::value maps to true if type can be used and false otherwhise.
+ */
+template <class T> struct IsSuitableType
+{
+  static constexpr bool value = std::is_scalar<T>::value;
+};
+
+/// Unwrap complex
+template <class T> struct IsSuitableType<std::complex<T>> {
+  static constexpr bool value = IsSuitableType<T>::value;
+};
+
+/// Unwrap VariableLengthVector
+template <class T> struct IsSuitableType<itk::VariableLengthVector<T>> {
+  static constexpr bool value = IsSuitableType<T>::value;
+};
+
+/// Unwrap FixedArray
+template <class T, size_t N> struct IsSuitableType<itk::FixedArray<T,N>> {
+  static constexpr bool value = IsSuitableType<T>::value;
+};
+
+/// Unwrap RGBPixel
+template <class T> struct IsSuitableType<itk::RGBPixel<T>> {
+  static constexpr bool value = IsSuitableType<T>::value;
+};
+
+/// Unwrap RGBAPixel
+template <class T> struct IsSuitableType<itk::RGBAPixel<T>> {
+  static constexpr bool value = IsSuitableType<T>::value;
+};
+
+/// Discard const qualifier
+template <class T> struct IsSuitableType<const T>{
+  static constexpr bool value = IsSuitableType<T>::value;
+};
+
+/// Discard reference
+template <class T> struct IsSuitableType<T &>{
+  static constexpr bool value = IsSuitableType<T>::value;
+};
+
+
+/**
+ * \struct PixelTypeDeduction
+ * \brief Helper struct to derive PixelType from template parameter.
+ * 
+ * T                           -> PixelType = T
+ * itk::Neighborhood<T>        -> PixelType = T
+ * const itk::Neighborhood<T>& -> PixelType = T
+*/
+template <class T> struct PixelTypeDeduction
+{
+  static_assert(IsSuitableType<T>::value,"T can not be used as a template parameter for Image or VectorImage classes.");
+  using PixelType = T;
+};
+
+/// Partial specialisation for itk::Neighborhood<T>
+template <class T> struct PixelTypeDeduction<itk::Neighborhood<T>>
+{
+  static_assert(IsSuitableType<T>::value,"T can not be used as a template parameter for Image or VectorImage classes.");
+  using PixelType = T;
+};
+
+/// Discard const qualifier
+template <class T> struct PixelTypeDeduction<const  T>
+{
+  using PixelType = typename PixelTypeDeduction<T>::PixelType;
+};
+
+/// Discard reference
+template <class T> struct PixelTypeDeduction<T &>
+{
+  using PixelType = typename PixelTypeDeduction<T>::PixelType;
+};
+
+/** 
+ * \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 ImageTypeDeduction<itk::VariableLengthVector<T>>
+{
+  using ImageType = otb::VectorImage<T>;
+};
+
+/**
+* \struct FunctorFilterSuperclassHelper 
+* \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
+* - the operator() prototype
+* - InputHasNeighborhood a tuple of N false_type or true_type to denote
+* - if Ith arg of operator() expects a neighborhood.
+*/
+
+
+template <typename T, typename TNameMap> struct FunctorFilterSuperclassHelper : public FunctorFilterSuperclassHelper<decltype(&T::operator()),TNameMap> {};
+
+namespace functor_filter_details
+{
+template <typename R, typename TNameMap, typename...T> struct FunctorFilterSuperclassHelperImpl
+{
+  // OutputImageType is derived from return type R
+  using OutputImageType = typename ImageTypeDeduction<R>::ImageType;
+  // InputImageType is derived using pixel type deduction and image
+  // type deduction
+  template <typename V> using InputImageType = typename ImageTypeDeduction<typename PixelTypeDeduction<V>::PixelType>::ImageType;
+
+  // Filter type is either VariadicInputsImageFilter or
+  // VariadicNamedInputsImageFilter depending on if there is a
+  // TNameMap or not
+  using FilterType = typename std::conditional<std::is_void<TNameMap>::value,
+                                               VariadicInputsImageFilter<OutputImageType,InputImageType<T>...>,
+                                               VariadicNamedInputsImageFilter<OutputImageType,TNameMap,InputImageType<T>...>>::type;
+
+  // InputHasNeighborhood is derived from IsNeighborhood
+  using InputHasNeighborhood = std::tuple<typename IsNeighborhood<T>::ValueType...>;
+};
+} // End namespace functor_filter_details
+
+/// Partial specialisation for R(*)(T...)
+template <typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(*)(T...),TNameMap>
+{
+  using OutputImageType      = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::OutputImageType;
+  using FilterType           = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::FilterType;
+  using InputHasNeighborhood = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::InputHasNeighborhood;
+};
+
+/// Partial specialisation for R(C::*)(T...) const
+template <typename C, typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(C::*)(T...) const, TNameMap>
+{
+  using OutputImageType      = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::OutputImageType;
+  using FilterType           = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::FilterType;
+  using InputHasNeighborhood = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::InputHasNeighborhood;
+
+};
+
+/// Partial specialisation for R(C::*)(T...)
+template <typename C, typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(C::*)(T...), TNameMap>
+{
+  using OutputImageType      = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::OutputImageType;
+  using FilterType           = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::FilterType;
+  using InputHasNeighborhood = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::InputHasNeighborhood;
+
+};
+
+/// Partial specialisation for void(*)(R &,T...)
+template <typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<void(*)(R&, T...), TNameMap>
+{
+  using OutputImageType      = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::OutputImageType;
+  using FilterType           = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::FilterType;
+  using InputHasNeighborhood = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::InputHasNeighborhood;
+
+};
+
+/// Partial specialisation for void(C::*)(R&,T...) const
+template <typename C, typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<void(C::*)(R&,T...) const, TNameMap>
+{
+  using OutputImageType      = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::OutputImageType;
+  using FilterType           = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::FilterType;
+  using InputHasNeighborhood = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::InputHasNeighborhood;
+
+};
+
+/// Partial specialisation for void(C::*)(R&,T...)
+template <typename C, typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<void(C::*)(R&,T...), TNameMap>
+{ 
+  using OutputImageType      = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::OutputImageType;
+  using FilterType           = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::FilterType;
+  using InputHasNeighborhood = typename functor_filter_details::FunctorFilterSuperclassHelperImpl<R,TNameMap,T...>::InputHasNeighborhood;
+};
+
+
+
+/**
+ * \brief This helper method builds a fully functional FunctorImageFilter from a functor instance
+ * 
+ * Functor can be any operator() (const or non-const) that matches the following:
+ * - Accepts any number of arguments of T,
+ * (const) itk::VariableLengthVector<T> (&),(const)
+ * itk::Neighborhood<T> (&), (const)
+ * itk::Neighborhood<itk::VariableLengthVector<T>> (&) with T a scalar type
+ * - returns T or itk::VariableLengthVector<T>, with T a scalar type
+ * or returns void and has first parameter as output (i.e. T& or itk::VariableLengthVector<T>&)
+ *
+ * The returned filter is ready to use. Inputs can be set through the
+ * SetVariadicInputs() method (see VariadicInputsImageFilter class for
+ * details)
+ * 
+ * \param f the Functor to build the filter from
+ * \param radius The size of neighborhood to use, if there is any
+ * itk::Neighborhood<T> in the operator() arguments.
+ * \return A ready to use OTB filter, which accepts n input image of
+ * type derived from the operator() arguments, and producing an image
+ * correpsonding to the operator() return type.
+ *
+ * Note that this function also works with a lambda as Functor,
+ * provided it returns a scalar type. If your lambda returns a
+ * VariableLengthVector, see the other NewFunctorFilter implementation.
+ */
+template <typename Functor, typename TNameMap = void> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius = {{0,0}});
+
+
+/** \class FunctorImageFilter
+ * \brief A generic functor filter templated by its functor
+ * 
+ * TFunction can be any operator() (const or non-const) that matches the following:
+ * - Accepts any number of arguments of T,
+ * (const) itk::VariableLengthVector<T> (&),(const)
+ * itk::Neighborhood<T> (&), (const)
+ * itk::Neighborhood<itk::VariableLengthVector<T>> (&) with T a scalar type
+ * - returns T or itk::VariableLengthVector<T>, with T a scalar type
+ * or returns void and has first parameter as output (i.e. T& or itk::VariableLengthVector<T>&)
+ *
+ * All image types will be deduced from the TFunction operator().
+ *
+ * \sa VariadicInputsImageFilter
+ * \sa NewFunctorFilter
+ * 
+ * \ingroup IntensityImageFilters   Multithreaded Streamed
+ *
+ * \ingroup OTBFunctor
+*/
+template <class TFunction, class TNameMap = void>
+    class ITK_EXPORT FunctorImageFilter
+  : public FunctorFilterSuperclassHelper<TFunction, TNameMap>::FilterType
+{
+
+public:
+  // Standard typedefs
+  using Self = FunctorImageFilter;
+  using FunctorType = TFunction;
+  using Pointer = itk::SmartPointer<Self>;
+  using ConstPointer = itk::SmartPointer<const Self>;
+
+  // Superclass through the helper struct
+  using SuperclassHelper = FunctorFilterSuperclassHelper<TFunction,TNameMap>;
+  using Superclass = typename SuperclassHelper::FilterType;
+  using OutputImageType = typename Superclass::OutputImageType;
+  using OutputImageRegionType = typename OutputImageType::RegionType;
+
+  // A tuple of bool of the same size as the number of arguments in
+  // the functor
+  using InputHasNeighborhood = typename SuperclassHelper::InputHasNeighborhood;
+  using InputTypesTupleType = typename Superclass::InputTypesTupleType;
+  template<size_t I> using InputImageType = typename Superclass::template InputImageType<I>;
+  using Superclass::NumberOfInputs;
+  
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(FunctorImageFilter, VariadicInputsImageFilter);
+  
+  /** Get the functor object.
+   * 
+   *  \return A non-const reference to the Functor in use. Note that
+   *  this call will call the Modified() function of the filter, which
+   *  will trigger a full output computation upon Update(). For
+   *  inspection only, prefer using GetFunctor()
+   */
+  FunctorType& GetModifiableFunctor()
+  {
+    this->Modified();
+    return m_Functor;
+  }
+
+  /** Get the functor object.  
+   * 
+   *  \return A const reference to the Functor in use. For a
+   *  modifiable version of the functor, see GetModifiableFunctor().
+   */
+  const FunctorType& GetFunctor() const
+  {
+    return m_Functor;
+  }
+
+protected:
+  /// Constructor of functor filter, will copy the functor
+  FunctorImageFilter(const FunctorType& f, itk::Size<2> radius) : m_Functor(f), m_Radius(radius) {};
+  FunctorImageFilter(const Self &) = delete;
+  void operator =(const Self&) = delete;
+  ~FunctorImageFilter() = default;
+
+private:
+  /// Actual creation of the filter is handled by this free function
+  friend auto NewFunctorFilter<TFunction,TNameMap>(const TFunction& f, itk::Size<2> radius);
+
+  /** Overload of ThreadedGenerateData  */
+  void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) override;
+
+  /**
+   * Pad the input requested region by radius
+   */
+  void GenerateInputRequestedRegion(void) override;
+
+  /**
+   * Will use the OutputSize() method of the functor if output is VectorImage
+   */
+  void GenerateOutputInformation() override;
+
+
+  // The functor member
+  FunctorType m_Functor;
+
+  // Radius if needed
+  itk::Size<2> m_Radius;
+};
+
+// Actual implementation of NewFunctorFilter free function
+template <typename Functor, typename TNameMap> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius)
+{
+  using FilterType = FunctorImageFilter<Functor,TNameMap>;
+  using PointerType = typename FilterType::Pointer;
+
+  PointerType  p = new FilterType(f,radius);
+  p->UnRegister();
+  return p;
+}
+
+/** 
+ * \struct NumberOfOutputBandsDecorator
+ * \brief This struct allows to forward the operator of template
+ *        parameter, while adding number of ouptut components service.
+ * 
+ * Its purpose is to enable the use of lambda or functor witht
+ * Outputsize() method with FunctorImageFilter.
+ * 
+ * It is used internally in NewFunctorFilter version with
+ * numberOfOutputBands parameter.
+ */ 
+
+template <typename F> struct NumberOfOutputBandsDecorator : F
+{
+public:
+  constexpr NumberOfOutputBandsDecorator(const F t, unsigned int nbComp) : F(t), m_NumberOfOutputBands(nbComp) {}
+  using F::operator();
+
+  constexpr size_t OutputSize(...) const
+  {
+    return m_NumberOfOutputBands;
+  }
+
+private:
+  unsigned int m_NumberOfOutputBands;
+};
+
+/** 
+ * brief This helper method builds a fully functional
+ * FunctorImageFilter from a functor instance which does not provide
+ * the OutputSize() service, or a lambda, returing a VariableLengthVector
+ * 
+ * \param f the Functor to build the filter from
+ * \param numberOfOutputBands The number of output bands that
+ * this filter will return
+ * \param radius The size of neighborhood to use, if there is any
+ * itk::Neighborhood<T> in the operator() arguments.
+ * \return A ready to use OTB filter, which accepts n input image of
+ * type derived from the operator() arguments, and producing an image
+ * correpsonding to the operator() return type.
+ *
+ * Note that this function also works with a lambda as Functor,
+ * provided it returns a scalar type. If your lambda returns a
+ * VariableLengthVector, see the other NewFunctorFilter implementation.
+
+ */ 
+
+template <typename Functor, typename TNameMap = void> auto NewFunctorFilter(const Functor& f, unsigned int numberOfOutputBands, itk::Size<2> radius)
+{
+  using FunctorType = NumberOfOutputBandsDecorator<Functor>;
+  FunctorType decoratedF(f,numberOfOutputBands);
+  return  NewFunctorFilter<FunctorType,TNameMap>(decoratedF,radius);
+}
+
+
+}// namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbFunctorImageFilter.hxx"
+#endif
+
+#endif
diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx
new file mode 100644
index 0000000000000000000000000000000000000000..42a93c2f2eb420075a5e7b989366ab5ea94ea936
--- /dev/null
+++ b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbFunctorImageFilter_hxx
+#define otbFunctorImageFilter_hxx
+
+#include "otbFunctorImageFilter.h"
+#include "itkProgressReporter.h"
+#include "itkConstNeighborhoodIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkImageScanlineIterator.h"
+
+namespace otb
+{
+namespace functor_filter_details
+{
+// Variadic SetRequestedRegion
+
+// 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, bool pad)
+{
+  assert(img&&"Input image is a nullptr");
+
+  auto currentRegion = region;
+
+  // Hopefully this will be optimized out by compiler
+  if(pad)
+    currentRegion.PadByRadius(radius);
+
+  // The ugly cast in all ITK filters
+  T * nonConstImg = const_cast<T*>(img);
+  
+  if(currentRegion.Crop(img->GetLargestPossibleRegion()))
+    {
+    nonConstImg->SetRequestedRegion(currentRegion);
+    return 0;
+    }
+  else
+    {
+    nonConstImg->SetRequestedRegion(currentRegion);
+        
+    // build an exception
+    itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
+    e.SetLocation("::SetInputRequestedRegion<>()");
+    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
+    e.SetDataObject(nonConstImg);
+    throw e;
+    }
+}
+
+// Will be easier to write in c++17 with std::apply and fold expressions
+template <typename HasNeighborhood, class Tuple, size_t...Is> auto SetInputRequestedRegionsImpl(Tuple & t, const itk::ImageRegion<2> & region, std::index_sequence<Is...>,const itk::Size<2> & radius)
+{
+  return std::make_tuple(SetInputRequestedRegion(std::get<Is>(t),region,radius,typename std::tuple_element<Is,HasNeighborhood>::type::value_type())...);
+}
+
+// Will be easier to write in c++17 with std::apply and fold expressions
+template <typename HasNeighborhood,typename... T> auto SetInputRequestedRegions(std::tuple<T...> && t,const itk::ImageRegion<2> & region, const itk::Size<2> & radius)
+{
+  return SetInputRequestedRegionsImpl<HasNeighborhood>(t,region,std::make_index_sequence<sizeof...(T)>{},radius);
+}
+
+// Will be easier to write in c++17 with std::apply and fold expressions
+template <class Tuple, size_t...Is> auto GetNumberOfComponentsPerInputImpl(Tuple & t, std::index_sequence<Is...>)
+{
+  return std::array<size_t,sizeof...(Is)>{{std::get<Is>(t)->GetNumberOfComponentsPerPixel()...}};
+}
+
+// Will be easier to write in c++17 with std::apply and fold expressions
+template <typename ...T> auto GetNumberOfComponentsPerInput(std::tuple<T...> & t)
+{
+  return GetNumberOfComponentsPerInputImpl(t, std::make_index_sequence<sizeof...(T)>{});
+}
+
+template <typename N> struct MakeIterator {};
+
+template <> struct MakeIterator<std::false_type>
+{
+  template <class T> static auto Make(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>&)
+  {
+    itk::ImageRegionConstIterator<T> it(img,region);
+    return it;
+  }
+};
+
+template <> struct MakeIterator<std::true_type>
+{
+  template <class T> static auto Make(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>& radius)
+  {
+    itk::ConstNeighborhoodIterator<T> it(radius,img,region);
+    return it;
+  }
+};
+
+// Will be easier to write in c++17 with std::apply and fold expressions
+template <class TNeigh, class Tuple, size_t...Is> auto MakeIteratorsImpl(const Tuple& t, const itk::ImageRegion<2> & region, const itk::Size<2> & radius, std::index_sequence<Is...>, TNeigh)
+{
+  return std::make_tuple(MakeIterator<typename std::tuple_element<Is,TNeigh>::type >::Make(std::get<Is>(t),region,radius)...);
+}
+
+// Will be easier to write in c++17 with std::apply and fold expressions
+template<class TNeigh, typename... T> auto MakeIterators(std::tuple<T...> &&t,const itk::ImageRegion<2> & region, const itk::Size<2> & radius, TNeigh n)
+  {
+    return MakeIteratorsImpl(t,region,radius,std::make_index_sequence<sizeof...(T)>{},n);
+  }
+
+// Variadic call of operator from iterator tuple
+template <typename T> struct GetProxy{};
+
+
+template <typename T> struct GetProxy<itk::ImageRegionConstIterator<T> >
+{
+  static decltype(auto) Get(const itk::ImageRegionConstIterator<T> & t)
+{
+  return t.Get();
+}
+};
+
+template <typename T> struct GetProxy<itk::ConstNeighborhoodIterator<T> >
+{
+  static decltype(auto) Get(const itk::ConstNeighborhoodIterator<T> & t)
+{
+  return t.GetNeighborhood();
+}
+};
+
+template <class Oper> struct OperProxy : public OperProxy<decltype(&Oper::operator())> {};
+
+template<class Out, class ... In> struct OperProxy<Out(*)(In...)>
+{
+  template <class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
+  {
+    out = oper(in...);
+  }
+};
+
+template<class C, class Out, class ... In> struct OperProxy<Out(C::*)(In...)>
+{
+  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
+  {
+    out = oper(in...);
+  }
+};
+
+template<class C, class Out, class ... In> struct OperProxy<Out(C::*)(In...) const>
+{
+  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
+  {
+    out = oper(in...);
+  }
+};
+
+template<class Out, class ... In> struct OperProxy<void(*)(Out&, In...)>
+{
+  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
+  {
+    oper(out,in...);
+  }
+};
+
+template<class C, class Out, class ... In> struct OperProxy<void(C::*)(Out&, In...)>
+{
+  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
+  {
+    oper(out,in...);
+  }
+};
+
+template<class C, class Out, class ... In> struct OperProxy<void(C::*)(Out&, In...) const>
+{
+  template template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
+  {
+    oper(out,in...);
+  }
+};
+
+
+// Will be easier to write in c++17 with std::apply and fold expressions
+template <class Tuple, class Out, class Oper, size_t...Is> auto CallOperatorImpl(Tuple& t, Out & out, Oper & oper,std::index_sequence<Is...>)
+{
+  OperProxy<Oper>::Compute(oper,out,GetProxy<typename std::remove_reference<decltype(std::get<Is>(t))>::type>::Get(std::get<Is>(t))...);
+}
+
+// Will be easier to write in c++17 with std::apply and fold expressions
+template <class Out, class Oper, typename ... Args> auto CallOperator(Out & out, Oper& oper, std::tuple<Args...> & t)
+{
+  CallOperatorImpl(t,out,oper,std::make_index_sequence<sizeof...(Args)>{});
+}
+
+// Variadic move of iterators
+// Will be easier to write in c++17 with std::apply and fold expressions
+template<class Tuple,size_t...Is> auto MoveIteratorsImpl(Tuple & t, std::index_sequence<Is...>)
+{
+  return std::make_tuple(++(std::get<Is>(t) )...);
+}
+
+template<typename ... Args> void MoveIterators(std::tuple<Args...> & t)
+{
+  MoveIteratorsImpl(t,std::make_index_sequence<sizeof...(Args)>{});
+}
+
+
+// Default implementation does nothing
+template <class F, class O, size_t N> struct NumberOfOutputComponents
+{};
+
+template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::Image<T>,N>
+  {
+  // We can not be here if output type is VectorImage
+    static void Set(const F&, otb::Image<T> *, std::array<size_t,N>){}
+};
+
+// O is a VectorImage AND F has a fixed OuptutSize static constexrp size_t;
+template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::VectorImage<T>,N>
+{
+  static void Set(const F & f, otb::VectorImage<T> * outputImage, std::array<size_t,N> inNbBands)
+  {
+    outputImage->SetNumberOfComponentsPerPixel(f.OutputSize(inNbBands));
+  }
+};
+
+} // end namespace functor_filter_details
+
+template <class TFunction, class TNameMap>
+void
+FunctorImageFilter<TFunction, TNameMap>
+::GenerateInputRequestedRegion()
+{
+  // Get requested region for output
+  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
+  auto requestedRegion = outputPtr->GetRequestedRegion();
+
+  // Propagate to each variadic inputs, including possible radius
+  // TODO: For now all inputs are padded with the radius, even if they
+  // are not neighborhood based
+  functor_filter_details::SetInputRequestedRegions<InputHasNeighborhood>(this->GetVariadicInputs(),requestedRegion, m_Radius);
+}
+
+template <class TFunction, class TNameMap>
+void
+FunctorImageFilter<TFunction, TNameMap>::GenerateOutputInformation()
+{
+  // Call Superclass implementation
+  Superclass::GenerateOutputInformation();
+
+  // Get All variadic inputs
+  auto inputs = this->GetVariadicInputs();
+
+  // Retrieve an array of number of components per input
+  auto inputNbComps = functor_filter_details::GetNumberOfComponentsPerInput(inputs);
+
+  // Call the helper to set the number of components for the output image
+  functor_filter_details::NumberOfOutputComponents<TFunction,OutputImageType,inputNbComps.size()>::Set(m_Functor,this->GetOutput(),inputNbComps);
+}
+
+/**
+ * ThreadedGenerateData Performs the neighborhood-wise operation
+ */
+template <class TFunction, class TNameMap>
+void
+FunctorImageFilter<TFunction, TNameMap>
+::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
+{
+  // Build output iterator
+  itk::ImageScanlineIterator<OutputImageType> outIt(this->GetOutput(),outputRegionForThread);
+  itk::ProgressReporter p(this,threadId,outputRegionForThread.GetNumberOfPixels());
+
+  // This will build a tuple of iterators to be used
+  auto inputIterators = functor_filter_details::MakeIterators(this->GetVariadicInputs(),outputRegionForThread, m_Radius,InputHasNeighborhood{});
+
+  // Build a default value
+  typename OutputImageType::PixelType outputValueHolder;
+  itk::NumericTraits<typename OutputImageType::PixelType>::SetLength(outputValueHolder,this->GetOutput()->GetNumberOfComponentsPerPixel());
+  
+  while(!outIt.IsAtEnd())
+    {
+    // MoveIterartors will ++ all iterators in the tuple
+    for(;!outIt.IsAtEndOfLine();++outIt,functor_filter_details::MoveIterators(inputIterators))
+      {
+      // This will call the operator with inputIterators Get() results
+      // and fill outputValueHolder with the result.
+      functor_filter_details::CallOperator(outputValueHolder,m_Functor,inputIterators);
+      outIt.Set(outputValueHolder);
+      // Update progress
+      p.CompletedPixel();
+      }
+    outIt.NextLine();
+    }
+}
+
+} // end namespace otb
+
+#endif
diff --git a/Modules/Core/Functor/include/otbVariadicAddFunctor.h b/Modules/Core/Functor/include/otbVariadicAddFunctor.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ab244af33ab630ad0ce1543f1790bf1862961c3
--- /dev/null
+++ b/Modules/Core/Functor/include/otbVariadicAddFunctor.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otb_VariadicAddFunctor_h
+#define otb_VariadicAddFunctor_h
+
+#include <numeric>
+
+namespace otb
+{
+
+namespace Functor
+{
+/**
+ * \class VariadicAdd
+ * \brief This functor adds any number of compile time scalar inputs 
+ * \ingroup OTBFunctor
+ */
+template <typename TOut, typename ...TIns> struct VariadicAdd
+{
+  auto operator()(TIns... ins) const
+  {
+    std::vector<TOut> outVector{static_cast<TOut>(ins)...};
+
+    return std::accumulate(outVector.begin(), outVector.end(),0);
+  }
+};
+
+} // end namespace Functor
+
+} // end namespace otb
+
+#endif
diff --git a/Modules/Core/Functor/include/otbVariadicConcatenateFunctor.h b/Modules/Core/Functor/include/otbVariadicConcatenateFunctor.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4903141aad2ebc38cdd131f9d77d7bceea42741
--- /dev/null
+++ b/Modules/Core/Functor/include/otbVariadicConcatenateFunctor.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otb_VariadicConcatenateFunctor_h
+#define otb_VariadicConcatenateFunctor_h
+
+#include "itkVariableLengthVector.h"
+#include <vector>
+#include <numeric>
+#include <array>
+
+namespace otb
+{
+
+namespace Functor
+{
+
+
+namespace variadic_concatenate_details
+{
+// helper function to implement next functor (convert a scalar value
+// to a VariableLengthVector)
+template <typename T> itk::VariableLengthVector<T> toVector(const T & in)
+{
+  itk::VariableLengthVector<T> out;
+  out.SetSize(1);
+  out[0] = in;
+  return out;
+}
+
+// helper function to implement next functor, VariableLengthVectorVersion (returns in)
+template <typename  T> const itk::VariableLengthVector<T> & toVector(const itk::VariableLengthVector<T> & in)
+{
+  return in;
+}
+
+// helper function to implement next functor, Merge two VariableLengthVector in-place
+template <typename v1, typename v2> void concatenateVectors(v1 & a, const v2 & b)
+{
+  const size_t previousSizeOfA = a.GetSize();
+  
+  a.SetSize(previousSizeOfA+b.GetSize());
+  
+  for(size_t it = 0; it<b.Size();++it)
+    {
+    a[previousSizeOfA+it] = static_cast<typename v1::ValueType>(b[it]);
+    }
+}
+
+// helper function to implement next functor, Merge N VariableLengthVector in-place
+template <typename v1, typename v2, typename ...vn> void concatenateVectors(v1 & a, const v2 & b, const vn&... z)
+{
+  concatenateVectors(a,b);
+  concatenateVectors(a,z...);
+}
+} // end namespace variadic_concatenate_details
+
+// N  images (all types) -> vector image
+// This functor concatenates N images (N = variadic) of type
+// VectorImage and or Image, into a single VectorImage
+
+/** 
+ * \class VariadicConcatenate
+ * \brief This functor concatenates any number of input of scalar type
+ * or VariableLengthVector.
+ * \ingroup OTBFunctor
+ */
+template<typename TOut, typename ...TIns> struct VariadicConcatenate
+{
+  auto operator()(const TIns &...  ins) const
+  {
+    itk::VariableLengthVector<TOut> out;
+    variadic_concatenate_details::concatenateVectors(out, variadic_concatenate_details::toVector(ins)...);
+    
+    return out;
+  }
+
+  // Must define OutputSize because output pixel is vector
+  constexpr size_t OutputSize(const std::array<size_t, sizeof...(TIns)> inputsNbBands) const
+  {
+    return std::accumulate(inputsNbBands.begin(),inputsNbBands.end(),0);
+  }
+};
+
+} // end namespace Functor
+
+} // end namespace otb
+
+#endif
diff --git a/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h b/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..9625815f24f3e54a2df56af5ee0560144b7fcc4d
--- /dev/null
+++ b/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef otb_VariadicInputsImageFilter_h
+#define otb_VariadicInputsImageFilter_h
+
+#include "itkImageSource.h"
+
+namespace otb {
+
+/**
+ * \brief Base class for image filter with variadic inputs.
+ *
+ * This filter act as a base class for all filters that will take
+ * several input images with different types and produce an output
+ * image.
+ * 
+ * Type for each input is taken from the variadic template parameter
+ * TInputs.
+ * 
+ * Inputs get be set/get with SetVariadicInput<N>() and
+ * GetVariadicInput<N>(), when N is the index (first input is 0) of
+ * the input. This is resolved at compile time: you can not call 
+ * SetVariadicInput<N>() with an argument not matching the Nth input
+ * type (it will lead to type mismatch compilation error).
+ * 
+ * Alternatively, you can call SetVariadicInputs() with all the input
+ * image in the same order as in the template parameters.
+ *
+ * Last, there is a macro that generates SetInput1() ... SetInput10()
+ * (iff the number of varidic input types is large enough) for
+ * backward compatibility.
+ * 
+ */
+template<class TOuptut, class ... TInputs> class VariadicInputsImageFilter : public itk::ImageSource<TOuptut>
+{
+public:
+  using Self = VariadicInputsImageFilter<TOuptut, TInputs...>;
+  using Pointer =  itk::SmartPointer<Self>;
+  using ConstPointer = itk::SmartPointer<const Self>;
+  using Superclass = itk::ImageSource<TOuptut>;
+  
+  using InputTypesTupleType = std::tuple<TInputs...>;
+  
+  template <size_t I> using InputImageType = typename std::tuple_element<I,InputTypesTupleType>::type;
+  static constexpr size_t NumberOfInputs = std::tuple_size<InputTypesTupleType>::value; 
+
+  // Good old new macro
+  itkNewMacro(Self);
+
+  /**
+   * \param Set the Ith input
+   */
+  template <std::size_t I> void SetVariadicInput(const typename std::tuple_element<I,InputTypesTupleType>::type * inputPtr)
+  {
+    static_assert(std::tuple_size<InputTypesTupleType>::value>I,"Template value I is out of range.");
+    this->SetNthInput(I,const_cast<typename std::tuple_element<I,InputTypesTupleType>::type *>(inputPtr));
+  }
+  
+#define DefineLegacySetInputMacro(n)                                                                               \
+  template<typename Tuple = InputTypesTupleType, typename Check = typename std::enable_if<n<=std::tuple_size<Tuple>::value >::type> \
+  void SetInput ## n(const typename std::tuple_element<n-1,Tuple>::type * img)                                           \
+  {                                                                                                                \
+    this->template SetVariadicInput<n-1>(img);                                                                             \
+  }
+
+  // The following defines legacy setters SetInput1()
+  // ... SetInput10(), only if the number of input type is sufficient
+  DefineLegacySetInputMacro(1);
+  DefineLegacySetInputMacro(2);
+  DefineLegacySetInputMacro(3);
+  DefineLegacySetInputMacro(4);
+  DefineLegacySetInputMacro(5);
+  DefineLegacySetInputMacro(6);
+  DefineLegacySetInputMacro(7);
+  DefineLegacySetInputMacro(8);
+  DefineLegacySetInputMacro(9);
+  DefineLegacySetInputMacro(10);
+
+#undef DefineLegacySetInputMacro
+
+  /**
+   * \return the Ith variadic input
+   */
+  template <std::size_t I> const typename std::tuple_element<I,InputTypesTupleType>::type * GetVariadicInput()
+  {
+    static_assert(std::tuple_size<InputTypesTupleType>::value>I,"Template value I is out of range.");
+    using ImageType = typename std::tuple_element<I,InputTypesTupleType>::type;
+    return dynamic_cast<const ImageType *>(this->GetInput(I));
+  }
+
+  /**
+   * \param inputs A vararg list of inputs 
+   */
+  void SetVariadicInputs(TInputs*... inputs)
+  {
+    auto inTuple = std::make_tuple(inputs...);
+    SetInputsImpl(inTuple,std::make_index_sequence<sizeof...(inputs)>{});
+  }
+
+  /**
+   * \return A tuple with all inputs
+   */
+  auto GetVariadicInputs()
+  {
+    return GetInputsImpl(std::make_index_sequence<sizeof...(TInputs)>{});
+  }
+
+protected:
+  VariadicInputsImageFilter()
+  {
+    this->SetNumberOfRequiredInputs(sizeof...(TInputs));
+  };
+  
+  ~VariadicInputsImageFilter() = default;
+  
+private:
+  template<class Tuple, size_t...Is> auto SetInputsImpl(Tuple& t, std::index_sequence<Is...>)
+  {
+    return std::initializer_list<int>{(this->SetVariadicInput<Is>(std::get<Is>(t)),0)...};
+  }
+
+  template <size_t...Is> auto GetInputsImpl(std::index_sequence<Is...>)
+  {
+    return std::make_tuple(this->GetVariadicInput<Is>()...);
+  }
+  
+  VariadicInputsImageFilter(const Self&) = delete;
+  void operator=(const Self&) = delete;
+};
+
+}
+
+#endif
diff --git a/Modules/Core/Functor/include/otbVariadicNamedInputsImageFilter.h b/Modules/Core/Functor/include/otbVariadicNamedInputsImageFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..3110a0ef478fe52ac28180b6654e3ceefe83efdf
--- /dev/null
+++ b/Modules/Core/Functor/include/otbVariadicNamedInputsImageFilter.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef otb_VariadicNamedInputsImageFilter_h
+#define otb_VariadicNamedInputsImageFilter_h
+
+#include "otbVariadicInputsImageFilter.h"
+
+namespace otb {
+
+/// TODO: Documentation
+
+namespace internal
+{
+template<typename Arg, typename Tuple> struct tuple_index;
+template<typename Arg, typename...Args> struct tuple_index<Arg, std::tuple<Arg,Args...> >
+{
+  static constexpr std::size_t value = 0;
+};
+
+template<typename Arg, typename NotMatching, typename...Args> struct tuple_index<Arg, std::tuple<NotMatching,Args...>>
+{
+  static_assert(sizeof...(Args)>0,"Could not find requested type in tuple");
+  static constexpr std::size_t value = 1 + tuple_index<Arg,std::tuple<Args...>>::value;
+};
+}
+
+template<class TOuptut, class TInputNameMap, class ... TInputs> class VariadicNamedInputsImageFilter : public VariadicInputsImageFilter<TOuptut,TInputs...>
+{
+public:
+  using Self         = VariadicNamedInputsImageFilter<TOuptut,TInputNameMap, TInputs...>;
+  using Pointer      = itk::SmartPointer<Self>;
+  using ConstPointer = itk::SmartPointer<const Self>;
+  using Superclass   = VariadicInputsImageFilter<TOuptut, TInputs...>;;
+
+  using InputTypesTupleType                = typename Superclass::InputTypesTupleType;
+  template <size_t I> using InputImageType = typename Superclass::template InputImageType<I>;
+  static constexpr size_t NumberOfInputs   = Superclass::NumberOfInputs;
+
+  static_assert(std::tuple_size<TInputNameMap>::value == NumberOfInputs,"Tuple for input name does not match the size of ... TInputs");
+  
+  itkNewMacro(Self);
+  
+  template <typename Tag> void SetVariadicNamedInput(const InputImageType<internal::tuple_index<Tag, TInputNameMap>::value> * inputPtr)
+  {
+    constexpr size_t idx = internal::tuple_index<Tag, TInputNameMap>::value;
+    this->SetNthInput(idx,const_cast<InputImageType<idx> *>(inputPtr));
+  }
+  
+  template <typename Tag> const InputImageType<internal::tuple_index<Tag,TInputNameMap>::value> * GetVariadicNamedInput()
+  {
+    constexpr size_t idx = internal::tuple_index<Tag, TInputNameMap>::value;
+    return dynamic_cast<const InputImageType<idx> *>(this->GetInput(idx));
+  }
+
+protected:
+  VariadicNamedInputsImageFilter() = default;
+  ~VariadicNamedInputsImageFilter() = default;
+  
+private:
+  VariadicNamedInputsImageFilter(const Self&) = delete;
+  void operator=(const Self&) = delete;
+};
+
+}
+
+#endif
diff --git a/Modules/Core/Functor/otb-module.cmake b/Modules/Core/Functor/otb-module.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..01d7f0cf94dc980a08e61ba9514e9792c4876d90
--- /dev/null
+++ b/Modules/Core/Functor/otb-module.cmake
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+#
+# This file is part of Orfeo Toolbox
+#
+#     https://www.orfeo-toolbox.org/
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set(DOCUMENTATION "This module contains a set of classes that allow parsing
+metadata files from different types of sensor (both optical and radar sensor types
+are supported. for instance: Pleiades, SPOT6, TerraSar, and so on).")
+
+otb_module(OTBFunctor
+  DEPENDS
+    OTBITK
+    OTBCommon
+    OTBImageBase
+  TEST_DEPENDS
+    OTBTestKernel
+DESCRIPTION
+    "${DOCUMENTATION}"
+)
diff --git a/Modules/Core/Functor/test/CMakeLists.txt b/Modules/Core/Functor/test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b51af1d22e27c3345ed3a69c2ea98485b918f31f
--- /dev/null
+++ b/Modules/Core/Functor/test/CMakeLists.txt
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+#
+# This file is part of Orfeo Toolbox
+#
+#     https://www.orfeo-toolbox.org/
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+otb_module_test()
+
+set(OTBFunctorTests
+otbFunctorTestDriver.cxx
+otbFunctorImageFilter.cxx
+)
+
+add_executable(otbFunctorTestDriver ${OTBFunctorTests})
+target_link_libraries(otbFunctorTestDriver ${OTBFunctor-Test_LIBRARIES})
+otb_module_target_label(otbFunctorTestDriver)
+
+otb_add_test(NAME bfTvFunctorImageFilter COMMAND otbImageManipulationTestDriver
+  otbFunctorImageFilter)
diff --git a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..464a4086b9eef59319754d841c5efb3cced2b3d3
--- /dev/null
+++ b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "itkMacro.h"
+#include "otbFunctorImageFilter.h"
+#include "otbImage.h"
+#include "otbVectorImage.h"
+#include "itkNeighborhood.h"
+#include "otbVariadicAddFunctor.h"
+#include "otbVariadicConcatenateFunctor.h"
+#include "otbVariadicNamedInputsImageFilter.h"
+#include <tuple>
+
+#include <numeric>
+#include <complex>
+#include <math.h>
+
+// static tests
+
+// Tests of IsNeighborhood, PixelTypeDeduction and ImageTypeDeduction structs
+using namespace otb;
+template <typename T> struct TypesCheck
+{
+  using ScalarType                    = T;
+  using ImageType                     = otb::Image<T>;
+  using VectorType                    = itk::VariableLengthVector<ScalarType>;
+  using FixedArrayType                = itk::FixedArray<ScalarType,4>;
+  using RGBPixelType                  = itk::RGBPixel<ScalarType>;
+  using RGBAPixelType                 = itk::RGBAPixel<ScalarType>;
+  using VectorImageType               = otb::VectorImage<ScalarType>;
+  using NeighborhoodType              = itk::Neighborhood<ScalarType>;
+  using VectorNeighborhoodType        = itk::Neighborhood<VectorType>;
+
+  // Test IsNeighborhood struct
+  template <typename U> struct CheckIsNeighborhood
+  {
+    static constexpr bool value = !otb::IsNeighborhood<U>::value && otb::IsNeighborhood<itk::Neighborhood<U> >::value;
+  };
+    
+  static_assert(CheckIsNeighborhood<T>::value,"");
+  static_assert(CheckIsNeighborhood<itk::VariableLengthVector<T>>::value,"");
+  static_assert(CheckIsNeighborhood<itk::FixedArray<T,4>>::value,"");
+  static_assert(CheckIsNeighborhood<itk::RGBPixel<T>>::value,"");
+  static_assert(CheckIsNeighborhood<itk::RGBAPixel<T>>::value,"");
+
+  // Test PixelTypeDeduction struct
+  template<typename U> struct CheckPixelTypeDeduction
+  {
+    static constexpr bool value = std::is_same<typename PixelTypeDeduction<U>::PixelType,U>::value
+      && std::is_same<typename PixelTypeDeduction<itk::Neighborhood<U>>::PixelType,U>::value;
+  };
+
+  static_assert(CheckPixelTypeDeduction<T>::value,"");
+  static_assert(CheckPixelTypeDeduction<itk::VariableLengthVector<T>>::value,"");
+  static_assert(CheckPixelTypeDeduction<itk::FixedArray<T,4>>::value,"");
+  static_assert(CheckPixelTypeDeduction<itk::RGBPixel<T>>::value,"");
+  static_assert(CheckPixelTypeDeduction<itk::RGBAPixel<T>>::value,"");
+  
+  // Test ImageTypeDeduction struct
+  static_assert(std::is_same<typename ImageTypeDeduction<ScalarType>::ImageType,ImageType>::value,"");
+  static_assert(std::is_same<typename ImageTypeDeduction<VectorType>::ImageType,VectorImageType>::value,"");
+
+  // Fake test operator
+  template <typename TOut,typename TIn> struct TestOperator
+  {
+    auto operator()(const TIn&) const
+    {
+      TOut res(OutputSize());
+      return res;
+    }
+    
+    constexpr size_t OutputSize(...) const
+    {
+      return 1;
+    }
+  };
+
+template <typename TOut,typename TIn> struct TestOperatorVoidReturn
+  {
+    void operator()(TOut& out,const TIn&) const
+    {
+      out = TOut(OutputSize());
+    }
+    
+    constexpr size_t OutputSize(...) const
+    {
+      return 1;
+    }
+  };
+
+  // Fake test operator non const
+  template <typename TOut,typename TIn> struct TestOperatorNonConst
+  {
+    auto operator()(const TIn&)
+    {
+      TOut res(OutputSize());
+      return res;
+    }
+    
+    constexpr size_t OutputSize(...) const
+    {
+      return 1;
+    }
+  };
+
+  
+  template <typename TOut, typename TIn> void TestFilter()
+  {
+  // Deduce types
+  using InputPixelType = typename PixelTypeDeduction<TIn>::PixelType;
+  using InputImageType = typename ImageTypeDeduction<InputPixelType>::ImageType;
+
+  // Allocate fake input
+  auto in = InputImageType::New();
+  typename InputImageType::SizeType size = {{10,10}};
+  in->SetRegions(size);
+  in->SetNumberOfComponentsPerPixel(1);
+  in->Allocate();
+  InputPixelType defaultValue(1);
+  in->FillBuffer(defaultValue);
+
+  // Build and run filter
+  auto functor = TestOperator<TOut,TIn>{};
+  auto filter = NewFunctorFilter(functor);
+  
+  using FilterType = typename decltype(filter)::ObjectType;
+  static_assert(FilterType::NumberOfInputs == 1,"");
+  static_assert(std::is_same<typename FilterType::template InputImageType<0>, InputImageType>::value, "");
+  filter->SetVariadicInputs(in);
+  filter->SetInput1(in);
+  filter->template SetVariadicInput<0>(in); // template keyword to
+                                            // avoid C++ parse
+                                            // ambiguity
+  auto res = filter->template GetVariadicInput<0>();
+  filter->Update();
+
+  // Test named input version
+  struct tag{};
+  using inputNames = std::tuple<tag>;
+  auto filter1 = NewFunctorFilter<decltype(functor),inputNames>(functor);
+  filter1->template SetVariadicNamedInput<tag>(in);
+  res = filter1->template GetVariadicNamedInput<tag>();
+  filter1->Update();
+  
+  // Test with void return
+  auto functorWithVoidReturn = TestOperatorVoidReturn<TOut,TIn>{};
+  auto filterWithVoidReturn = NewFunctorFilter(functorWithVoidReturn);
+  using FilterWithVoidReturnType = typename decltype(filter)::ObjectType;
+  static_assert(FilterWithVoidReturnType::NumberOfInputs == 1,"");
+  static_assert(std::is_same<typename FilterWithVoidReturnType::template InputImageType<0>, InputImageType>::value, "");
+  
+  // Test with non const operator
+  auto functorNonConstOperator = TestOperatorNonConst<TOut,TIn>{};
+  auto filterWithNonConstOperator = NewFunctorFilter(functorNonConstOperator);
+  filterWithNonConstOperator->SetInput1(in);
+  filterWithNonConstOperator->Update();  
+
+  filterWithVoidReturn->SetVariadicInputs(in);
+  filterWithVoidReturn->SetInput1(in);
+  filterWithVoidReturn->template SetVariadicInput<0>(in); // template keyword to avoid C++ parse ambiguity
+  filterWithVoidReturn->Update();
+  
+  // Test with simple lambda
+  auto lambda = [] (const TIn &)
+                {
+                  TOut ret(1);
+                  return ret;
+                };
+  auto filterWithLambda = NewFunctorFilter(lambda,1, {{0,0}});
+  filterWithLambda->SetVariadicInputs(in);
+  filterWithLambda->Update();
+
+  // Test with standard filter use
+  using FullFilterType = otb::FunctorImageFilter<TestOperator<TOut,TIn>>;
+  auto filter2 = FullFilterType::New();
+  }
+
+  TypesCheck()
+  {
+  // Test possible combinations
+  TestFilter<ScalarType,ScalarType>();
+  TestFilter<ScalarType,VectorType>();
+  TestFilter<ScalarType,NeighborhoodType>();
+  TestFilter<VectorType,ScalarType>();
+  } 
+};
+
+auto checksInt     = TypesCheck<int>{};
+auto checksDouble  = TypesCheck<double>{};
+auto checksComplex = TypesCheck<std::complex<double>>{};
+
+// Example functors
+
+
+
+// 1 VectorImage -> 1 VectorImage with a different size depending on a
+// parameter of the functor
+// This Functor 
+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<TIn> & in) const
+  {
+    itk::VariableLengthVector<TOut> out(m_Indices.size());
+
+    size_t idx = 0;
+    for(auto v: m_Indices)
+      {
+      out[idx] = static_cast<TOut>(in[v]);
+      ++idx;
+      }
+
+    return out;
+  }
+
+  // This time OutputSize does not depend on input image size, hence
+  // the ...
+  size_t OutputSize(...) const
+  {
+    return m_Indices.size();
+  }
+  
+  // set of band indices to extract
+  std::set<unsigned int> m_Indices;
+};
+
+// 1 Image with neighborhood -> 1 Image
+// This Functor computes the mean in neighborhood
+template<typename TOut, typename TIn> struct Mean
+{  
+  auto operator()(const itk::Neighborhood<TIn> & in) const
+  {
+    TOut out(0);
+
+    for(auto it = in.Begin(); it!=in.End();++it)
+      out+=static_cast<TOut>(*it);
+
+    out/=in.Size();
+    
+    return out;
+  }
+};
+
+// 1 Image with neighborhood of VariableLengthVector -> 1 image with
+// VariableLengthVector
+// For each channel, returns the maximum value in neighborhood
+template<typename T> struct MaxInEachChannel
+{
+  auto operator()(const itk::Neighborhood<itk::VariableLengthVector<T>> & in) const
+  {
+    auto out = in.GetCenterValue();
+
+    for(auto it = in.Begin(); it!=in.End(); ++it)
+      {
+      for(auto band = 0u; band < out.Size();++band)
+        {
+        if((*it)[band]>out[band])
+          out[band] = (*it)[band];
+        }
+      }
+    return out;
+  }
+
+  size_t OutputSize(const std::array<size_t,1> & nbBands) const
+  {
+    return nbBands[0];
+  } 
+};
+
+
+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];
+  }
+};
+
+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}};
+  
+  vimage->SetRegions(size);
+  vimage->SetNumberOfComponentsPerPixel(2);
+  vimage->Allocate();
+  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->SetVariadicInput<0>(vimage);
+  filter->SetVariadicInput<1>(image);
+
+  filter->SetInput1(vimage);
+  filter->SetInput2(image);
+
+  filter->SetVariadicInputs(vimage,image);
+  std::cout<<filter->GetVariadicInput<0>()<< filter->GetVariadicInput<1>()<<std::endl;
+
+  // Test VariadicNamedInputsImageFilter
+  struct xs {};
+  struct pan {};
+  using Names = std::tuple<xs,pan>; 
+   auto filterWithNames = otb::VariadicNamedInputsImageFilter<VectorImageType, Names, VectorImageType,ImageType>::New();
+   filterWithNames->SetVariadicNamedInput<xs>(vimage);
+  
+  // Test FunctorImageFilter with a built-in math function
+  using CosType = double(double);
+  auto filterCos = NewFunctorFilter(static_cast<CosType *>(std::cos));
+  filterCos->SetVariadicInputs(image);
+  filterCos->Update();
+    
+   filterWithNames->SetVariadicNamedInput<pan>(image);
+
+   std::cout<<filterWithNames->GetVariadicNamedInput<xs>()<< filterWithNames->GetVariadicNamedInput<pan>()<<std::endl;
+
+  
+  
+  // test FunctorImageFilter with a lambda
+  double scale = 10.;  
+  auto Lambda1 = [scale](double p)
+               {
+                 return scale*p;
+               };
+  auto filterLambda = NewFunctorFilter(Lambda1);
+  filterLambda->SetVariadicInputs(image);
+  filterLambda->Update();
+
+  // test FunctorImageFilter with a lambda that returns a
+  // VariableLengthVector
+  // Converts a neighborhood to a VariableLengthVector
+  auto Lambda2 = [](const itk::Neighborhood<double> & in)
+                 {
+                   itk::VariableLengthVector<double> out(in.Size());
+                   std::size_t idx{0};
+                   for(auto it = in.Begin(); it!=in.End();++it,++idx)
+                     {
+                     out[idx]=*it;
+                     }
+                   return out;
+                 };
+
+  // In this case, we use the helper function which allows to specify
+  // the number of outputs
+  auto filterLambda2  = NewFunctorFilter(Lambda2,vimage->GetNumberOfComponentsPerPixel(),{{3,3}});
+  filterLambda2->SetVariadicInputs(image);
+  filterLambda2->Update();
+  
+  // Test FunctorImageFilter with the VariadicConcatenate operator
+  using ConcatFunctorType = Functor::VariadicConcatenate<double, double, itk::VariableLengthVector<double> >;
+  auto concatenate = NewFunctorFilter(ConcatFunctorType{});
+  concatenate->SetVariadicInputs(image,vimage);
+  concatenate->Update();
+  
+  // Test FunctorImageFilter With VariadicAdd functor
+  using AddFunctorType = Functor::VariadicAdd<double, double, double>;
+  auto add = NewFunctorFilter(AddFunctorType{});
+  add->SetVariadicInput<0>(image);
+  add->SetVariadicInput<1>(image);
+  add->Update();
+
+  // Test FunctorImageFilter with BandExtraction functor
+  using ExtractFunctorType = BandExtraction<double,double>;
+  ExtractFunctorType extractFunctor{1,2};
+  auto extract = NewFunctorFilter(extractFunctor);
+  extract->SetVariadicInputs(vimage);
+  extract->Update();
+  
+  // Test FunctorImageFilter With Mean functor
+  using MeanFunctorType = Mean<double,double>;
+  auto median = NewFunctorFilter(MeanFunctorType{},{{2,2}});
+  median->SetVariadicInputs(image);
+  median->Update();
+
+  // Test FunctorImageFilter with MaxInEachChannel
+  using MaxInEachChannelType = MaxInEachChannel<double>;
+  auto maxInEachChannel = NewFunctorFilter(MaxInEachChannelType{},{{3,3}});
+  maxInEachChannel->SetVariadicInputs(vimage);
+  maxInEachChannel->Update();
+
+  // Test FunctorImageFilter with Module (complex=
+  using ModulusType = VectorModulus<double>;
+  auto modulus = NewFunctorFilter(ModulusType{});
+  modulus->SetVariadicInputs(cvimage);
+  modulus->Update();
+
+  auto LambdaComplex = [] (const std::complex<double> & in) {return std::arg(in);};
+  auto argFilter = NewFunctorFilter(LambdaComplex);
+  argFilter->SetVariadicInputs(cimage);
+  argFilter->Update();
+  
+ return EXIT_SUCCESS;
+}
+
diff --git a/Modules/Core/Functor/test/otbFunctorTestDriver.cxx b/Modules/Core/Functor/test/otbFunctorTestDriver.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..860a5e38ddbbdea1b8bed4a94dd4ca09b4667643
--- /dev/null
+++ b/Modules/Core/Functor/test/otbFunctorTestDriver.cxx
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbTestMain.h"
+
+void RegisterTests()
+{
+  REGISTER_TEST(otbFunctorImageFilter);
+}
diff --git a/Modules/Core/ImageBase/test/CMakeLists.txt b/Modules/Core/ImageBase/test/CMakeLists.txt
index 4e1896b536bbbf6e149d29f06e37783b755e2fce..abed0364f142c81d85af113a7cdf0d7fd67e0f26 100644
--- a/Modules/Core/ImageBase/test/CMakeLists.txt
+++ b/Modules/Core/ImageBase/test/CMakeLists.txt
@@ -40,7 +40,6 @@ set(OTBImageBaseTests
   otbImageTest.cxx
   otbImageFunctionAdaptor.cxx
   otbMetaImageFunction.cxx
-
   )
 
 add_executable(otbImageBaseTestDriver ${OTBImageBaseTests})