From 90d4151db8197442a7263a5321bfabde65c96d4e Mon Sep 17 00:00:00 2001 From: Julien Michel <julien.michel@c-s.fr> Date: Thu, 17 Jan 2008 16:43:43 +0000 Subject: [PATCH] =?UTF-8?q?Classification=20multi=C3=A9chelle=20des=20stru?= =?UTF-8?q?ctures=20convexes=20et=20concaves=20de=20l'image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../otbQuaternaryFunctorImageFilter.h | 171 ++++++++++++ .../otbQuaternaryFunctorImageFilter.txx | 178 +++++++++++++ ...ScaleConvexOrConcaveClassificationFilter.h | 246 ++++++++++++++++++ Testing/Code/MultiScale/CMakeLists.txt | 25 ++ ...aleConvexOrConcaveClassificationFilter.cxx | 111 ++++++++ ...ConvexOrConcaveClassificationFilterNew.cxx | 40 +++ .../Code/MultiScale/otbMultiScaleTests3.cxx | 2 + ...ativeToMultiScaleCharacteristicsFilter.cxx | 2 +- 8 files changed, 774 insertions(+), 1 deletion(-) create mode 100755 Code/BasicFilters/otbQuaternaryFunctorImageFilter.h create mode 100755 Code/BasicFilters/otbQuaternaryFunctorImageFilter.txx create mode 100644 Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilter.h create mode 100644 Testing/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilter.cxx create mode 100644 Testing/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilterNew.cxx diff --git a/Code/BasicFilters/otbQuaternaryFunctorImageFilter.h b/Code/BasicFilters/otbQuaternaryFunctorImageFilter.h new file mode 100755 index 0000000000..6d9a140b0a --- /dev/null +++ b/Code/BasicFilters/otbQuaternaryFunctorImageFilter.h @@ -0,0 +1,171 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.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 __itkQuaternaryFunctorImageFilter_h +#define __itkQuaternaryFunctorImageFilter_h + +#include "itkInPlaceImageFilter.h" +#include "itkImageRegionIteratorWithIndex.h" + +namespace otb +{ + +/** \class QuaternaryFunctorImageFilter + * \brief Implements pixel-wise generic operation of four images. + * + * This class is parameterized over the types of the four input images + * and the type of the output image. It is also parameterized by the + * operation to be applied, using a Functor style. + * + * \sa TernaryFunctorImageFilter,BinaryFunctorImageFilter UnaryFunctorImageFilter + * + * \ingroup IntensityImageFilters Multithreaded + */ +template <class TInputImage1, class TInputImage2, + class TInputImage3, class TInputImage4, + class TOutputImage, class TFunction > +class ITK_EXPORT QuaternaryFunctorImageFilter : + public itk::InPlaceImageFilter<TInputImage1,TOutputImage> +{ +public: + /** Standard class typedefs. */ + typedef QuaternaryFunctorImageFilter Self; + typedef itk::InPlaceImageFilter<TInputImage1,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(QuaternaryFunctorImageFilter, InPlaceImageFilter); + + /** Some typedefs. */ + typedef TFunction FunctorType; + typedef TInputImage1 Input1ImageType; + typedef typename Input1ImageType::ConstPointer Input1ImagePointer; + typedef typename Input1ImageType::RegionType Input1ImageRegionType; + typedef typename Input1ImageType::PixelType Input1ImagePixelType; + typedef TInputImage2 Input2ImageType; + typedef typename Input2ImageType::ConstPointer Input2ImagePointer; + typedef typename Input2ImageType::RegionType Input2ImageRegionType; + typedef typename Input2ImageType::PixelType Input2ImagePixelType; + typedef TInputImage3 Input3ImageType; + typedef typename Input3ImageType::ConstPointer Input3ImagePointer; + typedef typename Input3ImageType::RegionType Input3ImageRegionType; + typedef typename Input3ImageType::PixelType Input3ImagePixelType; + typedef TInputImage4 Input4ImageType; + typedef typename Input4ImageType::ConstPointer Input4ImagePointer; + typedef typename Input4ImageType::RegionType Input4ImageRegionType; + typedef typename Input4ImageType::PixelType Input4ImagePixelType; + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** Connect one of the operands for pixel-wise addition. */ + void SetInput1( const TInputImage1 *image1); + + /** Connect one of the operands for pixel-wise addition. */ + void SetInput2( const TInputImage2 *image2); + + /** Connect one of the operands for pixel-wise addition. */ + void SetInput3( const TInputImage3 *image3); + + /** Connect one of the operands for pixel-wise addition. */ + void SetInput4( const TInputImage4 *image4); + + /** 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(void) { 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) + { + if (! (functor == m_Functor) ) + { + m_Functor = functor; + this->Modified(); + } + } + + /** Image dimensions */ + itkStaticConstMacro(Input1ImageDimension, unsigned int, + TInputImage1::ImageDimension); + itkStaticConstMacro(Input2ImageDimension, unsigned int, + TInputImage2::ImageDimension); + itkStaticConstMacro(Input3ImageDimension, unsigned int, + TInputImage3::ImageDimension); + itkStaticConstMacro(Input4ImageDimension, unsigned int, + TInputImage4::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TOutputImage::ImageDimension); + +protected: + QuaternaryFunctorImageFilter(); + virtual ~QuaternaryFunctorImageFilter() {}; + + /** Validate the presence of all three inputs. If one or more inputs + * are missing, throw an exception. */ + void BeforeThreadedGenerateData(); + + /** QuaternaryFunctorImageFilter 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 ); + +private: + QuaternaryFunctorImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + FunctorType m_Functor; +}; + +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbQuaternaryFunctorImageFilter.txx" +#endif + +#endif diff --git a/Code/BasicFilters/otbQuaternaryFunctorImageFilter.txx b/Code/BasicFilters/otbQuaternaryFunctorImageFilter.txx new file mode 100755 index 0000000000..bfb0ac8414 --- /dev/null +++ b/Code/BasicFilters/otbQuaternaryFunctorImageFilter.txx @@ -0,0 +1,178 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.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 _otbQuaternaryFunctorImageFilter_txx +#define _otbQuaternaryFunctorImageFilter_txx + +#include "otbQuaternaryFunctorImageFilter.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIterator.h" +#include "itkProgressReporter.h" + +namespace otb +{ + +/** + * Constructor + */ +template < class TInputImage1, class TInputImage2,class TInputImage3, + class TInputImage4, class TOutputImage, class TFunction > +QuaternaryFunctorImageFilter<TInputImage1,TInputImage2,TInputImage3,TInputImage4,TOutputImage,TFunction> +::QuaternaryFunctorImageFilter() +{ + this->InPlaceOff(); +} + + +/** + * Connect one of the operands for pixel-wise addition + */ +template < class TInputImage1, class TInputImage2,class TInputImage3, + class TInputImage4, class TOutputImage, class TFunction > +void +QuaternaryFunctorImageFilter<TInputImage1,TInputImage2,TInputImage3,TInputImage4,TOutputImage,TFunction> +::SetInput1( const TInputImage1 *image1 ) +{ + // The ProcessObject is not const-correct so the const_cast is required here + SetNthInput( 0, const_cast<TInputImage1 *>( image1 ) ); +} + + +/** + * Connect one of the operands for pixel-wise addition + */ +template < class TInputImage1, class TInputImage2,class TInputImage3, + class TInputImage4, class TOutputImage, class TFunction > +void +QuaternaryFunctorImageFilter<TInputImage1,TInputImage2,TInputImage3,TInputImage4,TOutputImage,TFunction> +::SetInput2( const TInputImage2 *image2 ) +{ + // The ProcessObject is not const-correct so the const_cast is required here + SetNthInput( 1, const_cast<TInputImage2 *>( image2 ) ); +} + + + +/** + * Connect one of the operands for pixel-wise addition + */ +template < class TInputImage1, class TInputImage2,class TInputImage3, + class TInputImage4, class TOutputImage, class TFunction > +void +QuaternaryFunctorImageFilter<TInputImage1,TInputImage2,TInputImage3,TInputImage4,TOutputImage,TFunction> +::SetInput3( const TInputImage3 *image3 ) +{ + // The ProcessObject is not const-correct so the const_cast is required here + SetNthInput( 2, const_cast<TInputImage3 *>( image3 ) ); +} + + +/** + * Connect one of the operands for pixel-wise addition + */ +template < class TInputImage1, class TInputImage2,class TInputImage3, + class TInputImage4, class TOutputImage, class TFunction > +void +QuaternaryFunctorImageFilter<TInputImage1,TInputImage2,TInputImage3,TInputImage4,TOutputImage,TFunction> +::SetInput4( const TInputImage4 *image4 ) +{ + // The ProcessObject is not const-correct so the const_cast is required here + SetNthInput( 3, const_cast<TInputImage4 *>( image4 ) ); +} + +/** + * BeforeThreadedGenerateData function. Validate inputs + */ +template < class TInputImage1, class TInputImage2,class TInputImage3, + class TInputImage4, class TOutputImage, class TFunction > +void +QuaternaryFunctorImageFilter<TInputImage1,TInputImage2,TInputImage3,TInputImage4,TOutputImage,TFunction> +::BeforeThreadedGenerateData() +{ + Input1ImagePointer inputPtr1 + = dynamic_cast<const TInputImage1*>((itk::ProcessObject::GetInput(0))); + Input2ImagePointer inputPtr2 + = dynamic_cast<const TInputImage2*>((itk::ProcessObject::GetInput(1))); + Input3ImagePointer inputPtr3 + = dynamic_cast<const TInputImage3*>((itk::ProcessObject::GetInput(2))); + Input4ImagePointer inputPtr4 + = dynamic_cast<const TInputImage4*>((itk::ProcessObject::GetInput(4))); + if (inputPtr1.IsNull() || inputPtr2.IsNull() || inputPtr3.IsNull() ||inputPtr4.IsNull()) + { + itkExceptionMacro(<< "At least one input is missing." + << " Input1 is " << inputPtr1.GetPointer() << ", " + << " Input2 is " << inputPtr2.GetPointer() << ", " + << " Input3 is " << inputPtr3.GetPointer() << ", " + << " Input4 is " << inputPtr4.GetPointer()); + + } +} + +/** + * ThreadedGenerateData function. Performs the pixel-wise addition + */ +template < class TInputImage1, class TInputImage2,class TInputImage3, + class TInputImage4, class TOutputImage, class TFunction > +void +QuaternaryFunctorImageFilter<TInputImage1,TInputImage2,TInputImage3,TInputImage4,TOutputImage,TFunction> +::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, + int threadId) +{ + // We use dynamic_cast since inputs are stored as DataObjects. The + // ImageToImageFilter::GetInput(int) always returns a pointer to a + // TInputImage1 so it cannot be used for the second or third input. + Input1ImagePointer inputPtr1 + = dynamic_cast<const TInputImage1*>((itk::ProcessObject::GetInput(0))); + Input2ImagePointer inputPtr2 + = dynamic_cast<const TInputImage2*>((itk::ProcessObject::GetInput(1))); + Input3ImagePointer inputPtr3 + = dynamic_cast<const TInputImage3*>((itk::ProcessObject::GetInput(2))); + Input4ImagePointer inputPtr4 + = dynamic_cast<const TInputImage4*>((itk::ProcessObject::GetInput(3))); + OutputImagePointer outputPtr = this->GetOutput(0); + + itk::ImageRegionConstIterator<TInputImage1> inputIt1(inputPtr1, outputRegionForThread); + itk::ImageRegionConstIterator<TInputImage2> inputIt2(inputPtr2, outputRegionForThread); + itk::ImageRegionConstIterator<TInputImage3> inputIt3(inputPtr3, outputRegionForThread); + itk::ImageRegionConstIterator<TInputImage4> inputIt4(inputPtr4, outputRegionForThread); + itk::ImageRegionIterator<TOutputImage> outputIt(outputPtr, outputRegionForThread); + + itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); + + inputIt1.GoToBegin(); + inputIt2.GoToBegin(); + inputIt3.GoToBegin(); + outputIt.GoToBegin(); + + + while( !inputIt1.IsAtEnd() ) + { + outputIt.Set( m_Functor(inputIt1.Get(), inputIt2.Get(), inputIt3.Get(), inputIt4.Get()) ); + ++inputIt1; + ++inputIt2; + ++inputIt3; + ++inputIt4; + ++outputIt; + progress.CompletedPixel(); // potential exception thrown here + } +} +} // end namespace otb + +#endif diff --git a/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilter.h b/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilter.h new file mode 100644 index 0000000000..455b74e94f --- /dev/null +++ b/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilter.h @@ -0,0 +1,246 @@ +/*========================================================================= + +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 _otbConvexOrConcaveClassificationFilter_h +#define _otbConvexOrConcaveClassificationFilter_h + +#include "otbQuaternaryFunctorImageFilter.h" +namespace otb +{ +namespace Functor + { + /** \class MultiScaleConvexOrConcaveDecisionRule + * \brief This Functor apply a classification rule on two membership value along with two labels. + * + * \par + * This algorithm is based on the following publication: + * \par + * Martino Pesaresi and Jon Alti Benediktsson, Member, IEEE: + * A new approach for the morphological segmentation of high resolution + * satellite imagery. IEEE Transactions on geoscience and remote sensing, vol. 39, + * NO. 2, February 2001, p. 309-320. + * \par + * + * Given \f$x_1\f$ and \f$x_2\f$ two membership values, \f$L_1,L_2\f$ two labels associated, + * and \f$\sigma\f$ a tolerance value, the following decision rule is applied: + * + * \f[ + * L=\left{\begin{array}{lcl} + * L_{1} &:& x_{1}>x_{2} and x_{1}>\sigma\\ + * L_{2} &:& x_{2}>x_{1} and x_{2}>\sigma\\ + * 0 &:& otherwise. + * \end{array}\right. + * \f] + * + * To help the distinction between \f$L_{1}\f$ labels and \f$L_{2}\f$, + * this functor adds the m_LabelSeparators value to the \f$L_{1}\f$ labels. + * + * This functor is the decision rule used for multi-scale classification using + * morphological profiles. + */ + template<class TInput,class TLabeled> + class MultiScaleConvexOrConcaveDecisionRule + { + + public: + /** + * Constructor + */ + MultiScaleConvexOrConcaveDecisionRule() + { + m_Sigma = 0.0; + m_LabelSeparator = 10; + } + /** + * Destructor + */ + ~MultiScaleConvexOrConcaveDecisionRule(){}; + /** + * Label the pixel to convex, concave or flat + * \return The label of the pixel + * \param x The image value + * \param xlevel The leveling value + */ + inline TLabeled operator()(const TInput& opDeMax, const TInput& cloDeMax,const TLabeled& opDeChar, const TLabeled& cloDeChar) + { + TLabeled resp = 0; + + if( opDeMax>cloDeMax && static_cast<double>(opDeMax)>m_Sigma) + { + resp = m_LabelSeparator + opDeChar; + } + else if (cloDeMax>opDeMax && static_cast<double>(cloDeMax)>m_Sigma) + { + resp = cloDeChar; + } + return resp; + } + /** + * Set the tolerance value + * \param sigma the tolerance value + */ + void SetSigma(const double & sigma) + { + m_Sigma = sigma; + } + /** + * Get the tolerance value + * \return the tolerance value + */ + double GetSigma(void) + { + return m_Sigma; + } + /** + * Set the label separator + * \param labelSpeparator the label separator + */ + void SetLabelSeparator(const TLabeled& labelSeparator) + { + m_LabelSeparator = labelSeparator; + } + /** + * Get the label separator + * \return the label separator + */ + TLabeled GetLabelSeparator(void) + { + return m_LabelSeparator; + } + + private: + /** Sigma (tolerance) parameter */ + double m_Sigma; + /** Seperate between convex and concave labels */ + TLabeled m_LabelSeparator; + + }; + } //end namespace Functor + +/** \class MultiScaleConvexOrConcaveClassificationFilter + * \brief Apply the MultiScaleConvexOrConcaveDecisionRule to whole images. + * + * See MultiScaleConvexOrConcaveDecisionRule functor documentation for more details. + * + */ +template <class TInputImage, class TOutputImage> +class ITK_EXPORT MultiScaleConvexOrConcaveClassificationFilter + : public QuaternaryFunctorImageFilter<TInputImage,TInputImage, TOutputImage,TOutputImage,TOutputImage, + Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType, + typename TOutputImage::PixelType> > +{ + public: + /** Standard typedefs */ + typedef MultiScaleConvexOrConcaveClassificationFilter Self; + typedef QuaternaryFunctorImageFilter<TInputImage,TInputImage, TOutputImage,TOutputImage,TOutputImage, + Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType, + typename TOutputImage::PixelType> >Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Type macro */ + itkNewMacro(Self); + + /** Creation through object factory macro */ + itkTypeMacro(MultiScaleConvexOrConcaveClassificationFilter,QuaternaryFunctorImageFilter); + + /** Template class typedef */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::PixelType LabelType; + typedef Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType, + typename TOutputImage::PixelType> DecisionFunctorType; + /** + * Set the opening profile derivative maxima image + * \param derivativeMaxima the opening profile derivative maxima image + * + */ + void SetOpeningProfileDerivativeMaxima(const TInputImage * derivativeMaxima) + { + this->SetInput1(derivativeMaxima); + } + /** + * Set the opening profile characteristics image + * \param characteristics the opening profile characteristics image + * + */ + void SetOpeningProfileCharacteristics(const TOutputImage * characteristics) + { + this->SetInput3(characteristics); + } + /** + * Set the closing profile derivative maxima image + * \param derivativeMaxima the closing profile derivative maxima image + * + */ + void SetClosingProfileDerivativeMaxima(const TInputImage * derivativeMaxima) + { + this->SetInput2(derivativeMaxima); + } + /** + * Set the closing profile characteristics image + * \param characteristics the closing profile characteristics image + * + */ + void SetClosingProfileCharacteristics(const TOutputImage * characteristics) + { + this->SetInput4(characteristics); + } + + /** Set/Get the tolerance value */ + itkSetMacro(Sigma,double); + itkGetMacro(Sigma,double); + /** Set/Get the label separator */ + itkSetMacro(LabelSeparator,LabelType); + itkGetMacro(LabelSeparator,LabelType); + + + /** Set the functor parameters before calling the ThreadedGenerateData() */ + virtual void BeforeThreadedGenerateData(void) + { + this->GetFunctor().SetLabelSeparator(m_LabelSeparator); + this->GetFunctor().SetSigma(m_Sigma); + } + +protected: + /** Constructor */ + MultiScaleConvexOrConcaveClassificationFilter() + { + m_LabelSeparator = 10; + m_Sigma = 0.0; + }; + /** Destructor */ + virtual ~MultiScaleConvexOrConcaveClassificationFilter() {}; + /**PrintSelf method */ + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const + { + Superclass::PrintSelf(os,indent); + os<<indent<<"LabelSeparator: "<<m_LabelSeparator<<std::endl; + os<<indent<<"Sigma: "<<m_Sigma<<std::endl; + } + +private: + MultiScaleConvexOrConcaveClassificationFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + /** Label separator between convex and concave labels */ + LabelType m_LabelSeparator; + /** Tolerance value */ + double m_Sigma; +}; +}// End namespace otb +#endif diff --git a/Testing/Code/MultiScale/CMakeLists.txt b/Testing/Code/MultiScale/CMakeLists.txt index a7f02d0432..427fa4e15e 100644 --- a/Testing/Code/MultiScale/CMakeLists.txt +++ b/Testing/Code/MultiScale/CMakeLists.txt @@ -264,6 +264,10 @@ ADD_TEST(msTvMorphologicalClosingProfileFilter ${MULTISCALE_TESTS2} 1 ) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ otbMULTISCALE_TESTS3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # ------- otb::ProfileToProfileDerivativeFilter ---------- ADD_TEST(msTuProfileToProfileDerivativeFilterNew ${MULTISCALE_TESTS3} @@ -307,6 +311,24 @@ ADD_TEST(msTvProfileDerivativeToMultiScaleCharacteristicsFilter ${MULTISCALE_TES 1 1 ) +# ------- otb::MultiScaleConvexOrConcaveClassificationFilter ---------- + +ADD_TEST(msTuMultiScaleConvexOrConcaveClassificationFilterNew ${MULTISCALE_TESTS3} + otbMultiScaleConvexOrConcaveClassificationFilterNew) + +ADD_TEST(msTvMultiScaleConvexOrConcaveClassificationFilter ${MULTISCALE_TESTS3} + --compare-image ${TOL} + ${BASELINE}/msMultiScaleConvexOrConcaveClassificationFilterOutput.tif + ${TEMP}/msMultiScaleConvexOrConcaveClassificationFilterOutput.tif + otbMultiScaleConvexOrConcaveClassificationFilter + ${INPUTDATA}/ROI_IKO_PAN_LesHalles.tif + ${TEMP}/msMultiScaleConvexOrConcaveClassificationFilterOutput.tif + 5 + 1 + 1 + 1. +) + # ------- Fichiers sources CXX ----------------------------------- SET(BasicMultiScale_SRCS1 @@ -340,6 +362,9 @@ otbProfileToProfileDerivativeFilterNew.cxx otbProfileToProfileDerivativeFilter.cxx otbProfileDerivativeToMultiScaleCharacteristicsFilterNew.cxx otbProfileDerivativeToMultiScaleCharacteristicsFilter.cxx +otbMultiScaleConvexOrConcaveClassificationFilterNew.cxx +otbMultiScaleConvexOrConcaveClassificationFilter.cxx + ) INCLUDE_DIRECTORIES("${OTBTesting_BINARY_DIR}") diff --git a/Testing/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilter.cxx b/Testing/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilter.cxx new file mode 100644 index 0000000000..9c363c045f --- /dev/null +++ b/Testing/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilter.cxx @@ -0,0 +1,111 @@ +/*========================================================================= + +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. + +=========================================================================*/ +#include "otbMorphologicalOpeningProfileFilter.h" +#include "otbMorphologicalClosingProfileFilter.h" +#include "otbProfileToProfileDerivativeFilter.h" +#include "otbProfileDerivativeToMultiScaleCharacteristicsFilter.h" +#include "otbMultiScaleConvexOrConcaveClassificationFilter.h" +#include "itkBinaryBallStructuringElement.h" +#include "otbImageFileReader.h" +#include "otbStreamingImageFileWriter.h" +#include "otbImage.h" + +#include "itkMacro.h" + +int otbMultiScaleConvexOrConcaveClassificationFilter(int argc, char * argv[]) +{ + const char * inputFilename = argv[1]; + const char * outputFilename = argv[2]; + const unsigned int profileSize = atoi(argv[3]); + const unsigned int initialValue = atoi(argv[4]); + const unsigned int step = atoi(argv[5]); + const double sigma = atof(argv[6]); + + + const unsigned int Dimension = 2; + typedef double InputPixelType; + typedef double OutputPixelType; + typedef unsigned short LabeledPixelType; + + typedef otb::Image<InputPixelType,Dimension> InputImageType; + typedef otb::Image<OutputPixelType,Dimension> OutputImageType; + typedef otb::Image<LabeledPixelType,2> LabeledImageType; + + typedef otb::ImageFileReader<InputImageType> ReaderType; + typedef otb::StreamingImageFileWriter<LabeledImageType> LabeledWriterType; + + typedef itk::BinaryBallStructuringElement<InputPixelType,Dimension> StructuringElementType; + typedef otb::MorphologicalOpeningProfileFilter<InputImageType,InputImageType,StructuringElementType> + OpeningProfileFilterType; + typedef otb::MorphologicalClosingProfileFilter<InputImageType,InputImageType,StructuringElementType> + ClosingProfileFilterType; + typedef otb::ProfileToProfileDerivativeFilter<InputImageType,InputImageType> DerivativeFilterType; + typedef otb::ProfileDerivativeToMultiScaleCharacteristicsFilter<InputImageType,OutputImageType,LabeledImageType> + MultiScaleCharacteristicsFilterType; + typedef otb::MultiScaleConvexOrConcaveClassificationFilter<InputImageType,LabeledImageType> MultiScaleClassificationFilterType; + + + // Reading input image + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(inputFilename); + + // Instantiation + OpeningProfileFilterType::Pointer oprofileFilter = OpeningProfileFilterType::New(); + oprofileFilter->SetInput(reader->GetOutput()); + oprofileFilter->SetProfileSize(profileSize); + oprofileFilter->SetInitialValue(initialValue); + oprofileFilter->SetStep(step); + + ClosingProfileFilterType::Pointer cprofileFilter = ClosingProfileFilterType::New(); + cprofileFilter->SetInput(reader->GetOutput()); + cprofileFilter->SetProfileSize(profileSize); + cprofileFilter->SetInitialValue(initialValue); + cprofileFilter->SetStep(step); + + DerivativeFilterType::Pointer oderivativeFilter = DerivativeFilterType::New(); + oderivativeFilter->SetInput(oprofileFilter->GetOutput()); + + DerivativeFilterType::Pointer cderivativeFilter = DerivativeFilterType::New(); + cderivativeFilter->SetInput(cprofileFilter->GetOutput()); + + MultiScaleCharacteristicsFilterType::Pointer omsCharFilter = MultiScaleCharacteristicsFilterType::New(); + omsCharFilter->SetInput(oderivativeFilter->GetOutput()); + omsCharFilter->SetInitialValue(initialValue); + omsCharFilter->SetStep(step); + + MultiScaleCharacteristicsFilterType::Pointer cmsCharFilter = MultiScaleCharacteristicsFilterType::New(); + cmsCharFilter->SetInput(cderivativeFilter->GetOutput()); + cmsCharFilter->SetInitialValue(initialValue); + cmsCharFilter->SetStep(step); + + MultiScaleClassificationFilterType::Pointer classificationFilter = MultiScaleClassificationFilterType::New(); + classificationFilter->SetOpeningProfileDerivativeMaxima(omsCharFilter->GetOutput()); + classificationFilter->SetOpeningProfileCharacteristics(omsCharFilter->GetOutputCharacteristics()); + classificationFilter->SetClosingProfileDerivativeMaxima(cmsCharFilter->GetOutput()); + classificationFilter->SetClosingProfileCharacteristics(cmsCharFilter->GetOutputCharacteristics()); + classificationFilter->SetSigma(sigma); + classificationFilter->SetLabelSeparator(initialValue+profileSize*step); + + LabeledWriterType::Pointer labeledWriter = LabeledWriterType::New(); + + labeledWriter->SetFileName(outputFilename); + labeledWriter->SetInput(classificationFilter->GetOutput()); + labeledWriter->Update(); + + return EXIT_SUCCESS; +} diff --git a/Testing/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilterNew.cxx b/Testing/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilterNew.cxx new file mode 100644 index 0000000000..03447562ee --- /dev/null +++ b/Testing/Code/MultiScale/otbMultiScaleConvexOrConcaveClassificationFilterNew.cxx @@ -0,0 +1,40 @@ +/*========================================================================= + +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. + +=========================================================================*/ +#include "itkBinaryBallStructuringElement.h" +#include "otbMultiScaleConvexOrConcaveClassificationFilter.h" +#include "otbImage.h" +#include "itkMacro.h" + +int otbMultiScaleConvexOrConcaveClassificationFilterNew(int argc, char * argv[]) +{ + const unsigned int Dimension = 2; + typedef double InputPixelType; + typedef double OutputPixelType; + typedef unsigned short LabeledPixelType; + + typedef otb::Image<InputPixelType,Dimension> InputImageType; + typedef otb::Image<OutputPixelType,Dimension> OutputImageType; + typedef otb::Image<LabeledPixelType,2> LabeledImageType; + + typedef otb::MultiScaleConvexOrConcaveClassificationFilter<InputImageType,LabeledImageType> MultiScaleClassificationFilterType; + + // Instantiation + MultiScaleClassificationFilterType::Pointer classificationFilter = MultiScaleClassificationFilterType::New(); + + return EXIT_SUCCESS; +} diff --git a/Testing/Code/MultiScale/otbMultiScaleTests3.cxx b/Testing/Code/MultiScale/otbMultiScaleTests3.cxx index b43a9e264c..7370f4fb2d 100644 --- a/Testing/Code/MultiScale/otbMultiScaleTests3.cxx +++ b/Testing/Code/MultiScale/otbMultiScaleTests3.cxx @@ -30,4 +30,6 @@ REGISTER_TEST(otbProfileToProfileDerivativeFilterNew); REGISTER_TEST(otbProfileToProfileDerivativeFilter); REGISTER_TEST(otbProfileDerivativeToMultiScaleCharacteristicsFilterNew); REGISTER_TEST(otbProfileDerivativeToMultiScaleCharacteristicsFilter); +REGISTER_TEST(otbMultiScaleConvexOrConcaveClassificationFilterNew); +REGISTER_TEST(otbMultiScaleConvexOrConcaveClassificationFilter); } diff --git a/Testing/Code/MultiScale/otbProfileDerivativeToMultiScaleCharacteristicsFilter.cxx b/Testing/Code/MultiScale/otbProfileDerivativeToMultiScaleCharacteristicsFilter.cxx index 66efbed305..6f0da0b149 100644 --- a/Testing/Code/MultiScale/otbProfileDerivativeToMultiScaleCharacteristicsFilter.cxx +++ b/Testing/Code/MultiScale/otbProfileDerivativeToMultiScaleCharacteristicsFilter.cxx @@ -32,7 +32,7 @@ int otbProfileDerivativeToMultiScaleCharacteristicsFilter(int argc, char * argv[ const char * outputFilename2 = argv[3]; const unsigned int profileSize = atoi(argv[4]); const unsigned int initialValue = atoi(argv[5]); - const unsigned int step = atoi(argv[5]); + const unsigned int step = atoi(argv[6]); const unsigned int Dimension = 2; -- GitLab