diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.h b/Modules/Core/Functor/include/otbFunctorImageFilter.h index 1a7daba4eccbd8bd88ea12de33b87ae1fc1b818a..3af0e552c3ac1df83b5ebdce796a521cfbfeae06 100644 --- a/Modules/Core/Functor/include/otbFunctorImageFilter.h +++ b/Modules/Core/Functor/include/otbFunctorImageFilter.h @@ -83,7 +83,7 @@ template <class T> struct IsSuitableType<itk::VariableLengthVector<T>> { }; /// Unwrap FixedArray -template <class T> struct IsSuitableType<itk::FixedArray<T>> { +template <class T, size_t N> struct IsSuitableType<itk::FixedArray<T,N>> { static constexpr bool value = IsSuitableType<T>::value; }; @@ -218,7 +218,7 @@ template <typename C, typename R, typename... T> struct FunctorFilterSuperclassH * - returns T or itk::VariableLengthVector<T>, with T a scalar type * * The returned filter is ready to use. Inputs can be set through the - * SetVInputs() method (see VariadicInputsImageFilter class for + * SetVariadicInputs() method (see VariadicInputsImageFilter class for * details) * * \param f the Functor to build the filter from diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx index edfea3c78d763ba2f2c20e24308830f0c4b34caa..f0a1dc9100410f2d2eb9a71d0f8efab54b35158e 100644 --- a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx +++ b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx @@ -196,7 +196,7 @@ FunctorImageFilter<TFunction> // 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(this->GetVInputs(),requestedRegion, m_Radius); + functor_filter_details::SetInputRequestedRegions(this->GetVariadicInputs(),requestedRegion, m_Radius); } template <class TFunction> @@ -207,7 +207,7 @@ FunctorImageFilter<TFunction>::GenerateOutputInformation() Superclass::GenerateOutputInformation(); // Get All variadic inputs - auto inputs = this->GetVInputs(); + auto inputs = this->GetVariadicInputs(); // Retrieve an array of number of components per input auto inputNbComps = functor_filter_details::GetNumberOfComponentsPerInput(inputs); @@ -228,7 +228,7 @@ FunctorImageFilter<TFunction> itk::ImageScanlineIterator<OutputImageType> outIt(this->GetOutput(),outputRegionForThread); itk::ProgressReporter p(this,threadId,outputRegionForThread.GetNumberOfPixels()); - auto inputIterators = functor_filter_details::MakeIterators(this->GetVInputs(),outputRegionForThread, m_Radius,InputHasNeighborhood{}); + auto inputIterators = functor_filter_details::MakeIterators(this->GetVariadicInputs(),outputRegionForThread, m_Radius,InputHasNeighborhood{}); while(!outIt.IsAtEnd()) { diff --git a/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h b/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h index f66752e6f08313c717ea72b94b869d918b9b6cf2..5ed4a29e85d2ea44fe23b51131349d61574b552d 100644 --- a/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h +++ b/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h @@ -42,7 +42,7 @@ public: itkNewMacro(Self); - template <std::size_t I> void SetVInput(const typename std::tuple_element<I,InputTypesTupleType>::type * inputPtr) + template <std::size_t I> void SetVariadicInput(const typename std::tuple_element<I,InputTypesTupleType>::type * inputPtr) { this->SetNthInput(I,const_cast<typename std::tuple_element<I,InputTypesTupleType>::type *>(inputPtr)); } @@ -51,7 +51,7 @@ public: 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 SetVInput<n-1>(img); \ + this->template SetVariadicInput<n-1>(img); \ } // The following defines legacy setters SetInput1() @@ -69,19 +69,19 @@ public: #undef DefineLegacySetInputMacro - template <std::size_t I> const typename std::tuple_element<I,InputTypesTupleType>::type * GetVInput() + template <std::size_t I> const typename std::tuple_element<I,InputTypesTupleType>::type * GetVariadicInput() { using ImageType = typename std::tuple_element<I,InputTypesTupleType>::type; return dynamic_cast<const ImageType *>(this->GetInput(I)); } - void SetVInputs(TInputs*... inputs) + void SetVariadicInputs(TInputs*... inputs) { auto inTuple = std::make_tuple(inputs...); SetInputsImpl(inTuple,std::make_index_sequence<sizeof...(inputs)>{}); } - auto GetVInputs() + auto GetVariadicInputs() { return GetInputsImpl(std::make_index_sequence<sizeof...(TInputs)>{}); } @@ -97,12 +97,12 @@ protected: private: template<class Tuple, size_t...Is> auto SetInputsImpl(Tuple& t, std::index_sequence<Is...>) { - return std::initializer_list<int>{(this->SetVInput<Is>(std::get<Is>(t)),0)...}; + 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->GetVInput<Is>()...); + return std::make_tuple(this->GetVariadicInput<Is>()...); } VariadicInputsImageFilter(const Self&) = delete; diff --git a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx index cf42cb22b5dac736e708ad85a64bb65442d5436d..44fe64ea55b3c369094cfc7fb1c5f1325a2cb07d 100644 --- a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx +++ b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx @@ -39,26 +39,38 @@ 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 - static_assert(!otb::IsNeighborhood<ScalarType>::value,""); - static_assert(!otb::IsNeighborhood<VectorType>::value,""); - static_assert(otb::IsNeighborhood<NeighborhoodType>::value,""); - static_assert(otb::IsNeighborhood<VectorNeighborhoodType>::value,""); - static_assert(otb::IsNeighborhood<const NeighborhoodType &>::value,""); - static_assert(otb::IsNeighborhood<const VectorNeighborhoodType &>::value,""); + 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 - static_assert(std::is_same<typename PixelTypeDeduction<ScalarType>::PixelType,ScalarType>::value,""); - static_assert(std::is_same<typename PixelTypeDeduction<VectorType>::PixelType,VectorType>::value,""); - static_assert(std::is_same<typename PixelTypeDeduction<NeighborhoodType>::PixelType,ScalarType>::value,""); - static_assert(std::is_same<typename PixelTypeDeduction<VectorNeighborhoodType>::PixelType,VectorType>::value,""); - static_assert(std::is_same<typename PixelTypeDeduction<const NeighborhoodType &>::PixelType,ScalarType>::value,""); - static_assert(std::is_same<typename PixelTypeDeduction<const VectorNeighborhoodType &>::PixelType,VectorType>::value,""); + 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,""); @@ -102,10 +114,20 @@ template <typename T> struct TypesCheck static_assert(FilterType::NumberOfInputs == 1,""); static_assert(std::is_same<typename FilterType::template InputImageType<0>, InputImageType>::value, ""); - filter->SetVInputs(in); + filter->SetVariadicInputs(in); filter->SetInput1(in); - filter->template SetVInput<0>(in); // template keyword to avoid C++ parse ambiguity + filter->template SetVariadicInput<0>(in); // template keyword to avoid C++ parse ambiguity filter->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(); } TypesCheck() @@ -264,14 +286,14 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) // Test VariadicInputsImageFilter auto filter = otb::VariadicInputsImageFilter<VectorImageType,VectorImageType,ImageType>::New(); - filter->SetVInput<0>(vimage); - filter->SetVInput<1>(image); + filter->SetVariadicInput<0>(vimage); + filter->SetVariadicInput<1>(image); filter->SetInput1(vimage); filter->SetInput2(image); - filter->SetVInputs(vimage,image); - std::cout<<filter->GetVInput<0>()<< filter->GetVInput<1>()<<std::endl; + filter->SetVariadicInputs(vimage,image); + std::cout<<filter->GetVariadicInput<0>()<< filter->GetVariadicInput<1>()<<std::endl; // test FunctorImageFilter with a lambda @@ -281,7 +303,7 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) return scale*p; }; auto filterLambda = NewFunctorFilter(Lambda1); - filterLambda->SetVInputs(image); + filterLambda->SetVariadicInputs(image); filterLambda->Update(); // test FunctorImageFilter with a lambda that returns a @@ -301,49 +323,49 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) // 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->SetVInputs(image); + 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->SetVInputs(image,vimage); + concatenate->SetVariadicInputs(image,vimage); concatenate->Update(); // Test FunctorImageFilter With VariadicAdd functor using AddFunctorType = Functor::VariadicAdd<double, double, double>; auto add = NewFunctorFilter(AddFunctorType{}); - add->SetVInputs(image,image); + add->SetVariadicInputs(image,image); add->Update(); // Test FunctorImageFilter with BandExtraction functor using ExtractFunctorType = BandExtraction<double,double>; ExtractFunctorType extractFunctor{1,2}; auto extract = NewFunctorFilter(extractFunctor); - extract->SetVInputs(vimage); + extract->SetVariadicInputs(vimage); extract->Update(); // Test FunctorImageFilter With Mean functor using MeanFunctorType = Mean<double,double>; auto median = NewFunctorFilter(MeanFunctorType{},{{2,2}}); - median->SetVInputs(image); + median->SetVariadicInputs(image); median->Update(); // Test FunctorImageFilter with MaxInEachChannel using MaxInEachChannelType = MaxInEachChannel<double>; auto maxInEachChannel = NewFunctorFilter(MaxInEachChannelType{},{{3,3}}); - maxInEachChannel->SetVInputs(vimage); + maxInEachChannel->SetVariadicInputs(vimage); maxInEachChannel->Update(); // Test FunctorImageFilter with Module (complex= using ModulusType = VectorModulus<double>; auto modulus = NewFunctorFilter(ModulusType{}); - modulus->SetVInputs(cvimage); + modulus->SetVariadicInputs(cvimage); modulus->Update(); auto LambdaComplex = [] (const std::complex<double> & in) {return std::arg(in);}; auto argFilter = NewFunctorFilter(LambdaComplex); - argFilter->SetVInputs(cimage); + argFilter->SetVariadicInputs(cimage); argFilter->Update(); return EXIT_SUCCESS;