diff --git a/Code/FeatureExtraction/otbModulusAndDirectionImageToImageFilter.txx b/Code/FeatureExtraction/otbModulusAndDirectionImageToImageFilter.txx index 03950a847203ab83023cff500e3aad76dbc72e79..27a89489d4481a27421051fee014726bcb28214f 100755 --- a/Code/FeatureExtraction/otbModulusAndDirectionImageToImageFilter.txx +++ b/Code/FeatureExtraction/otbModulusAndDirectionImageToImageFilter.txx @@ -81,7 +81,7 @@ const typename ModulusAndDirectionImageToImageFilter<TInputImage, TInputImageDir ModulusAndDirectionImageToImageFilter<TInputImage, TInputImageDirection, TOutputImage>:: GetInputDirection(void) { - if (this->GetNumberOfInputs() < 1) + if (this->GetNumberOfInputs() < 2) { return 0; } diff --git a/Code/FeatureExtraction/otbVectorizationPathListFilter.h b/Code/FeatureExtraction/otbVectorizationPathListFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..469fe7a1c70c9d8606984034ce8e2597fcbcc3b6 --- /dev/null +++ b/Code/FeatureExtraction/otbVectorizationPathListFilter.h @@ -0,0 +1,141 @@ +/*========================================================================= + +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 _otbVectorizationPathListFilter_h +#define _otbVectorizationPathListFilter_h + +#include "otbPathListSource.h" +#include "itkImageRegionConstIterator.h" +#include "itkImageRegionIterator.h" +#include "itkConstNeighborhoodIterator.h" +#include "itkNeighborhoodIterator.h" +#include "itkConstantBoundaryCondition.h" +#include "otbImage.h" + +namespace otb +{ +/** \class VectorizationPathListFilter + * \brief + * + * \ingroup + * \ingroup + */ +template <class TInputModulus, class TInputDirection, class TOutputPath> +class ITK_EXPORT VectorizationPathListFilter + : public PathListSource<TOutputPath> +{ + public: + /** Standard typedefs */ + typedef VectorizationPathListFilter Self; + typedef PathListSource<TOutputPath> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Type macro */ + itkNewMacro(Self); + + /** Creation through object factory macro */ + itkTypeMacro(VectorizationPathListFilter, PathListSource); + + /** Template parameters typedefs */ + typedef TInputModulus InputModulusType; + typedef typename InputModulusType::ConstPointer InputModulusConstPointerType; + typedef typename InputModulusType::PixelType InputPixelType; + typedef typename InputModulusType::PointType PointType; + typedef typename InputModulusType::IndexType IndexType; + + typedef TInputDirection InputDirectionType; + typedef typename InputDirectionType::ConstPointer InputDirectionConstPointerType; + typedef TOutputPath OutputPathType; + typedef typename OutputPathType::Pointer OutputPathPointerType; + typedef typename OutputPathType::ContinuousIndexType VertexType; + + /** Derived typedefs */ + typedef typename Superclass::OutputPathListType OutputPathListType; + typedef typename Superclass::OutputPathListPointerType OutputPathListPointerType; + + /** Set/get the input modulus */ + void SetInput(InputModulusType * inputModulus); + const InputModulusType * GetInput(void); + + /** Set/get the input direction */ + void SetInputDirection(InputDirectionType * inputDirection); + const InputDirectionType * GetInputDirection(void); + + itkSetMacro(AmplitudeThreshold,InputPixelType); + itkGetMacro(AmplitudeThreshold,InputPixelType); + +protected: + + /** Other internal useful typedefs */ + typedef otb::Image<bool,InputModulusType::ImageDimension> FlagImageType; + typedef typename FlagImageType::Pointer FlagImagePointerType; + + typedef itk::ImageRegionConstIterator<InputModulusType> ModRegionIteratorType; + typedef itk::ImageRegionConstIterator<InputDirectionType> DirRegionIteratorType; + typedef itk::ImageRegionIterator<FlagImageType> FlagRegionIteratorType; + + typedef itk::ConstantBoundaryCondition<InputModulusType> ModBCType; + typedef itk::ConstantBoundaryCondition<InputDirectionType> DirBCType; + typedef itk::ConstantBoundaryCondition<FlagImageType> FlagBCType; + + typedef itk::ConstNeighborhoodIterator<InputModulusType,ModBCType> ModNeighborhoodIteratorType; + typedef itk::ConstNeighborhoodIterator<InputDirectionType,ModBCType> DirNeighborhoodIteratorType; + typedef itk::NeighborhoodIterator<FlagImageType,FlagBCType> FlagNeighborhoodIteratorType; + + typedef typename ModNeighborhoodIteratorType::RadiusType RadiusType; + typedef typename ModNeighborhoodIteratorType::OffsetType OffsetType; + typedef std::vector<OffsetType> OffsetVectorType; + + typedef typename OutputPathType::VertexListType VertexListType; + typedef typename VertexListType::ConstPointer VertexListPointerType; + typedef typename VertexListType::ConstIterator VertexIteratorType; + + /** Constructor */ + VectorizationPathListFilter(); + /** Destructor */ + virtual ~VectorizationPathListFilter() {}; + /**PrintSelf method */ + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + /** Main computation method */ + virtual void GenerateData(void); + /** + * Compute a vector of the 8 neighbors to explore from the direction and the type of search (forward or backward). + * \param direction The direction + * \param flagReverse The type of search + * \return The neighborhood vector + */ + OffsetVectorType GetEightNeighborOffsetFromDirection(double direction, unsigned int flagReverse); + /** + * Compute a vector of the 3 neighbors to explore from the direction and the type of search (forward or backward). + * \param direction The direction + * \param flagReverse The type of search + * \return The neighborhood vector + */ + OffsetVectorType GetThreeNeighborOffsetFromDirection(double direction, unsigned int flagReverse); +private: + VectorizationPathListFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + /** Amplitude threshold to start following a path */ + InputPixelType m_AmplitudeThreshold; +}; +}// End namespace otb +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbVectorizationPathListFilter.txx" +#endif + +#endif diff --git a/Code/FeatureExtraction/otbVectorizationPathListFilter.txx b/Code/FeatureExtraction/otbVectorizationPathListFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..7ab83f7b2fb7c9254010d9c61db87e73e71d5b79 --- /dev/null +++ b/Code/FeatureExtraction/otbVectorizationPathListFilter.txx @@ -0,0 +1,484 @@ +/*========================================================================= + +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 _otbVectorizationPathListFilter_txx +#define _otbVectorizationPathListFilter_txx + +#include "otbVectorizationPathListFilter.h" +#include "otbMacro.h" + +#ifndef M_PI +#define M_PI vcl_acos(-1.0) +#endif + +namespace otb +{ +/** + * Constructor + */ +template <class TInputModulus, class TInputDirection, class TOutputPath> +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::VectorizationPathListFilter() +{ + this->SetNumberOfRequiredInputs(2); + this->SetNumberOfInputs(2); + m_AmplitudeThreshold = 1.0; +} +template <class TInputModulus, class TInputDirection, class TOutputPath> +void +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::SetInput(InputModulusType * inputModulus) +{ + this->itk::ProcessObject::SetNthInput(0,const_cast<InputModulusType *>(inputModulus)); +} +template <class TInputModulus, class TInputDirection, class TOutputPath> +const typename VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::InputModulusType * +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::GetInput(void) +{ + if (this->GetNumberOfInputs() < 1) + { + return 0; + } + return static_cast<const TInputModulus*>(this->itk::ProcessObject::GetInput(0)); +} +template <class TInputModulus, class TInputDirection, class TOutputPath> +void +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::SetInputDirection(InputDirectionType * inputDirection) +{ + this->itk::ProcessObject::SetNthInput(1,const_cast<InputDirectionType *>(inputDirection)); +} +template <class TInputModulus, class TInputDirection, class TOutputPath> +const typename VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::InputDirectionType * +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::GetInputDirection(void) +{ + if (this->GetNumberOfInputs() < 2) + { + return 0; + } + return static_cast<const TInputDirection *>(this->itk::ProcessObject::GetInput(1)); +} +/** + * Main computation method + */ +template <class TInputModulus, class TInputDirection, class TOutputPath> +void +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::GenerateData(void) +{ + InputModulusConstPointerType modPtr = this->GetInput(); + InputDirectionConstPointerType dirPtr = this->GetInputDirection(); + OutputPathListPointerType outPtr = this->GetOutput(); + + typedef typename OffsetVectorType::iterator OffsetIteratorType; + + RadiusType radius; + radius.Fill(2); + OffsetVectorType offsetVector; + + // Creation of the flag image + FlagImagePointerType flagImage = FlagImageType::New(); + flagImage->SetRegions(modPtr->GetLargestPossibleRegion()); + flagImage->Allocate(); + flagImage->FillBuffer(false); + + // Iterators instantiation + ModRegionIteratorType modIt(modPtr,modPtr->GetLargestPossibleRegion()); + DirRegionIteratorType dirIt(dirPtr,dirPtr->GetLargestPossibleRegion()); + FlagRegionIteratorType flagIt(flagImage,flagImage->GetLargestPossibleRegion()); + + for(modIt.GoToBegin(),dirIt.GoToBegin(),flagIt.GoToBegin(); + (!modIt.IsAtEnd()) && (!dirIt.IsAtEnd()) && (!flagIt.IsAtEnd()); + ++modIt,++dirIt,++flagIt) + { + if((modIt.Get() > m_AmplitudeThreshold) && (!flagIt.Get())) + { + //this is a begining, to follow in two directions + OutputPathPointerType pathTempDirect = OutputPathType::New(); + OutputPathPointerType pathTempReverse = OutputPathType::New(); + OutputPathPointerType path = OutputPathType::New(); + + bool flagFinish; + int flagReverse = 0; + double totalAmplitude = 0; + + ModNeighborhoodIteratorType nModIt(radius,modPtr,modPtr->GetLargestPossibleRegion()); + DirNeighborhoodIteratorType nDirIt(radius,dirPtr,dirPtr->GetLargestPossibleRegion()); + FlagNeighborhoodIteratorType nFlagIt(radius,flagImage,flagImage->GetLargestPossibleRegion()); + + for (flagReverse=0; flagReverse < 2; ++flagReverse) + { + nModIt.SetLocation(modIt.GetIndex()); + nDirIt.SetLocation(dirIt.GetIndex()); + nFlagIt.SetLocation(flagIt.GetIndex()); + // temporary point + PointType point; + VertexType vertex; + modPtr->TransformIndexToPhysicalPoint(nModIt.GetIndex(),point); + modPtr->TransformPhysicalPointToContinuousIndex(point,vertex); + if(flagReverse==0) + { + flagIt.Set(true); + otbMsgDebugMacro(<<"Adding new vertex: "<<vertex); + pathTempDirect->AddVertex(vertex); + } + flagFinish = false; + while(!flagFinish) + { + offsetVector =GetThreeNeighborOffsetFromDirection(nDirIt.GetCenterPixel(),flagReverse); + OffsetIteratorType vecIt = offsetVector.begin(); + bool flagFound=false; + while(vecIt!=offsetVector.end()&&!flagFound) + { + flagFound = nModIt.GetPixel(*vecIt) > 0 + && !nFlagIt.GetPixel(*vecIt); + ++vecIt; + } + if(flagFound) + { + point.Fill(0); + PointType tmpPoint; + totalAmplitude = 0; + for(vecIt = offsetVector.begin();vecIt!=offsetVector.end();++vecIt) + { + totalAmplitude += nModIt.GetPixel(*vecIt); + modPtr->TransformIndexToPhysicalPoint(nModIt.GetIndex(*vecIt),tmpPoint); + point[0] += nModIt.GetPixel(*vecIt) * tmpPoint[0]; + point[1] += nModIt.GetPixel(*vecIt) * tmpPoint[1]; + } + point[0] = point[0] / totalAmplitude + 0.49; + point[1] = point[1] / totalAmplitude + 0.49; + modPtr->TransformPhysicalPointToContinuousIndex(point,vertex); + if(flagReverse == 0) + { + otbMsgDebugMacro(<<"Adding new vertex: "<<vertex); + pathTempDirect->AddVertex(vertex); + } + else + { + otbMsgDebugMacro(<<"Adding new vertex: "<<vertex); + pathTempReverse->AddVertex(vertex); + } + // flag the pixel use + nFlagIt.SetCenterPixel(true); + //update the neighbor iterators so they are centered on the nearest pixel to the barycenter + IndexType newIndex; + if(modPtr->TransformPhysicalPointToIndex(point,newIndex)) + { + nModIt.SetLocation(newIndex); + nDirIt.SetLocation(newIndex); + nFlagIt.SetLocation(newIndex); + + if(nModIt.GetCenterPixel()==0) + { + //we need to check that in case the barycenter is out... + flagFinish=true; + } + if(nFlagIt.GetCenterPixel()) + { + //we don't want to go back to the same pixels + flagFinish=true; + } + } + else + { + //new point outside image + flagFinish=true; + } + } + else + { + flagFinish=true; + } + } + } + VertexListPointerType vertexDirect = pathTempDirect->GetVertexList(); + VertexListPointerType vertexReverse = pathTempReverse->GetVertexList(); + + unsigned int numberVertex = 0; + + VertexIteratorType vertexReverseIt = vertexReverse->End(); + if (vertexReverseIt != vertexReverse->Begin()){ + --vertexReverseIt; + while ( vertexReverseIt != vertexReverse->Begin()){ + path->AddVertex(vertexReverseIt.Value()); + ++numberVertex; + --vertexReverseIt; + } + path->AddVertex(vertexReverseIt.Value()); + } + + + VertexIteratorType vertexDirectIt = vertexDirect->Begin(); + while ( vertexDirectIt != vertexDirect->End()){ + path->AddVertex(vertexDirectIt.Value()); + ++vertexDirectIt; + ++numberVertex; + } + otbMsgDebugMacro(<<"Path number of vertices: "<<numberVertex); + if (numberVertex > 3) { + outPtr->PushBack(path); + } + } + } +} +/** + * Compute the 8 neighbors to explore from the direction and the type of search (forward or backward). + * \param direction The direction + * \param flagReverse The type of search + * \return The neighborhood + */ +template <class TInputModulus, class TInputDirection, class TOutputPath> +typename VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::OffsetVectorType +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::GetEightNeighborOffsetFromDirection(double direction, unsigned int flagReverse) +{ + int neighborhoodNumber=0; + OffsetVectorType offset; + offset.reserve(8); + if (direction > 0) + { + //find the direction in terms of 0,1,2,3 + neighborhoodNumber = (int) (direction/(M_PI/4)-1); + } + else + { + neighborhoodNumber = (int) ((direction+M_PI)/(M_PI/4)-1); + neighborhoodNumber = (neighborhoodNumber + 4); + //if the direction was <0 need to convert to 4,5,6,7 + } + if (flagReverse) + { + //if the reverse flag is activated we need to look on the other side + neighborhoodNumber = (neighborhoodNumber + 4) % 8; + } + switch( neighborhoodNumber ) + { + case 0: + offset.push_back((OffsetType) {{1,0}}); + offset.push_back((OffsetType) {{1,1}}); + offset.push_back((OffsetType) {{0,1}}); + + offset.push_back((OffsetType) {{2,0}}); + offset.push_back((OffsetType) {{2,1}}); + offset.push_back((OffsetType) {{2,2}}); + offset.push_back((OffsetType) {{1,2}}); + offset.push_back((OffsetType) {{0,2}}); + + break; + + case 1: + offset.push_back((OffsetType) {{1,1}}); + offset.push_back((OffsetType) {{0,1}}); + offset.push_back((OffsetType) {{-1,1}}); + + offset.push_back((OffsetType) {{2,2}}); + offset.push_back((OffsetType) {{1,2}}); + offset.push_back((OffsetType) {{0,2}}); + offset.push_back((OffsetType) {{-1,2}}); + offset.push_back((OffsetType) {{-2,2}}); + + break; + + case 2: + offset.push_back((OffsetType) {{0,1}}); + offset.push_back((OffsetType) {{-1,1}}); + offset.push_back((OffsetType) {{-1,0}}); + + offset.push_back((OffsetType) {{0,2}}); + offset.push_back((OffsetType) {{-1,2}}); + offset.push_back((OffsetType) {{-2,2}}); + offset.push_back((OffsetType) {{-2,1}}); + offset.push_back((OffsetType) {{-2,0}}); + + break; + + case 3: + offset.push_back((OffsetType) {{-1,1}}); + offset.push_back((OffsetType) {{-1,0}}); + offset.push_back((OffsetType) {{-1,-1}}); + + offset.push_back((OffsetType) {{-2,2}}); + offset.push_back((OffsetType) {{-2,1}}); + offset.push_back((OffsetType) {{-2,0}}); + offset.push_back((OffsetType) {{-2,-1}}); + offset.push_back((OffsetType) {{-2,-2}}); + + break; + + case 4: + offset.push_back((OffsetType) {{-1,0}}); + offset.push_back((OffsetType) {{-1,-1}}); + offset.push_back((OffsetType) {{0,-1}}); + + offset.push_back((OffsetType) {{-2,0}}); + offset.push_back((OffsetType) {{-2,-1}}); + offset.push_back((OffsetType) {{-2,-2}}); + offset.push_back((OffsetType) {{-1,-2}}); + offset.push_back((OffsetType) {{0,-2}}); + + break; + + case 5: + offset.push_back((OffsetType) {{-1,-1}}); + offset.push_back((OffsetType) {{0,-1}}); + offset.push_back((OffsetType) {{1,-1}}); + + offset.push_back((OffsetType) {{-2,-2}}); + offset.push_back((OffsetType) {{-1,-2}}); + offset.push_back((OffsetType) {{0,-2}}); + offset.push_back((OffsetType) {{1,-2}}); + offset.push_back((OffsetType) {{2,-2}}); + + break; + + case 6: + offset.push_back((OffsetType) {{0,-1}}); + offset.push_back((OffsetType) {{1,-1}}); + offset.push_back((OffsetType) {{1,0}}); + + offset.push_back((OffsetType) {{0,-2}}); + offset.push_back((OffsetType) {{1,-2}}); + offset.push_back((OffsetType) {{2,-2}}); + offset.push_back((OffsetType) {{2,-1}}); + offset.push_back((OffsetType) {{2,0}}); + + break; + + case 7: + offset.push_back((OffsetType) {{1,-1}}); + offset.push_back((OffsetType) {{1,0}}); + offset.push_back((OffsetType) {{1,1}}); + + offset.push_back((OffsetType) {{2,-2}}); + offset.push_back((OffsetType) {{2,-1}}); + offset.push_back((OffsetType) {{2,0}}); + offset.push_back((OffsetType) {{2,1}}); + offset.push_back((OffsetType) {{2,2}}); + + break; + } + return offset; +}/** + * Compute the 3 neighbors to explore from the direction and the type of search (forward or backward). + * \param direction The direction + * \param flagReverse The type of search + * \return The neighborhood + */ +template <class TInputModulus, class TInputDirection, class TOutputPath> +typename VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::OffsetVectorType +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::GetThreeNeighborOffsetFromDirection(double direction, unsigned int flagReverse) +{ + int neighborhoodNumber=0; + OffsetVectorType offset; + offset.reserve(3); + if (direction > 0) + { + //find the direction in terms of 0,1,2,3 + neighborhoodNumber = (int) (direction/(M_PI/4)-1); + } + else + { + neighborhoodNumber = (int) ((direction+M_PI)/(M_PI/4)-1); + neighborhoodNumber = (neighborhoodNumber + 4); + //if the direction was <0 need to convert to 4,5,6,7 + } + if (flagReverse) + { + //if the reverse flag is activated we need to look on the other side + neighborhoodNumber = (neighborhoodNumber + 4) % 8; + } + switch( neighborhoodNumber ) + { + case 0: + offset.push_back((OffsetType) {{1,0}}); + offset.push_back((OffsetType) {{1,1}}); + offset.push_back((OffsetType) {{0,1}}); + + break; + + case 1: + offset.push_back((OffsetType) {{1,1}}); + offset.push_back((OffsetType) {{0,1}}); + offset.push_back((OffsetType) {{-1,1}}); + + break; + + case 2: + offset.push_back((OffsetType) {{0,1}}); + offset.push_back((OffsetType) {{-1,1}}); + offset.push_back((OffsetType) {{-1,0}}); + + break; + + case 3: + offset.push_back((OffsetType) {{-1,1}}); + offset.push_back((OffsetType) {{-1,0}}); + offset.push_back((OffsetType) {{-1,-1}}); + + break; + + case 4: + offset.push_back((OffsetType) {{-1,0}}); + offset.push_back((OffsetType) {{-1,-1}}); + offset.push_back((OffsetType) {{0,-1}}); + + break; + + case 5: + offset.push_back((OffsetType) {{-1,-1}}); + offset.push_back((OffsetType) {{0,-1}}); + offset.push_back((OffsetType) {{1,-1}}); + + break; + + case 6: + offset.push_back((OffsetType) {{0,-1}}); + offset.push_back((OffsetType) {{1,-1}}); + offset.push_back((OffsetType) {{1,0}}); + + break; + + case 7: + offset.push_back((OffsetType) {{1,-1}}); + offset.push_back((OffsetType) {{1,0}}); + offset.push_back((OffsetType) {{1,1}}); + + break; + } + return offset; +} + +/** + * PrintSelf Method + */ +template <class TInputModulus, class TInputDirection, class TOutputPath> +void +VectorizationPathListFilter<TInputModulus, TInputDirection, TOutputPath> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); +} +} // End namespace otb +#endif diff --git a/Testing/Code/FeatureExtraction/CMakeLists.txt b/Testing/Code/FeatureExtraction/CMakeLists.txt index 25d9b964f7faaf7b8562733b1c4dd6fcb124f15b..3eba3c1e715a474f0fb0a9ea48c167cd95984ce8 100755 --- a/Testing/Code/FeatureExtraction/CMakeLists.txt +++ b/Testing/Code/FeatureExtraction/CMakeLists.txt @@ -529,6 +529,22 @@ ADD_TEST(feTvNonMaxRemovalByDirectionFilter ${FEATUREEXTRACTION_TESTS} ${TEMP}/feTvNonMaxRemovalByDirectionOutput.hdr ) +# ------- otb::VectorizationPathListFilter ------------- + +ADD_TEST(feTuVectorizationPathListFilterNew ${FEATUREEXTRACTION_TESTS} + otbVectorizationPathListFilterNew) + +ADD_TEST(feTvVectorizationPathListFilter ${FEATUREEXTRACTION_TESTS} +--compare-ascii ${EPS} + ${BASELINE_FILES}/feTvVectorizationPathListOutput.txt + ${TEMP}/feTvVectorizationPathListOutput.txt + otbVectorizationPathListFilter + ${BASELINE}/feTvNonMaxRemovalByDirectionOutput.hdr + ${BASELINE}/feTvNeigborhoodScalarProductDirectionOutput.hdr + ${TEMP}/feTvVectorizationPathListOutput.txt + ) + + # A enrichir SET(BasicFeatureExtraction_SRCS @@ -591,6 +607,8 @@ otbRemoveWrongDirectionFilterNew.cxx otbRemoveWrongDirectionFilter.cxx otbNonMaxRemovalByDirectionFilterNew.cxx otbNonMaxRemovalByDirectionFilter.cxx +otbVectorizationPathListFilterNew.cxx +otbVectorizationPathListFilter.cxx ) diff --git a/Testing/Code/FeatureExtraction/otbFeatureExtractionTests.cxx b/Testing/Code/FeatureExtraction/otbFeatureExtractionTests.cxx index f82a98e13431b86cde52cfb4324eb5dc3ef442e9..fb728ac644859890446466b4e60ffda2e881bf6f 100755 --- a/Testing/Code/FeatureExtraction/otbFeatureExtractionTests.cxx +++ b/Testing/Code/FeatureExtraction/otbFeatureExtractionTests.cxx @@ -86,4 +86,6 @@ REGISTER_TEST(otbRemoveWrongDirectionFilterNew); REGISTER_TEST(otbRemoveWrongDirectionFilter); REGISTER_TEST(otbNonMaxRemovalByDirectionFilterNew); REGISTER_TEST(otbNonMaxRemovalByDirectionFilter); +REGISTER_TEST(otbVectorizationPathListFilterNew); +REGISTER_TEST(otbVectorizationPathListFilter); } diff --git a/Testing/Code/FeatureExtraction/otbVectorizationPathListFilter.cxx b/Testing/Code/FeatureExtraction/otbVectorizationPathListFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f6e14288ad089f6cb6667edb407bd25f9cc4f1dc --- /dev/null +++ b/Testing/Code/FeatureExtraction/otbVectorizationPathListFilter.cxx @@ -0,0 +1,96 @@ +/*========================================================================= + + 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 "itkExceptionObject.h" +#include "otbVectorizationPathListFilter.h" +#include "otbImage.h" +#include "itkPolyLineParametricPath.h" +#include "otbImageFileReader.h" +#include <fstream> + +#include "otbDrawPathListFilter.h" +#include "otbImageFileWriter.h" + +int otbVectorizationPathListFilter(int argc, char * argv[]) +{ + try + { + const char * modfname = argv[1]; + const char * dirfname = argv[2]; + const char * outfname = argv[3]; + + const unsigned int Dimension = 2; + typedef double PixelType; + typedef otb::Image<PixelType,Dimension> ImageType; + typedef otb::ImageFileReader<ImageType> ReaderType; + typedef itk::PolyLineParametricPath<Dimension> PathType; + typedef otb::VectorizationPathListFilter<ImageType,ImageType,PathType> VectorizationPathListFilterType; + typedef VectorizationPathListFilterType::OutputPathListType PathListType; + typedef PathListType::ConstIterator PathListIteratorType; + typedef PathType::VertexListType VertexListType; + typedef VertexListType::ConstIterator VertexIteratorType; + // Instantiating objects + VectorizationPathListFilterType::Pointer filter = VectorizationPathListFilterType::New(); + ReaderType::Pointer modReader = ReaderType::New(); + ReaderType::Pointer dirReader = ReaderType::New(); + + modReader->SetFileName(modfname); + dirReader->SetFileName(dirfname); + + filter->SetInput(modReader->GetOutput()); + filter->SetInputDirection(dirReader->GetOutput()); + filter->Update(); + + PathListType::Pointer pathList = filter->GetOutput(); + PathListIteratorType pathListIt = pathList->Begin(); + + std::ofstream file; + file.open(outfname); + unsigned int counter = 0; + + while(pathListIt!=pathList->End()) + { + file<<"Path "<<counter<<": "; + for(VertexIteratorType vIt = pathListIt.Get()->GetVertexList()->Begin(); + vIt!=pathListIt.Get()->GetVertexList()->End(); + ++vIt) + { + if(vIt!=pathListIt.Get()->GetVertexList()->Begin()) + { + file<<", "; + } + file<<vIt.Value(); + } + file<<std::endl; + ++pathListIt; + ++counter; + } + file.close(); + } + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject thrown !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Unknown exception thrown !" << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/Testing/Code/FeatureExtraction/otbVectorizationPathListFilterNew.cxx b/Testing/Code/FeatureExtraction/otbVectorizationPathListFilterNew.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b289f809537db3b41b1231f522d46abf9db26b3b --- /dev/null +++ b/Testing/Code/FeatureExtraction/otbVectorizationPathListFilterNew.cxx @@ -0,0 +1,50 @@ +/*========================================================================= + + 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 "itkExceptionObject.h" +#include "otbVectorizationPathListFilter.h" +#include "otbImage.h" +#include "itkPolyLineParametricPath.h" + +int otbVectorizationPathListFilterNew(int argc, char * argv[]) +{ + try + { + const unsigned int Dimension = 2; + typedef double PixelType; + typedef otb::Image<PixelType,Dimension> ImageType; + typedef itk::PolyLineParametricPath<Dimension> PathType; + typedef otb::VectorizationPathListFilter<ImageType,ImageType,PathType> VectorizationPathListFilterType; + + // Instantiating object + VectorizationPathListFilterType::Pointer object = VectorizationPathListFilterType::New(); + } + + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject thrown !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + + catch( ... ) + { + std::cout << "Unknown exception thrown !" << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +}