Commit 0397595a authored by Julien Michel's avatar Julien Michel

ENH: Introducing named inputs

parent 09877b54
......@@ -21,7 +21,7 @@
#ifndef otbFunctorImageFilter_h
#define otbFunctorImageFilter_h
#include "otbVariadicInputsImageFilter.h"
#include "otbVariadicNamedInputsImageFilter.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "itkDefaultConvertPixelTraits.h"
......@@ -122,29 +122,46 @@ template <class T> struct ImageTypeDeduction<const T &>
* - InputHasNeighborhood a tuple of N false_type or true_type to denote
* - if Ith arg of operator() expects a neighborhood.
*/
template <typename T> struct FunctorFilterSuperclassHelper : public FunctorFilterSuperclassHelper<decltype(&T::operator())> {};
template <typename T, typename TNameMap> struct FunctorFilterSuperclassHelper : public FunctorFilterSuperclassHelper<decltype(&T::operator()),TNameMap> {};
/// Partial specialisation for R(*)(T...)
template <typename R, typename... T> struct FunctorFilterSuperclassHelper<R(*)(T...)>
template <typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(*)(T...),TNameMap>
{
using OutputImageType = typename ImageTypeDeduction<R>::ImageType;
using FilterType = VariadicInputsImageFilter<OutputImageType,typename ImageTypeDeduction<typename PixelTypeDeduction<T>::PixelType>::ImageType...>;
template <typename V> using InputImageType = typename ImageTypeDeduction<typename PixelTypeDeduction<V>::PixelType>::ImageType;
using FilterType = typename std::conditional<std::is_void<TNameMap>::value,
VariadicInputsImageFilter<OutputImageType,InputImageType<T>...>,
VariadicNamedInputsImageFilter<OutputImageType,TNameMap,InputImageType<T>...>>::type;
using InputHasNeighborhood = std::tuple<typename IsNeighborhood<T>::ValueType...>;
};
// Partial specialisation for R(C::*)(T...) const
template <typename C, typename R, typename... T> struct FunctorFilterSuperclassHelper<R(C::*)(T...) const>
template <typename C, typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(C::*)(T...) const, TNameMap>
{
using OutputImageType = typename ImageTypeDeduction<R>::ImageType;
using FilterType = VariadicInputsImageFilter<OutputImageType,typename ImageTypeDeduction<typename PixelTypeDeduction<T>::PixelType>::ImageType...>;
template <typename V> using InputImageType = typename ImageTypeDeduction<typename PixelTypeDeduction<V>::PixelType>::ImageType;
using FilterType = typename std::conditional<std::is_void<TNameMap>::value,
VariadicInputsImageFilter<OutputImageType,InputImageType<T>...>,
VariadicNamedInputsImageFilter<OutputImageType,TNameMap,InputImageType<T>...>>::type;
using InputHasNeighborhood = std::tuple<typename IsNeighborhood<T>::ValueType...>;
};
// Partial specialisation for R(C::*)(T...)
template <typename C, typename R, typename... T> struct FunctorFilterSuperclassHelper<R(C::*)(T...)>
template <typename C, typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(C::*)(T...), TNameMap>
{
using OutputImageType = typename ImageTypeDeduction<R>::ImageType;
using FilterType = VariadicInputsImageFilter<OutputImageType,typename ImageTypeDeduction<typename PixelTypeDeduction<T>::PixelType>::ImageType...>;
template <typename V> using InputImageType = typename ImageTypeDeduction<typename PixelTypeDeduction<V>::PixelType>::ImageType;
using FilterType = typename std::conditional<std::is_void<TNameMap>::value,
VariadicInputsImageFilter<OutputImageType,InputImageType<T>...>,
VariadicNamedInputsImageFilter<OutputImageType,TNameMap,InputImageType<T>...>>::type;
using InputHasNeighborhood = std::tuple<typename IsNeighborhood<T>::ValueType...>;
};
......@@ -173,7 +190,7 @@ template <typename C, typename R, typename... T> struct FunctorFilterSuperclassH
* provided it returns a scalar type. If your lambda returns a
* VariableLengthVector, see the other NewFunctorFilter implementation.
*/
template <typename Functor> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius = {{0,0}});
template <typename Functor, typename TNameMap = void> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius = {{0,0}});
/** \class FunctorImageFilter
......@@ -186,9 +203,9 @@ template <typename Functor> auto NewFunctorFilter(const Functor& f, itk::Size<2>
*
* \ingroup OTBFunctor
*/
template <class TFunction>
template <class TFunction, class TNameMap = void>
class ITK_EXPORT FunctorImageFilter
: public FunctorFilterSuperclassHelper<TFunction>::FilterType
: public FunctorFilterSuperclassHelper<TFunction, TNameMap>::FilterType
{
public:
......@@ -199,7 +216,8 @@ public:
using ConstPointer = itk::SmartPointer<const Self>;
// Superclass through the helper struct
using Superclass = typename FunctorFilterSuperclassHelper<TFunction>::FilterType;
using SuperclassHelper = FunctorFilterSuperclassHelper<TFunction,TNameMap>;
using Superclass = typename SuperclassHelper::FilterType;
using OutputImageType = typename Superclass::OutputImageType;
using OutputImageRegionType = typename OutputImageType::RegionType;
......@@ -207,7 +225,7 @@ public:
// A tuple of bool of the same size as the number of arguments in
// the functor
using InputHasNeighborhood = typename FunctorFilterSuperclassHelper<TFunction>::InputHasNeighborhood;
using InputHasNeighborhood = typename SuperclassHelper::InputHasNeighborhood;
using InputTypesTupleType = typename Superclass::InputTypesTupleType;
template<size_t I> using InputImageType = typename Superclass::template InputImageType<I>;
using Superclass::NumberOfInputs;
......@@ -244,7 +262,7 @@ protected:
private:
/// Actual creation of the filter is handled by this free function
friend auto NewFunctorFilter<TFunction>(const TFunction& f, itk::Size<2> radius);
friend auto NewFunctorFilter<TFunction,TNameMap>(const TFunction& f, itk::Size<2> radius);
/** Overload of ThreadedGenerateData */
void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) override;
......@@ -268,9 +286,9 @@ private:
};
// Actual implementation of NewFunctorFilter free function
template <typename Functor> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius)
template <typename Functor, typename TNameMap> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius)
{
using FilterType = FunctorImageFilter<Functor>;
using FilterType = FunctorImageFilter<Functor,TNameMap>;
using PointerType = typename FilterType::Pointer;
PointerType p = new FilterType(f,radius);
......@@ -325,11 +343,11 @@ private:
*/
template <typename Functor> auto NewFunctorFilter(const Functor& f, unsigned int numberOfOutputBands, itk::Size<2> radius)
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(decoratedF,radius);
return NewFunctorFilter<FunctorType,TNameMap>(decoratedF,radius);
}
......
......@@ -176,9 +176,9 @@ template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::Vec
} // end namespace functor_filter_details
template <class TFunction>
template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction>
FunctorImageFilter<TFunction, TNameMap>
::GenerateInputRequestedRegion()
{
// Get requested region for output
......@@ -191,9 +191,9 @@ FunctorImageFilter<TFunction>
functor_filter_details::SetInputRequestedRegions(this->GetVInputs(),requestedRegion, m_Radius);
}
template <class TFunction>
template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction>::GenerateOutputInformation()
FunctorImageFilter<TFunction, TNameMap>::GenerateOutputInformation()
{
// Call Superclass implementation
Superclass::GenerateOutputInformation();
......@@ -211,9 +211,9 @@ FunctorImageFilter<TFunction>::GenerateOutputInformation()
/**
* ThreadedGenerateData Performs the neighborhood-wise operation
*/
template <class TFunction>
template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction>
FunctorImageFilter<TFunction, TNameMap>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
{
// Build output iterator
......
/*
* 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 SetVNamedInput(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> * GetVNamedInput()
{
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
......@@ -25,6 +25,7 @@
#include "itkNeighborhood.h"
#include "otbVariadicAddFunctor.h"
#include "otbVariadicConcatenateFunctor.h"
#include "otbVariadicNamedInputsImageFilter.h"
#include <tuple>
#include <numeric>
......@@ -99,7 +100,7 @@ template <typename T> struct TypesCheck
// 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, "");
......@@ -108,6 +109,13 @@ template <typename T> struct TypesCheck
filter->SetInput1(in);
filter->template SetVInput<0>(in); // template keyword to avoid C++ parse ambiguity
filter->Update();
// Test named input version
struct tag{};
using inputNames = std::tuple<tag>;
auto filter1 = NewFunctorFilter<decltype(functor),inputNames>(functor);
filter1->template SetVNamedInput<tag>(in);
filter1->Update();
}
TypesCheck()
......@@ -274,6 +282,17 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
filter->SetVInputs(vimage,image);
std::cout<<filter->GetVInput<0>()<< filter->GetVInput<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->SetVNamedInput<xs>(vimage);
filterWithNames->SetVNamedInput<pan>(image);
std::cout<<filterWithNames->GetVNamedInput<xs>()<< filterWithNames->GetVNamedInput<pan>()<<std::endl;
// test FunctorImageFilter with a lambda
double scale = 10.;
......@@ -314,6 +333,8 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
// Test FunctorImageFilter With VariadicAdd functor
using AddFunctorType = Functor::VariadicAdd<double, double, double>;
auto add = NewFunctorFilter(AddFunctorType{});
add->SetVInput<0>(image);
add->SetVInput<1>(image);
add->SetVInputs(image,image);
add->Update();
......@@ -346,7 +367,7 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
auto argFilter = NewFunctorFilter(LambdaComplex);
argFilter->SetVInputs(cimage);
argFilter->Update();
return EXIT_SUCCESS;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment