diff --git a/Code/FeatureExtraction/otbRadiometricMomentsImageFilter.h b/Code/FeatureExtraction/otbRadiometricMomentsImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..fe591e87f90d5cdb37e2dd4d83fb9db4fb62be7e --- /dev/null +++ b/Code/FeatureExtraction/otbRadiometricMomentsImageFilter.h @@ -0,0 +1,109 @@ +/*========================================================================= + + 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 __otbRadiometricMomentsImageFilter_h +#define __otbRadiometricMomentsImageFilter_h + +#include "itkImageToImageFilter.h" +#include "otbRadiometricMomentsFunctor.h" +#include "itkConstNeighborhoodIterator.h" + +namespace otb +{ + +/** + * \class RadiometricMomentsImageFilter + * \brief Calculate the radiometric moments. + * + * Calculate the radiometric moments over a specified neighborhood + * + * This class is templated over the input image and the output image. + * + * \ingroup ImageFilters + */ + + +template <class TInputImage, class TOutputImage> +class ITK_EXPORT RadiometricMomentsImageFilter : + public itk::ImageToImageFilter<TInputImage, TOutputImage> +{ +public: + /** Standard class typedefs. */ + typedef RadiometricMomentsImageFilter Self; + typedef itk::ImageToImageFilter<TInputImage,TOutputImage> 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(RadiometricMomentsImageFilter, ImageToImageFilter); + + /** Some convenient typedefs. */ + typedef typename Superclass::InputImageType InputImageType; + typedef typename InputImageType::ConstPointer InputImagePointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename InputImageType::SizeType InputImageSizeType; + typedef typename Superclass::OutputImageType OutputImageType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + typedef typename OutputImageType::InternalPixelType ScalarType; + + typedef Functor::RadiometricMomentsFunctor< itk::ConstNeighborhoodIterator<InputImageType>, ScalarType> + FunctorType; + + typedef itk::ProcessObject ProcessObjectType; + + /**Set/Get the radius of neighborhood.*/ + itkSetMacro(Radius, InputImageSizeType); + itkGetMacro(Radius, InputImageSizeType); + + /** Set unsinged int radius */ + void SetRadius(unsigned int radius) + { + m_Radius.Fill(radius); + } + + typedef itk::ConstNeighborhoodIterator<TInputImage> NeighborhoodIteratorType; + typedef typename NeighborhoodIteratorType::RadiusType RadiusType; + typedef unsigned char RadiusSizeType; + +protected: + RadiometricMomentsImageFilter(); + virtual ~RadiometricMomentsImageFilter() {} + virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId); + virtual void GenerateInputRequestedRegion(void); + virtual void GenerateOutputInformation(void); + +private: + RadiometricMomentsImageFilter(const Self &); //purposely not implemented + void operator =(const Self&); //purposely not implemented + + InputImageSizeType m_Radius; + FunctorType m_Functor; +}; + +} // namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbRadiometricMomentsImageFilter.txx" +#endif + +#endif diff --git a/Code/FeatureExtraction/otbRadiometricMomentsImageFilter.txx b/Code/FeatureExtraction/otbRadiometricMomentsImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..677fb0b56409f56a66ec7d0539e9c797e764bfe8 --- /dev/null +++ b/Code/FeatureExtraction/otbRadiometricMomentsImageFilter.txx @@ -0,0 +1,163 @@ +/*========================================================================= + + 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 __otbRadiometricMomentsImageFilter_txx +#define __otbRadiometricMomentsImageFilter_txx + +#include "otbRadiometricMomentsImageFilter.h" +#include "itkImageRegionIterator.h" +#include "itkConstNeighborhoodIterator.h" +#include "itkNeighborhoodAlgorithm.h" +#include "itkProgressReporter.h" +#include "itkZeroFluxNeumannBoundaryCondition.h" +#include "itkNeighborhoodAlgorithm.h" + +namespace otb +{ +/** + * Constructor + */ +template <class TInputImage, class TOutputImage> +RadiometricMomentsImageFilter<TInputImage, TOutputImage> +::RadiometricMomentsImageFilter() +{ + this->SetNumberOfRequiredInputs(1); + m_Radius.Fill(1); +} + +template <class TInputImage, class TOutputImage> +void +RadiometricMomentsImageFilter<TInputImage, TOutputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the input and output + typename Superclass::InputImagePointer inputPtr = + const_cast<TInputImage *>(this->GetInput()); + typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); + + if (!inputPtr || !outputPtr) + { + return; + } + // get a copy of the input requested region (should equal the output + // requested region) + typename TInputImage::RegionType inputRequestedRegion; + inputRequestedRegion = inputPtr->GetRequestedRegion(); + + // pad the input requested region by the operator radius + inputRequestedRegion.PadByRadius(m_Radius); + + // crop the input requested region at the input's largest possible region + if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion())) + { + inputPtr->SetRequestedRegion(inputRequestedRegion); + return; + } + else + { + // Couldn't crop the region (requested region is outside the largest + // possible region). Throw an exception. + + // store what we tried to request (prior to trying to crop) + inputPtr->SetRequestedRegion(inputRequestedRegion); + + // build an exception + itk::InvalidRequestedRegionError e(__FILE__, __LINE__); + std::ostringstream msg; + msg << this->GetNameOfClass() + << "::GenerateInputRequestedRegion()"; + e.SetLocation(msg.str().c_str()); + e.SetDescription("Requested region is (at least partially) outside the largest possible region."); + e.SetDataObject(inputPtr); + throw e; + } +} + +/** + * Generate the output information + */ +template <class TInputImage, class TOutputImage> +void +RadiometricMomentsImageFilter<TInputImage, TOutputImage> +::GenerateOutputInformation(void) +{ + Superclass::GenerateOutputInformation(); + this->GetOutput()->SetNumberOfComponentsPerPixel(4); +} +/** + * ThreadedGenerateData Performs the neighborhood-wise operation + */ +template <class TInputImage, class TOutputImage> +void +RadiometricMomentsImageFilter<TInputImage, TOutputImage> +::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId) +{ + itk::ZeroFluxNeumannBoundaryCondition<TInputImage> nbc; + +// We use dynamic_cast since inputs are stored as DataObjects. The +// ImageToImageFilter::GetInput(int) always returns a pointer to a +// TInputImage so it cannot be used for the second input. + InputImagePointer inputPtr + = dynamic_cast<const TInputImage*>(ProcessObjectType::GetInput(0)); + OutputImagePointer outputPtr = this->GetOutput(0); + + RadiusType r; + + r[0] = m_Radius[0]; + r[1] = m_Radius[1]; + + NeighborhoodIteratorType neighInputIt; + + itk::ImageRegionIterator<TOutputImage> outputIt; + + // Find the data-set boundary "faces" + typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage>::FaceListType faceList; + typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage> bC; + faceList = bC(inputPtr, outputRegionForThread, r); + + typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage>::FaceListType::iterator fit; + + // support progress methods/callbacks + itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); + + // Process each of the boundary faces. These are N-d regions which border + // the edge of the buffer. + for (fit = faceList.begin(); fit != faceList.end(); ++fit) + { + neighInputIt = itk::ConstNeighborhoodIterator<TInputImage>(r, inputPtr, *fit); + + outputIt = itk::ImageRegionIterator<TOutputImage>(outputPtr, *fit); + neighInputIt.OverrideBoundaryCondition(&nbc); + neighInputIt.GoToBegin(); + + while (!outputIt.IsAtEnd()) + { + outputIt.Set(m_Functor(neighInputIt)); + + ++neighInputIt; + ++outputIt; + progress.CompletedPixel(); + } + } +} + +} // end namespace otb + +#endif