diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.h b/Modules/Core/Functor/include/otbFunctorImageFilter.h index e303687afb8f04365aeed5efd06ce427c30a98dc..44d99daaac9b78f03d6a64bd62a2d94d484dd81c 100644 --- a/Modules/Core/Functor/include/otbFunctorImageFilter.h +++ b/Modules/Core/Functor/include/otbFunctorImageFilter.h @@ -29,6 +29,8 @@ #include "itkFixedArray.h" #include "itkDefaultConvertPixelTraits.h" #include <type_traits> +#include "itkConstNeighborhoodIterator.h" +#include "otbImage.h" namespace otb { @@ -41,13 +43,19 @@ namespace otb * - value set to true or false */ template <class T> struct IsNeighborhood : std::false_type {}; - +/* /// Partial specialisation for itk::Neighborhood<T> template <class T> struct IsNeighborhood<itk::Neighborhood<T>> : std::true_type {}; - - +*/ +/* /// Partial specialisation for const itk::Neighborhood<T> & template <class T> struct IsNeighborhood<const itk::Neighborhood<T>&> : std::true_type {}; +*/ +/// Partial specialisation for const ConstNeighborhoodIterator<Image::T> & +template <class T> struct IsNeighborhood<const itk::ConstNeighborhoodIterator<Image<T>>&> : std::true_type {}; + +/// Partial specialisation for const ConstNeighborhoodIterator<VectorImage::T> & +template <class T> struct IsNeighborhood<const itk::ConstNeighborhoodIterator<VectorImage<T>>&> : std::true_type {}; /** * \struct IsSuitableType @@ -88,13 +96,21 @@ template <class T> struct PixelTypeDeduction }; /// Partial specialisation for itk::Neighborhood<T> -template <class T> struct PixelTypeDeduction<itk::Neighborhood<T>> +template <class T> struct PixelTypeDeduction<itk::ConstNeighborhoodIterator<Image<T>>> { 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::ConstNeighborhoodIterator<VectorImage<T>>> +{ + static_assert(IsSuitableType<T>::value, + "T can not be used as a template parameter for Image or VectorImage classes."); + using PixelType = itk::VariableLengthVector<T>; +}; + /** * \struct ImageTypeDeduction * \brief Helper struct to derive ImageType from template parameter diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx index 4686961489593be4f820a0f9e5f6e9d3c115a53f..5b2a0fbabfda46558f25134e5fc35c2a6faae029 100644 --- a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx +++ b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx @@ -138,7 +138,7 @@ template <typename T> struct GetProxy<itk::ConstNeighborhoodIterator<T> > { static decltype(auto) Get(const itk::ConstNeighborhoodIterator<T> & t) { - return t.GetNeighborhood(); + return t; } }; diff --git a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx index 6155c35a409fb883adf389250957ddb8c5bdabc8..16fe5cf856f8cc4eb7b74ff7d909ea1d4dc4e48f 100644 --- a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx +++ b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx @@ -22,7 +22,6 @@ #include "otbFunctorImageFilter.h" #include "otbImage.h" #include "otbVectorImage.h" -#include "itkNeighborhood.h" #include "otbVariadicAddFunctor.h" #include "otbVariadicConcatenateFunctor.h" #include "otbVariadicNamedInputsImageFilter.h" @@ -45,13 +44,14 @@ template <typename T> struct TypesCheck 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>; + using NeighborhoodType = itk::ConstNeighborhoodIterator<ImageType>; + using VectorNeighborhoodType = itk::ConstNeighborhoodIterator<VectorImageType>; // Test IsNeighborhood struct template <typename U> struct CheckIsNeighborhood { - static constexpr bool value = !otb::IsNeighborhood<U>::value && otb::IsNeighborhood<itk::Neighborhood<U> >::value; + static constexpr bool value = !otb::IsNeighborhood<U>::value + && otb::IsNeighborhood<const itk::ConstNeighborhoodIterator<Image<U>>& >::value; }; static_assert(CheckIsNeighborhood<T>::value,""); @@ -64,7 +64,7 @@ template <typename T> struct TypesCheck 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; + && std::is_same<typename PixelTypeDeduction<itk::ConstNeighborhoodIterator<Image<U>>>::PixelType,U>::value; }; static_assert(CheckPixelTypeDeduction<T>::value,""); @@ -259,13 +259,15 @@ template<typename TOut, typename TIn> struct BandExtraction // This Functor computes the mean in neighborhood template<typename TOut, typename TIn> struct Mean { - auto operator()(const itk::Neighborhood<TIn> & in) const + auto operator()(const itk::ConstNeighborhoodIterator<otb::Image<TIn>> & in) const { TOut out(0); - for(auto it = in.Begin(); it!=in.End();++it) - out+=static_cast<TOut>(*it); - + for (auto idx = 0u; idx < in.Size(); idx++) + { + out+=static_cast<TOut>(in.GetPixel(idx)); + } + out/=in.Size(); return out; @@ -277,16 +279,16 @@ template<typename TOut, typename TIn> struct Mean // 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 operator()(const itk::ConstNeighborhoodIterator<otb::VectorImage<T>> & in) const { - auto out = in.GetCenterValue(); + auto out = in.GetCenterPixel(); - for(auto it = in.Begin(); it!=in.End(); ++it) + for (auto idx = 0u; idx < in.Size(); idx++) { for(auto band = 0u; band < out.Size();++band) { - if((*it)[band]>out[band]) - out[band] = (*it)[band]; + if(in.GetPixel(idx)[band] < out[band]) + out[band] = in.GetPixel(idx)[band]; } } return out; @@ -299,6 +301,34 @@ template<typename T> struct MaxInEachChannel }; +// 1 Image with neighborhood of VariableLengthVector -> 1 image +// this is a dummy functor that returns the first element of the vector at the +// center of the neighborhood +template<typename T> struct NeighborhoodVecInScalOut +{ + auto operator()(const itk::ConstNeighborhoodIterator<otb::VectorImage<T>> & in) const + { + float out = in.GetCenterPixel()[0]; + + return out; + } + +}; + +template<typename T> struct NeighborhoodArrayInScalOut +{ + auto operator()(const itk::ConstNeighborhoodIterator< otb::Image<itk::FixedArray<T,2>>> & in) const + { + float out = in.GetCenterPixel()[0]; + + return out; + } + +}; + + + + template<typename T> struct VectorModulus { itk::VariableLengthVector<double> operator()(const itk::VariableLengthVector<std::complex<T>> & in) const @@ -397,12 +427,11 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) // test FunctorImageFilter with a lambda that returns a // VariableLengthVector // Converts a neighborhood to a VariableLengthVector - auto Lambda2 = [](const itk::Neighborhood<double>& in) { + auto Lambda2 = [](const itk::ConstNeighborhoodIterator<otb::Image<double>>& in) { itk::VariableLengthVector<double> out(in.Size()); - std::size_t idx{0}; - for (auto it = in.Begin(); it != in.End(); ++it, ++idx) + for (size_t idx = 0; idx < in.Size(); idx++) { - out[idx] = *it; + out[idx] = in.GetPixel(idx); } return out; }; @@ -445,6 +474,26 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) maxInEachChannel->SetInputs(vimage); maxInEachChannel->Update(); + + using NeighborhoodVecInScalOutType = NeighborhoodVecInScalOut<double>; + auto neighborhoodVecInScalOut = NewFunctorFilter(NeighborhoodVecInScalOutType{}, {{3, 3}}); + neighborhoodVecInScalOut->SetInputs(vimage); + neighborhoodVecInScalOut->Update(); + + using ArrayImageType = Image<itk::FixedArray<double,2>>; + auto arrayImage = ArrayImageType::New(); + + arrayImage->SetRegions(size); + arrayImage->Allocate(); + itk::FixedArray<double,2> array; + array.Fill(0); + arrayImage->FillBuffer(array); + + using NeighborhoodArrayInScalOutType = NeighborhoodArrayInScalOut<double>; + auto neighborhoodArrayInScalOut = NewFunctorFilter(NeighborhoodArrayInScalOutType{}, {{3, 3}}); + neighborhoodArrayInScalOut->SetInputs(arrayImage); + neighborhoodArrayInScalOut->Update(); + // Test FunctorImageFilter with Module (complex= using ModulusType = VectorModulus<double>; auto modulus = NewFunctorFilter(ModulusType{});