diff --git a/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.h b/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..ffbbcc69c1998e5140b033abf4eaf64b762154bf --- /dev/null +++ b/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.h @@ -0,0 +1,175 @@ +/* + * 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 "itkImageToImageFilter.h" +#include "otbImage.h" +#include "otbVectorImage.h" +#include "itkConstNeighborhoodIterator.h" +#include "itkProcessObject.h" +#include <type_traits> + +namespace otb +{ + +template<typename TOutput> +struct ImageFunctorBase +{ + using OutputImageType = typename std::conditional<std::is_scalar<TOutput>::value, + otb::Image<TOutput>, + otb::VectorImage<TOutput>>::type; + + void SetRadius(size_t r) + { + m_Radius = r; + } + +protected: + size_t m_Radius = 0; + +}; + +template<typename TInput, typename TOutput> +struct ImageFunctor : ImageFunctorBase<TOutput> { + using HasNeighborhood = std::false_type; + using InputImageType = typename std::conditional<std::is_scalar<TInput>::value, + otb::Image<TInput>, + otb::VectorImage<TInput>>::type; + +}; + + +template<typename TInput, typename TOutput> +struct ImageFunctor<typename itk::ConstNeighborhoodIterator<TInput>, + TOutput> : ImageFunctorBase<TOutput> { + using HasNeighborhood = std::true_type; + using InputImageType = TInput; +}; + +/** \class FunctorImageFilter + * \brief Implements + * + * This class is + * + * \ingroup IntensityImageFilters Multithreaded + * + * \ingroup OTBImageManipulation + */ +template <class TFunction> +class ITK_EXPORT FunctorImageFilter + : public itk::ImageToImageFilter<typename TFunction::InputImageType, + typename TFunction::OutputImageType> +{ +public: + using Self = FunctorImageFilter; + using FunctorType = TFunction; + using Pointer = itk::SmartPointer<Self>; + using ConstPointer = itk::SmartPointer<const Self>; + using InputImageType = typename FunctorType::InputImageType; + using InputImagePointer = typename InputImageType::ConstPointer; + using InputImageRegionType = typename InputImageType::RegionType; + using InputImagePixelType = typename InputImageType::PixelType; + using InputImageSizeType = typename InputImageType::SizeType; + using InputImageIndexType = typename InputImageType::IndexType; + using OutputImageType = typename FunctorType::OutputImageType; + using OutputImagePointer = typename OutputImageType::Pointer; + using OutputImageRegionType = typename OutputImageType::RegionType; + using OutputImagePixelType = typename OutputImageType::PixelType; + using Superclass = itk::ImageToImageFilter<InputImageType, + OutputImageType>; + using ProcessObjectType = itk::ProcessObject; + +/** Method for creation by passing the filter type. */ + itkNewMacro(Self); + + +/** Run-time type information (and related methods). */ +itkTypeMacro(FunctorImageFilter, ImageToImageFilter); + + +/** 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.) */ +FunctorType& GetFunctor() +{ + this->Modified(); + return m_Functor; +} + +/** 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.) */ +const FunctorType& GetFunctor() const +{ + return m_Functor; +} + +/** Set the functor object. This replaces the current Functor with a + * copy of the specified Functor. This allows the user to specify a + * functor that has ivars set differently than the default functor. + * This method requires an operator!=() be defined on the functor + * (or the compiler's default implementation of operator!=() being + * appropriate). */ +void SetFunctor(const FunctorType& functor) +{ + m_Functor = functor; + this->Modified(); +} + +private: +FunctorImageFilter(){} ; +FunctorImageFilter(const Self &) ; +void operator =(const Self&) ; +~FunctorImageFilter() override {} + +protected: + +/** FunctorImageFilter can be implemented as a multithreaded filter. + * Therefore, this implementation provides a ThreadedGenerateData() routine + * which is called for each processing thread. The output image data is + * allocated automatically by the superclass prior to calling + * ThreadedGenerateData(). ThreadedGenerateData can only write to the + * portion of the output image specified by the parameter + * "outputRegionForThread" + * + * \sa ImageToImageFilter::ThreadedGenerateData(), + * ImageToImageFilter::GenerateData() */ + void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) override; + + /** + * Pad the input requested region by radius + */ + void GenerateInputRequestedRegion(void) override; + + + FunctorType m_Functor; +}; + +} // namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbFunctorImageFilter.hxx" +#endif + +#endif diff --git a/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.hxx b/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.hxx new file mode 100644 index 0000000000000000000000000000000000000000..e5006d887dc998a83dc555076a4fe45c29750ef5 --- /dev/null +++ b/Modules/Filtering/ImageManipulation/include/otbFunctorImageFilter.hxx @@ -0,0 +1,54 @@ +/* + * 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 "itkImageRegionIterator.h" +#include "itkProgressReporter.h" + +namespace otb +{ + +template <class TFunction> +void +FunctorImageFilter<TFunction> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); +} + +/** + * ThreadedGenerateData Performs the neighborhood-wise operation + */ +template <class TFunction> +void +FunctorImageFilter<TFunction> +::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) +{ + (void) outputRegionForThread; + (void) threadId; +} + +} // end namespace otb + +#endif diff --git a/Modules/Filtering/ImageManipulation/test/CMakeLists.txt b/Modules/Filtering/ImageManipulation/test/CMakeLists.txt index adc522717529ad846c0ebfcc477d431321f2e43b..92822a25e405db615390f57b6745bca381721fd4 100644 --- a/Modules/Filtering/ImageManipulation/test/CMakeLists.txt +++ b/Modules/Filtering/ImageManipulation/test/CMakeLists.txt @@ -71,6 +71,7 @@ otbImageToNoDataMaskFilter.cxx otbChangeInformationImageFilter.cxx otbGridResampleImageFilter.cxx otbMaskedIteratorDecorator.cxx +otbFunctorFilter.cxx ) add_executable(otbImageManipulationTestDriver ${OTBImageManipulationTests}) @@ -621,3 +622,7 @@ otb_add_test(NAME bfTvMaskedIteratorDecoratorDegenerate COMMAND otbImageManipula otb_add_test(NAME bfTvMaskedIteratorDecoratorExtended COMMAND otbImageManipulationTestDriver otbMaskedIteratorDecoratorExtended ) + +otb_add_test(NAME bfTvFunctorFilter COMMAND otbImageManipulationTestDriver + otbFunctorFilter + ) diff --git a/Modules/Filtering/ImageManipulation/test/otbFunctorImageFilter.cxx b/Modules/Filtering/ImageManipulation/test/otbFunctorImageFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9e82bd71d9b85ae14bf0f246797b92452020d139 --- /dev/null +++ b/Modules/Filtering/ImageManipulation/test/otbFunctorImageFilter.cxx @@ -0,0 +1,60 @@ +/* + * 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" + +struct Funct1 : otb::ImageFunctor<double, double> +{ + double operator()(double p) + { + return p; + } +}; + +struct Funct2 : otb::ImageFunctor<double, itk::VariableLengthVector<double>> +{ + itk::VariableLengthVector<double> operator()(double p) + { + itk::VariableLengthVector<double> result(2); + result[0] = result[1] = p; + return result; + } +}; + +using IntImageNeighborhood = itk::ConstNeighborhoodIterator<otb::Image<int>>; +struct Funct3 : otb::ImageFunctor<IntImageNeighborhood, + double> +{ + double operator()(IntImageNeighborhood p) + { + return static_cast<double>(p.GetPixel(0)); + } +}; + + +int otbFunctorFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) +{ + auto filter1 = otb::FunctorImageFilter<Funct1>::New(); + auto filter2 = otb::FunctorImageFilter<Funct2>::New(); + auto filter3 = otb::FunctorImageFilter<Funct3>::New(); + return EXIT_SUCCESS; +} + diff --git a/Modules/Filtering/ImageManipulation/test/otbImageManipulationTestDriver.cxx b/Modules/Filtering/ImageManipulation/test/otbImageManipulationTestDriver.cxx index 08aa5acb7d90cf47b890599f0fb7e802e2b37e86..739dd773048a50de7ce234d1a41dc9b597150f66 100644 --- a/Modules/Filtering/ImageManipulation/test/otbImageManipulationTestDriver.cxx +++ b/Modules/Filtering/ImageManipulation/test/otbImageManipulationTestDriver.cxx @@ -74,4 +74,5 @@ void RegisterTests() REGISTER_TEST(otbMaskedIteratorDecoratorNominal); REGISTER_TEST(otbMaskedIteratorDecoratorDegenerate); REGISTER_TEST(otbMaskedIteratorDecoratorExtended); + REGISTER_TEST(otbFunctorImageFilter); }