diff --git a/Code/Radiometry/otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.h b/Code/Radiometry/otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.h index f9f2861d71802348c2271affd15efa568e83f48f..2bed2ed5a1705ed4735aba4550c0f71f5d920490 100644 --- a/Code/Radiometry/otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.h +++ b/Code/Radiometry/otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.h @@ -18,7 +18,7 @@ #ifndef __otbMultiChannelRAndBAndNIRVegetationIndexImageFilter_h #define __otbMultiChannelRAndBAndNIRVegetationIndexImageFilter_h -#include "itkInPlaceImageFilter.h" +#include "itkUnaryFunctorImageFilter.h" #include "itkImageRegionIteratorWithIndex.h" #include "otbVegetationIndex.h" @@ -26,72 +26,39 @@ namespace otb { /** \class MultiChannelRAndBAndNIRVegetationIndexImageFilter - * \brief Implements mutli channel R and B and NIR vegetation index operation, pixel-wise generic vegetation index operation on one vector image. + * \brief Implements mutli channel R and B and NIR pixel-wise generic vegetation index operation on one vector image. * * This class is parameterized over the type of the input image and * the type of the output image. It is also parameterized by the * operation to be applied, using a Functor style. * + * \sa UnaryFunctorImageFilter + * */ template <class TInputImage, class TOutputImage, -class TFunction = Functor::ARVI< typename TInputImage::InternalPixelType, -typename TInputImage::InternalPixelType, -typename TInputImage::InternalPixelType, -typename TOutputImage::PixelType> > -class ITK_EXPORT MultiChannelRAndBAndNIRVegetationIndexImageFilter : public itk::InPlaceImageFilter<TInputImage,TOutputImage> + class TFunction = Functor::ARVI< typename TInputImage::InternalPixelType, + typename TInputImage::InternalPixelType, + typename TInputImage::InternalPixelType, + typename TOutputImage::PixelType> > +class ITK_EXPORT MultiChannelRAndBAndNIRVegetationIndexImageFilter + : public itk::UnaryFunctorImageFilter<TInputImage,TOutputImage,TFunction> { public: /** Standard class typedefs. */ - typedef MultiChannelRAndBAndNIRVegetationIndexImageFilter Self; - typedef itk::InPlaceImageFilter<TInputImage,TOutputImage> Superclass; - typedef itk::SmartPointer<Self> Pointer; - typedef itk::SmartPointer<const Self> ConstPointer; + typedef MultiChannelRAndBAndNIRVegetationIndexImageFilter Self; + typedef itk::UnaryFunctorImageFilter<TInputImage,TOutputImage,TFunction> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); /** Run-time type information (and related methods). */ - itkTypeMacro(MultiChannelRAndBAndNIRVegetationIndexImageFilter, InPlaceImageFilter); + itkTypeMacro(MultiChannelRAndBAndNIRVegetationIndexImageFilter, UnaryFunctorImageFilter); /** Some typedefs. */ typedef TFunction FunctorType; - typedef TInputImage InputImageType; - typedef typename InputImageType::ConstPointer InputImagePointer; - typedef typename InputImageType::RegionType InputImageRegionType; - typedef typename InputImageType::PixelType InputImagePixelType; - typedef TOutputImage OutputImageType; - typedef typename OutputImageType::Pointer OutputImagePointer; - typedef typename OutputImageType::RegionType OutputImageRegionType; - typedef typename OutputImageType::PixelType OutputImagePixelType; - - /** 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() - { - return m_Functor; - }; - 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) - { - if (m_Functor != functor) - { - m_Functor = functor; - this->Modified(); - } - } - + /** Set/Get the red channel index. Value must be in [1...[ */ itkSetMacro(RedIndex,unsigned int); itkGetMacro(RedIndex,unsigned int); @@ -103,33 +70,29 @@ public: itkGetMacro(NIRIndex,unsigned int); protected: - MultiChannelRAndBAndNIRVegetationIndexImageFilter(); + /// Constructor + MultiChannelRAndBAndNIRVegetationIndexImageFilter(): m_RedIndex(3),m_BlueIndex(1),m_NIRIndex(4) {}; + /// Destructor virtual ~MultiChannelRAndBAndNIRVegetationIndexImageFilter() {}; - - /** MultiChannelRAndBAndNIRVegetationIndexImageFilter can produce an image which is a different - * resolution than its input image. As such, MultiChannelRAndBAndNIRVegetationIndexImageFilter - * needs to provide an implementation for - * GenerateOutputInformation() in order to inform the pipeline - * execution model. The original documentation of this method is - * below. - * - * \sa ProcessObject::GenerateOutputInformaton() */ - virtual void GenerateOutputInformation(); - - /** MultiChannelRAndBAndNIRVegetationIndexImageFilter 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, - int threadId ); - - void PrintSelf(std::ostream& os, itk::Indent indent) const; + /// Before generating data, set functor parameters + virtual void BeforeThreadedGenerateData() + { + if(m_RedIndex < 1 || m_BlueIndex < 1 || m_NIRIndex < 1) + { + itkExceptionMacro(<<"Channel indices must belong to range [1, ...["); + } + this->GetFunctor().SetRedIndex(m_RedIndex); + this->GetFunctor().SetBlueIndex(m_BlueIndex); + this->GetFunctor().SetNIRIndex(m_NIRIndex); + } + /// PrintSelf + void PrintSelf(std::ostream& os, itk::Indent indent) const + { + this->Superclass::PrintSelf(os,indent); + os << indent << "Red index: "<<m_RedIndex<<std::endl; + os << indent << "Blue index: "<<m_BlueIndex<<std::endl; + os << indent << "NIR index: "<<m_NIRIndex<<std::endl; + } private: MultiChannelRAndBAndNIRVegetationIndexImageFilter(const Self&); //purposely not implemented @@ -141,13 +104,8 @@ private: unsigned int m_BlueIndex; /** NIR channel index */ unsigned int m_NIRIndex; - FunctorType m_Functor; }; } // end namespace otb -#ifndef OTB_MANUAL_INSTANTIATION -#include "otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.txx" -#endif - #endif diff --git a/Code/Radiometry/otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.txx b/Code/Radiometry/otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.txx deleted file mode 100644 index 845266542904daa1e470b43e71072bdbe8e7b4bf..0000000000000000000000000000000000000000 --- a/Code/Radiometry/otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.txx +++ /dev/null @@ -1,197 +0,0 @@ -/*========================================================================= - - Program: ORFEO Toolbox - Language: C++ - Date: $Date$ - Version: $Revision$ - - - Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. - See OTBCopyright.txt for details. - - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#ifndef __otbMultiChannelRAndBAndNIRVegetationIndexImageFilter_txx -#define __otbMultiChannelRAndBAndNIRVegetationIndexImageFilter_txx - -#include "otbMultiChannelRAndBAndNIRVegetationIndexImageFilter.h" -#include "itkImageRegionIterator.h" -#include "itkImageRegionConstIterator.h" -#include "itkProgressReporter.h" - -namespace otb -{ - -/** - * Constructor - */ -template <class TInputImage, class TOutputImage, class TFunction > -MultiChannelRAndBAndNIRVegetationIndexImageFilter<TInputImage,TOutputImage,TFunction> -::MultiChannelRAndBAndNIRVegetationIndexImageFilter() -{ - this->SetNumberOfRequiredInputs( 1 ); - this->InPlaceOff(); -} - -/** - * MultiChannelRAndBAndNIRVegetationIndexImageFilter can produce an image which is a different resolution - * than its input image. As such, MultiChannelRAndBAndNIRVegetationIndexImageFilter needs to provide an - * implementation for GenerateOutputInformation() in order to inform - * the pipeline execution model. The original documentation of this - * method is below. - * - * \sa ProcessObject::GenerateOutputInformaton() - */ -template <class TInputImage, class TOutputImage, class TFunction> -void -MultiChannelRAndBAndNIRVegetationIndexImageFilter<TInputImage,TOutputImage,TFunction> -::GenerateOutputInformation() -{ - // do not call the superclass' implementation of this method since - // this filter allows the input the output to be of different dimensions - - // get pointers to the input and output - typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); - typename Superclass::InputImageConstPointer inputPtr = this->GetInput(); - - if ( !outputPtr || !inputPtr) - { - return; - } - - // Set the output image largest possible region. Use a RegionCopier - // so that the input and output images can be different dimensions. - OutputImageRegionType outputLargestPossibleRegion; - this->CallCopyInputRegionToOutputRegion(outputLargestPossibleRegion, - inputPtr->GetLargestPossibleRegion()); - outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion ); - - // Set the output spacing and origin - const itk::ImageBase<Superclass::InputImageDimension> *phyData; - - phyData - = dynamic_cast<const itk::ImageBase<Superclass::InputImageDimension>*>(this->GetInput()); - - if (phyData) - { - // Copy what we can from the image from spacing and origin of the input - // This logic needs to be augmented with logic that select which - // dimensions to copy - unsigned int i, j; - const typename InputImageType::SpacingType& - inputSpacing = inputPtr->GetSpacing(); - const typename InputImageType::PointType& - inputOrigin = inputPtr->GetOrigin(); - const typename InputImageType::DirectionType& - inputDirection = inputPtr->GetDirection(); - - typename OutputImageType::SpacingType outputSpacing; - typename OutputImageType::PointType outputOrigin; - typename OutputImageType::DirectionType outputDirection; - - // copy the input to the output and fill the rest of the - // output with zeros. - for (i=0; i < Superclass::InputImageDimension; ++i) - { - outputSpacing[i] = inputSpacing[i]; - outputOrigin[i] = inputOrigin[i]; - for (j=0; j < Superclass::OutputImageDimension; j++) - { - if (j < Superclass::InputImageDimension) - { - outputDirection[j][i] = inputDirection[j][i]; - } - else - { - outputDirection[j][i] = 0.0; - } - } - } - for (; i < Superclass::OutputImageDimension; ++i) - { - outputSpacing[i] = 1.0; - outputOrigin[i] = 0.0; - for (j=0; j < Superclass::OutputImageDimension; j++) - { - if (j == i) - { - outputDirection[j][i] = 1.0; - } - else - { - outputDirection[j][i] = 0.0; - } - } - } - - // set the spacing and origin - outputPtr->SetSpacing( outputSpacing ); - outputPtr->SetOrigin( outputOrigin ); - outputPtr->SetDirection( outputDirection ); - outputPtr->SetNumberOfComponentsPerPixel( // propagate vector length info - inputPtr->GetNumberOfComponentsPerPixel()); - } - else - { - // pointer could not be cast back down - itkExceptionMacro(<< "otb::MultiChannelRAndBAndNIRVegetationIndexImageFilter::GenerateOutputInformation " - << "cannot cast input to " - << typeid(itk::ImageBase<Superclass::InputImageDimension>*).name() ); - } -} - - -/** - * ThreadedGenerateData Performs the pixel-wise addition - */ -template <class TInputImage, class TOutputImage, class TFunction > -void -MultiChannelRAndBAndNIRVegetationIndexImageFilter<TInputImage,TOutputImage,TFunction> -::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, - int threadId) -{ - InputImagePointer inputPtr = this->GetInput(); - OutputImagePointer outputPtr = this->GetOutput(0); - - // Define the portion of the input to walk for this thread, using - // the CallCopyOutputRegionToInputRegion method allows for the input - // and output images to be different dimensions - InputImageRegionType inputRegionForThread; - this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread); - - // Define the iterators - itk::ImageRegionConstIterator<TInputImage> inputIt(inputPtr, inputRegionForThread); - itk::ImageRegionIterator<TOutputImage> outputIt(outputPtr, outputRegionForThread); - - itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); - - inputIt.GoToBegin(); - outputIt.GoToBegin(); - - while ( !inputIt.IsAtEnd() ) - { - outputIt.Set( m_Functor( inputIt.Get()[m_RedIndex-1],inputIt.Get()[m_BlueIndex-1], inputIt.Get()[m_NIRIndex-1] ) ); - ++inputIt; - ++outputIt; - progress.CompletedPixel(); // potential exception thrown here - } -} - -template <class TInputImage, class TOutputImage, class TFunction > -void -MultiChannelRAndBAndNIRVegetationIndexImageFilter<TInputImage,TOutputImage,TFunction> -::PrintSelf(std::ostream& os, itk::Indent indent) const -{ - this->Superclass::PrintSelf(os,indent); - os << indent << "Red index: "<<m_RedIndex<<std::endl; - os << indent << "Blue index: "<<m_BlueIndex<<std::endl; - os << indent << "NIR index: "<<m_NIRIndex<<std::endl; -} - -} // end namespace otb - -#endif diff --git a/Code/Radiometry/otbMultiChannelRAndNIRVegetationIndexImageFilter.h b/Code/Radiometry/otbMultiChannelRAndNIRVegetationIndexImageFilter.h index 0bdee3acbeee1bea2a20e7705c615ef825f65e87..a95d32261d59201b9d6b4382fa6f5ba03310f53a 100644 --- a/Code/Radiometry/otbMultiChannelRAndNIRVegetationIndexImageFilter.h +++ b/Code/Radiometry/otbMultiChannelRAndNIRVegetationIndexImageFilter.h @@ -18,7 +18,7 @@ #ifndef __otbMultiChannelRAndNIRVegetationIndexImageFilter_h #define __otbMultiChannelRAndNIRVegetationIndexImageFilter_h -#include "itkInPlaceImageFilter.h" +#include "itkUnaryFunctorImageFilter.h" #include "itkImageRegionIteratorWithIndex.h" #include "otbVegetationIndex.h" @@ -26,71 +26,37 @@ namespace otb { /** \class MultiChannelRAndNIRVegetationIndexImageFilter - * \brief Implements mutli channel R and NIR vegetation index operation, pixel-wise generic vegetation index operation on one vector image. + * \brief Implements mutli channel R and NIR pixel-wise generic vegetation index operation on one vector image. * * This class is parameterized over the type of the input image and * the type of the output image. It is also parameterized by the * operation to be applied, using a Functor style. - * + * + * \sa UnaryFunctorImageFilter */ template <class TInputImage, class TOutputImage, -class TFunction = Functor::NDVI< typename TInputImage::InternalPixelType, -typename TInputImage::InternalPixelType, -typename TOutputImage::PixelType> > -class ITK_EXPORT MultiChannelRAndNIRVegetationIndexImageFilter : public itk::InPlaceImageFilter<TInputImage,TOutputImage> + class TFunction = Functor::NDVI< typename TInputImage::InternalPixelType, + typename TInputImage::InternalPixelType, + typename TOutputImage::PixelType> > +class ITK_EXPORT MultiChannelRAndNIRVegetationIndexImageFilter + : public itk::UnaryFunctorImageFilter<TInputImage,TOutputImage, TFunction> { public: /** Standard class typedefs. */ - typedef MultiChannelRAndNIRVegetationIndexImageFilter Self; - typedef itk::InPlaceImageFilter<TInputImage,TOutputImage> Superclass; - typedef itk::SmartPointer<Self> Pointer; - typedef itk::SmartPointer<const Self> ConstPointer; + typedef MultiChannelRAndNIRVegetationIndexImageFilter Self; + typedef itk::UnaryFunctorImageFilter<TInputImage,TOutputImage, TFunction> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); /** Run-time type information (and related methods). */ - itkTypeMacro(MultiChannelRAndNIRVegetationIndexImageFilter, InPlaceImageFilter); + itkTypeMacro(MultiChannelRAndNIRVegetationIndexImageFilter, UnaryFunctorImageFilter); /** Some typedefs. */ typedef TFunction FunctorType; - typedef TInputImage InputImageType; - typedef typename InputImageType::ConstPointer InputImagePointer; - typedef typename InputImageType::RegionType InputImageRegionType; - typedef typename InputImageType::PixelType InputImagePixelType; - typedef TOutputImage OutputImageType; - typedef typename OutputImageType::Pointer OutputImagePointer; - typedef typename OutputImageType::RegionType OutputImageRegionType; - typedef typename OutputImageType::PixelType OutputImagePixelType; - - /** 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() - { - return m_Functor; - }; - 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) - { - if (m_Functor != functor) - { - m_Functor = functor; - this->Modified(); - } - } - + /** Set/Get the red channel index. Value must be in [1...[ */ itkSetMacro(RedIndex,unsigned int); itkGetMacro(RedIndex,unsigned int); @@ -99,49 +65,35 @@ public: itkGetMacro(NIRIndex,unsigned int); protected: - MultiChannelRAndNIRVegetationIndexImageFilter(); + /// Constructor + MultiChannelRAndNIRVegetationIndexImageFilter(): m_RedIndex(3), m_NIRIndex(4) {}; + /// Destructor virtual ~MultiChannelRAndNIRVegetationIndexImageFilter() {}; - - /** MultiChannelRAndNIRVegetationIndexImageFilter can produce an image which is a different - * resolution than its input image. As such, MultiChannelRAndNIRVegetationIndexImageFilter - * needs to provide an implementation for - * GenerateOutputInformation() in order to inform the pipeline - * execution model. The original documentation of this method is - * below. - * - * \sa ProcessObject::GenerateOutputInformaton() */ - virtual void GenerateOutputInformation(); - - /** MultiChannelRAndNIRVegetationIndexImageFilter 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, - int threadId ); - - void PrintSelf(std::ostream& os, itk::Indent indent) const; - + /// Before generating data, set functor parameters + virtual void BeforeThreadedGenerateData() + { + if(m_RedIndex < 1 || m_NIRIndex < 1) + { + itkExceptionMacro(<<"Channel indices must belong to range [1, ...["); + } + this->GetFunctor().SetRedIndex(m_RedIndex); + this->GetFunctor().SetNIRIndex(m_NIRIndex); + } + /// PrintSelf Method + void PrintSelf(std::ostream& os, itk::Indent indent) const + { + this->Superclass::PrintSelf(os,indent); + os << indent << "Red index: "<<m_RedIndex<<std::endl; + os << indent << "NIR index: "<<m_NIRIndex<<std::endl; + } private: MultiChannelRAndNIRVegetationIndexImageFilter(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented - /** Red channel index */ unsigned int m_RedIndex; /** NIR channel index */ unsigned int m_NIRIndex; - FunctorType m_Functor; }; - } // end namespace otb -#ifndef OTB_MANUAL_INSTANTIATION -#include "otbMultiChannelRAndNIRVegetationIndexImageFilter.txx" -#endif - #endif diff --git a/Code/Radiometry/otbMultiChannelRAndNIRVegetationIndexImageFilter.txx b/Code/Radiometry/otbMultiChannelRAndNIRVegetationIndexImageFilter.txx deleted file mode 100644 index 8d0695b5d7d6b2aed25e125b4ea53d27a1ea53bb..0000000000000000000000000000000000000000 --- a/Code/Radiometry/otbMultiChannelRAndNIRVegetationIndexImageFilter.txx +++ /dev/null @@ -1,197 +0,0 @@ -/*========================================================================= - - Program: ORFEO Toolbox - Language: C++ - Date: $Date$ - Version: $Revision$ - - - Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. - See OTBCopyright.txt for details. - - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#ifndef __otbMultiChannelRAndNIRVegetationIndexImageFilter_txx -#define __otbMultiChannelRAndNIRVegetationIndexImageFilter_txx - -#include "otbMultiChannelRAndNIRVegetationIndexImageFilter.h" -#include "itkImageRegionIterator.h" -#include "itkImageRegionConstIterator.h" -#include "itkProgressReporter.h" - -namespace otb -{ - -/** - * Constructor - */ -template <class TInputImage, class TOutputImage, class TFunction > -MultiChannelRAndNIRVegetationIndexImageFilter<TInputImage,TOutputImage,TFunction> -::MultiChannelRAndNIRVegetationIndexImageFilter() -{ - this->SetNumberOfRequiredInputs( 1 ); - this->InPlaceOff(); -} - -/** - * MultiChannelRAndNIRVegetationIndexImageFilter can produce an image which is a different resolution - * than its input image. As such, MultiChannelRAndNIRVegetationIndexImageFilter needs to provide an - * implementation for GenerateOutputInformation() in order to inform - * the pipeline execution model. The original documentation of this - * method is below. - * - * \sa ProcessObject::GenerateOutputInformaton() - */ -template <class TInputImage, class TOutputImage, class TFunction> -void -MultiChannelRAndNIRVegetationIndexImageFilter<TInputImage,TOutputImage,TFunction> -::GenerateOutputInformation() -{ - // do not call the superclass' implementation of this method since - // this filter allows the input the output to be of different dimensions - - // get pointers to the input and output - typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); - typename Superclass::InputImageConstPointer inputPtr = this->GetInput(); - - if ( !outputPtr || !inputPtr) - { - return; - } - - // Set the output image largest possible region. Use a RegionCopier - // so that the input and output images can be different dimensions. - OutputImageRegionType outputLargestPossibleRegion; - this->CallCopyInputRegionToOutputRegion(outputLargestPossibleRegion, - inputPtr->GetLargestPossibleRegion()); - outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion ); - - // Set the output spacing and origin - const itk::ImageBase<Superclass::InputImageDimension> *phyData; - - phyData - = dynamic_cast<const itk::ImageBase<Superclass::InputImageDimension>*>(this->GetInput()); - - if (phyData) - { - // Copy what we can from the image from spacing and origin of the input - // This logic needs to be augmented with logic that select which - // dimensions to copy - unsigned int i, j; - const typename InputImageType::SpacingType& - inputSpacing = inputPtr->GetSpacing(); - const typename InputImageType::PointType& - inputOrigin = inputPtr->GetOrigin(); - const typename InputImageType::DirectionType& - inputDirection = inputPtr->GetDirection(); - - typename OutputImageType::SpacingType outputSpacing; - typename OutputImageType::PointType outputOrigin; - typename OutputImageType::DirectionType outputDirection; - - // copy the input to the output and fill the rest of the - // output with zeros. - for (i=0; i < Superclass::InputImageDimension; ++i) - { - outputSpacing[i] = inputSpacing[i]; - outputOrigin[i] = inputOrigin[i]; - for (j=0; j < Superclass::OutputImageDimension; j++) - { - if (j < Superclass::InputImageDimension) - { - outputDirection[j][i] = inputDirection[j][i]; - } - else - { - outputDirection[j][i] = 0.0; - } - } - } - for (; i < Superclass::OutputImageDimension; ++i) - { - outputSpacing[i] = 1.0; - outputOrigin[i] = 0.0; - for (j=0; j < Superclass::OutputImageDimension; j++) - { - if (j == i) - { - outputDirection[j][i] = 1.0; - } - else - { - outputDirection[j][i] = 0.0; - } - } - } - - // set the spacing and origin - outputPtr->SetSpacing( outputSpacing ); - outputPtr->SetOrigin( outputOrigin ); - outputPtr->SetDirection( outputDirection ); - outputPtr->SetNumberOfComponentsPerPixel( // propagate vector length info - inputPtr->GetNumberOfComponentsPerPixel()); - } - else - { - // pointer could not be cast back down - itkExceptionMacro(<< "otb::MultiChannelRAndNIRVegetationIndexImageFilter::GenerateOutputInformation " - << "cannot cast input to " - << typeid(itk::ImageBase<Superclass::InputImageDimension>*).name() ); - } -} - - -/** - * ThreadedGenerateData Performs the pixel-wise addition - */ -template <class TInputImage, class TOutputImage, class TFunction > -void -MultiChannelRAndNIRVegetationIndexImageFilter<TInputImage,TOutputImage,TFunction> -::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, - int threadId) -{ - InputImagePointer inputPtr = this->GetInput(); - OutputImagePointer outputPtr = this->GetOutput(0); - - // Define the portion of the input to walk for this thread, using - // the CallCopyOutputRegionToInputRegion method allows for the input - // and output images to be different dimensions - InputImageRegionType inputRegionForThread; - this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread); - - // Define the iterators - itk::ImageRegionConstIterator<TInputImage> inputIt(inputPtr, inputRegionForThread); - itk::ImageRegionIterator<TOutputImage> outputIt(outputPtr, outputRegionForThread); - - itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); - - inputIt.GoToBegin(); - outputIt.GoToBegin(); - - while ( !inputIt.IsAtEnd() ) - { -// outputIt.Set( m_Functor( inputIt.Get() ) ); - outputIt.Set( m_Functor( inputIt.Get()[m_RedIndex-1], inputIt.Get()[m_NIRIndex-1] ) ); - ++inputIt; - ++outputIt; - progress.CompletedPixel(); // potential exception thrown here - } -} - -template <class TInputImage, class TOutputImage, class TFunction > -void -MultiChannelRAndNIRVegetationIndexImageFilter<TInputImage,TOutputImage,TFunction> -::PrintSelf(std::ostream& os, itk::Indent indent) const -{ - this->Superclass::PrintSelf(os,indent); - os << indent << "Red index: "<<m_RedIndex<<std::endl; - os << indent << "NIR index: "<<m_NIRIndex<<std::endl; -} - -} // end namespace otb - -#endif diff --git a/Code/Radiometry/otbVegetationIndex.h b/Code/Radiometry/otbVegetationIndex.h index ba2763e05680eac2a46fa74939c6a604112faee5..06ae70dde6eb0ab8ca4e2b2dd155b19c721ea780 100644 --- a/Code/Radiometry/otbVegetationIndex.h +++ b/Code/Radiometry/otbVegetationIndex.h @@ -19,11 +19,148 @@ #define __otbVegetationIndex_h #include "otbMath.h" +#include "itkVariableLengthVector.h" namespace otb { namespace Functor { +/** Base class for R And NIR based Index +* Implement operators for UnaryFunctorImageFilter templated with a +* VectorImage and BinaryFunctorImageFilter templated with single +* images. +* Subclasses should NOT overload operators, they must re-implement +* the Evaluate() method. +*/ +template<class TInput1, class TInput2, class TOutput> +class RAndNIRIndexBase +{ +public: + /// Vector pixel type used to support both vector images and multiple + /// input images + typedef itk::VariableLengthVector<TInput1> InputVectorType; + + // Operator on vector pixel type + inline TOutput operator()(const InputVectorType & inputVector) + { + return this->Evaluate(inputVector[m_RedIndex-1],static_cast<TInput2>(inputVector[m_NIRIndex-1])); + } + + // Binary operator + inline TOutput operator()(const TInput1 &r, const TInput2 &nir) + { + return this->Evaluate(r,nir); + }; + /// Constructor + RAndNIRIndexBase() : m_RedIndex(3), m_NIRIndex(4) {}; + /// Desctructor + ~RAndNIRIndexBase() {}; + + /// Set Red Index + void SetRedIndex(unsigned int channel) + { + m_RedIndex = channel; + } + /// Get Red Index + unsigned int GetRedIndex() + { + return m_RedIndex; + } + /// Set NIR Index + void SetNIRIndex(unsigned int channel) + { + m_NIRIndex = channel; + } + /// Get NIR Index + unsigned int GetNIRIndex() + { + return m_NIRIndex; + } +protected: + // This method must be reimplemented in subclasses to actually + // compute the index value + virtual TOutput Evaluate(const TInput1 & r, const TInput2 & nir) const = 0; + +private: + unsigned int m_RedIndex; + unsigned int m_NIRIndex; +}; + +/** base class for R, B And NIR based Index +* Implement operators for UnaryFunctorImageFilter templated with a +* VectorImage and BinaryFunctorImageFilter templated with single +* images. +* Subclasses should NOT overload operators, they must re-implement +* the Evaluate() method. +*/ +template<class TInput1, class TInput2, class TInput3, class TOutput> +class RBAndNIRIndexBase +{ +public: + /// Vector pixel type used to support both vector images and multiple + /// input images + typedef itk::VariableLengthVector<TInput1> InputVectorType; + + // Operator on vector pixel type + inline TOutput operator()(const InputVectorType & inputVector) + { + return this->Evaluate(inputVector[m_RedIndex-1],static_cast<TInput2>(inputVector[m_BlueIndex-1]), static_cast<TInput3>(inputVector[m_NIRIndex-1])); + } + + // Binary operator + inline TOutput operator()(const TInput1 &r, const TInput2 &b, const TInput2 &nir) + { + return this->Evaluate(r,b,nir); + }; + /// Constructor + RBAndNIRIndexBase() : m_RedIndex(3), m_BlueIndex(1), m_NIRIndex(4) {}; + /// Desctructor + ~RBAndNIRIndexBase() {}; + + /// Set Red Index + void SetRedIndex(unsigned int channel) + { + m_RedIndex = channel; + } + /// Get Red Index + unsigned int GetRedIndex() + { + return m_RedIndex; + } + /// Set Blue Index + void SetBlueIndex(unsigned int channel) + { + m_BlueIndex = channel; + } + /// Get Blue Index + unsigned int GetBlueIndex() + { + return m_BlueIndex; + } + + /// Set NIR Index + void SetNIRIndex(unsigned int channel) + { + m_NIRIndex = channel; + } + /// Get NIR Index + unsigned int GetNIRIndex() + { + return m_NIRIndex; + } +protected: + // This method must be reimplemented in subclasses to actually + // compute the index value + virtual TOutput Evaluate(const TInput1 & r, const TInput2& b, const TInput3 & nir) const = 0; + +private: + unsigned int m_RedIndex; + unsigned int m_BlueIndex; + unsigned int m_NIRIndex; +}; + + + /** \class NDVI * \brief This functor calculate the NormalizeD Vegetation Index (NDVI) * @@ -32,19 +169,23 @@ namespace Functor * \ingroup Functor */ template <class TInput1, class TInput2, class TOutput> -class NDVI +class NDVI : public RAndNIRIndexBase<TInput1,TInput2,TOutput> { public: + /// Constructor NDVI() {}; + /// Desctructor ~NDVI() {}; - inline TOutput operator()(const TInput1 &r, const TInput2 &nir) + // Operator on r and nir single pixel values +protected: + inline TOutput Evaluate(const TInput1 &r, const TInput2 &nir) const { double dr = static_cast<double>(r); double dnir = static_cast<double>(nir); if ( (nir + r) == 0 ) - { + { return static_cast<TOutput>(0.); - } + } return ( static_cast<TOutput>((dnir-dr)/(dnir+dr))); } @@ -58,19 +199,20 @@ public: * \ingroup Functor */ template <class TInput1, class TInput2, class TOutput> -class RVI +class RVI : public RAndNIRIndexBase<TInput1, TInput2, TOutput> { public: RVI() {}; ~RVI() {}; - inline TOutput operator()(const TInput1 &r, const TInput2 &nir) +protected: + inline TOutput Evaluate(const TInput1 &r, const TInput2 &nir) const { double dr = static_cast<double>(r); double dnir = static_cast<double>(nir); if ( r == 0 ) - { + { return static_cast<TOutput>(0.); - } + } return ( static_cast<TOutput>(dnir/dr)); } }; @@ -82,17 +224,11 @@ public: * \ingroup Functor2 */ template <class TInput1, class TInput2, class TOutput> -class PVI +class PVI : public RAndNIRIndexBase<TInput1, TInput2, TOutput> { public: PVI() {}; ~PVI() {}; - inline TOutput operator()(const TInput1 &r, const TInput2 &nir) - { - double dnir = static_cast<double>(nir); - double dr = static_cast<double>(r); - return ( static_cast<TOutput>( (dnir - m_A*dr - m_B)*m_Coeff) ); - } /** Set/Get A and B parameters */ void SetA(const double A) { @@ -111,7 +247,14 @@ public: { return ( m_B ); } - +protected: + inline TOutput Evaluate(const TInput1 &r, const TInput2 &nir) const + { + double dnir = static_cast<double>(nir); + double dr = static_cast<double>(r); + return ( static_cast<TOutput>( (dnir - m_A*dr - m_B)*m_Coeff) ); + } + private: /** A and B parameters */ @@ -131,22 +274,12 @@ private: * \ingroup Functor */ template <class TInput1, class TInput2, class TOutput> -class SAVI +class SAVI : public RAndNIRIndexBase<TInput1, TInput2, TOutput> { public: SAVI() : m_L(0.5) {}; ~SAVI() {}; - inline TOutput operator()(const TInput1 &r, const TInput2 &nir) - { - double dnir = static_cast<double>(nir); - double dr = static_cast<double>(r); - double denominator = dnir + dr + m_L; - if ( denominator == 0. ) - { - return static_cast<TOutput>(0.); - } - return ( static_cast<TOutput>( ((dnir-dr)*(1+m_L))/denominator ) ); - } + /** Set/Get L correction */ void SetL(const double L) { @@ -157,6 +290,19 @@ public: return ( m_L ); } +protected: + inline TOutput Evaluate(const TInput1 &r, const TInput2 &nir) const + { + double dnir = static_cast<double>(nir); + double dr = static_cast<double>(r); + double denominator = dnir + dr + m_L; + if ( denominator == 0. ) + { + return static_cast<TOutput>(0.); + } + return ( static_cast<TOutput>( ((dnir-dr)*(1+m_L))/denominator ) ); + } + private: /** L correction */ @@ -171,22 +317,12 @@ private: * \ingroup Functor */ template <class TInput1, class TInput2, class TOutput> -class TSAVI +class TSAVI : public RAndNIRIndexBase<TInput1, TInput2, TOutput> { public: TSAVI() : m_X(0.08) {}; ~TSAVI() {}; - inline TOutput operator()(const TInput1 &r, const TInput2 &nir) - { - double dnir = static_cast<double>(nir); - double dr = static_cast<double>(r); - double denominator = m_A*dnir + dr + m_X*(1.+m_A*m_A); - if ( denominator == 0. ) - { - return static_cast<TOutput>(0.); - } - return ( static_cast<TOutput>( (m_A*(dnir - m_A*dr - m_B))/denominator ) ); - } + /** Set/Get A and B parameters */ void SetA(const double A) { @@ -214,6 +350,19 @@ public: return (m_X); } +protected: + inline TOutput Evaluate(const TInput1 &r, const TInput2 &nir) const + { + double dnir = static_cast<double>(nir); + double dr = static_cast<double>(r); + double denominator = m_A*dnir + dr + m_X*(1.+m_A*m_A); + if ( denominator == 0. ) + { + return static_cast<TOutput>(0.); + } + return ( static_cast<TOutput>( (m_A*(dnir - m_A*dr - m_B))/denominator ) ); + } + private: /** A and B parameters */ @@ -232,20 +381,22 @@ private: * \ingroup Functor */ template <class TInput1, class TInput2, class TOutput> -class MSAVI +class MSAVI : public RAndNIRIndexBase<TInput1, TInput2, TOutput> { public: MSAVI() {}; ~MSAVI() {}; - inline TOutput operator()(const TInput1 &r, const TInput2 &nir) + +protected: + inline TOutput Evaluate(const TInput1 &r, const TInput2 &nir) const { double dnir = static_cast<double>(nir); double dr = static_cast<double>(r); double sqrt_value = (2*dnir+1)*(2*dnir+1) - 8*(dnir-dr); if ( sqrt_value < 0. ) - { + { return static_cast<TOutput>(0.); - } + } return ( static_cast<TOutput>( (2*dnir + 1 - vcl_sqrt(sqrt_value))/2. ) ); } @@ -256,17 +407,29 @@ public: * * This vegetation index use three inputs channels * - * [Yoram J. Kaufman and Didier Tanr�, 1992] + * [Yoram J. Kaufman and Didier Tanre, 1992] * * \ingroup Functor */ template <class TInput1, class TInput2, class TInput3, class TOutput> -class ARVI +class ARVI : public RBAndNIRIndexBase<TInput1,TInput2,TInput3,TOutput> { public: ARVI() : m_Gamma(0.5) {}; ~ARVI() {}; - inline TOutput operator()(const TInput1 &r, const TInput2 &b, const TInput3 &nir) + + /** Set/Get Gamma parameter */ + void SetGamma(const double gamma) + { + m_Gamma = gamma; + } + double GetGamma(void)const + { + return (m_Gamma); + } + +protected: + inline TOutput Evaluate(const TInput1 &r, const TInput2 &b, const TInput3 &nir) const { double dr = static_cast<double>(r); double db = static_cast<double>(b); @@ -274,20 +437,11 @@ public: double RHOrb = dr - m_Gamma*(db - dr); double denominator = dnir + RHOrb; if ( denominator == 0. ) - { + { return static_cast<TOutput>(0.); - } + } return ( static_cast<TOutput>( (dnir - RHOrb)/denominator ) ); } - /** Set/Get Gamma parameter */ - void SetGamma(const double gamma) - { - m_Gamma = gamma; - } - double GetGamma(void)const - { - return (m_Gamma); - } private: @@ -305,25 +459,12 @@ private: * \ingroup Functor */ template <class TInput1, class TInput2, class TInput3, class TOutput> -class EVI +class EVI : public RBAndNIRIndexBase<TInput1,TInput2,TInput3,TOutput> { public: EVI() : m_G(2.5), m_C1(6.0), m_C2(7.5), m_L(1.0) {}; ~EVI() {}; - inline TOutput operator()(const TInput1 &r, const TInput2 &b, const TInput3 &nir) - { - double dr = static_cast<double>(r); - double db = static_cast<double>(b); - double dnir = static_cast<double>(nir); - double denominator = dnir + m_C1*dr - m_C2*db + m_L; - if ( denominator == 0. ) - { - return static_cast<TOutput>(0.); - } - return ( static_cast<TOutput>( m_G * (dnir - dr)/denominator ) ); -//return ( static_cast<TOutput>( dnir ) ); - } - /** Set/Get G parameter */ +/** Set/Get G parameter */ void SetG(const double g) { m_G = g; @@ -359,7 +500,20 @@ public: { return (m_L); } - +protected: + inline TOutput Evaluate(const TInput1 &r, const TInput2 &b, const TInput3 &nir) const + { + double dr = static_cast<double>(r); + double db = static_cast<double>(b); + double dnir = static_cast<double>(nir); + double denominator = dnir + m_C1*dr - m_C2*db + m_L; + if ( denominator == 0. ) + { + return static_cast<TOutput>(0.); + } + return ( static_cast<TOutput>( m_G * (dnir - dr)/denominator ) ); + } + private: /** Gain factor */ diff --git a/Code/SpatialReasoning/otbPolygonListToRCC8GraphFilter.txx b/Code/SpatialReasoning/otbPolygonListToRCC8GraphFilter.txx index df6876db6fdd863837cad3d2ce62c92d97d89ecc..45d96e97bef2f9596ef24d34e6f97a72b3224002 100644 --- a/Code/SpatialReasoning/otbPolygonListToRCC8GraphFilter.txx +++ b/Code/SpatialReasoning/otbPolygonListToRCC8GraphFilter.txx @@ -341,7 +341,18 @@ PolygonListToRCC8GraphFilter<TPolygonList, TOutputGraph> { // Add the edge to the graph. otbMsgDevMacro(<<"Adding edge: "<<vIt1.GetIndex()<<" -> "<<vIt2.GetIndex()<<": "<<value); - m_EdgesPerThread[threadId][EdgePairType(vIt1.GetIndex(),vIt2.GetIndex())]=value; + if(value==OTB_RCC8_NTPPI) + { + m_EdgesPerThread[threadId][EdgePairType(vIt2.GetIndex(),vIt1.GetIndex())]=OTB_RCC8_NTPP; + } + else if(value == OTB_RCC8_TPPI) + { + m_EdgesPerThread[threadId][EdgePairType(vIt2.GetIndex(),vIt1.GetIndex())]=OTB_RCC8_TPP; + } + else + { + m_EdgesPerThread[threadId][EdgePairType(vIt1.GetIndex(),vIt2.GetIndex())]=value; + } if (m_UseInverted) { m_EdgesPerThread[threadId][EdgePairType(vIt2.GetIndex(),vIt1.GetIndex())]=invert[value];