diff --git a/Code/BasicFilters/otbOpeningClosingMorphologicalFilter.h b/Code/BasicFilters/otbOpeningClosingMorphologicalFilter.h index d145f9c971d786973644e88c0f4f5f10b5eaa9e9..dfdc2fec3b5e6c6f18712e4fd4cf03566a411f55 100644 --- a/Code/BasicFilters/otbOpeningClosingMorphologicalFilter.h +++ b/Code/BasicFilters/otbOpeningClosingMorphologicalFilter.h @@ -1,4 +1,3 @@ - /*========================================================================= Program: ORFEO Toolbox diff --git a/Code/Common/otbObjectList.txx b/Code/Common/otbObjectList.txx index ab95f08d7466ab6136801b911ffa039689a1838c..ee5460ac97c2c476e1540fdcd8ea3e975c671cbe 100644 --- a/Code/Common/otbObjectList.txx +++ b/Code/Common/otbObjectList.txx @@ -162,7 +162,9 @@ namespace otb template <class TObject> ObjectList<TObject>::Iterator ::Iterator(InternalIteratorType iter) - {} + { + m_Iter=iter; + } /** * Get the current object. * \return The current object pointed by the iterator. @@ -245,7 +247,9 @@ namespace otb template <class TObject> ObjectList<TObject>::ConstIterator ::ConstIterator(InternalConstIteratorType iter) - {} + { + m_Iter=iter; + } /** * Get the current object. * \return The current object pointed by the iterator. @@ -348,7 +352,9 @@ namespace otb template <class TObject> ObjectList<TObject>::ReverseIterator ::ReverseIterator(InternalReverseIteratorType iter) - {} + { + m_Iter=iter; + } /** * Get the current object. * \return The current object pointed by the iterator. @@ -431,7 +437,9 @@ namespace otb template <class TObject> ObjectList<TObject>::ReverseConstIterator ::ReverseConstIterator(InternalReverseConstIteratorType iter) - {} + { + m_Iter=iter; + } /** * Get the current object. * \return The current object pointed by the iterator. diff --git a/Code/Common/otbTestMain.h b/Code/Common/otbTestMain.h index 5869999d6c12be30db5c4a3135eb5aeb0a8a7b14..bdfd4aa0d60ecf8dd39aeb977ed7f1c771a10c75 100644 --- a/Code/Common/otbTestMain.h +++ b/Code/Common/otbTestMain.h @@ -145,8 +145,8 @@ int main(int ac, char* av[] ) baseLineFilenamesImage.push_back(av[4+2*i]); testFilenamesImage.push_back(av[5+2*i]); } - av+=2+2*nbComparisons; - ac-=2+2*nbComparisons; + av+=3+2*nbComparisons; + ac-=3+2*nbComparisons; } else if (strcmp(av[1], "--compare-binary") == 0) { diff --git a/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.h b/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..4dba1c28d31b6b1c40e6817ab769670ab6e46810 --- /dev/null +++ b/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.h @@ -0,0 +1,143 @@ +/*========================================================================= + + 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 _otbMorphologicalPyramidAnalyseFilter_h +#define _otbMorphologicalPyramidAnalyseFilter_h + +#include "otbImageToImageListFilter.h" + +namespace otb +{ +/** \class MorphologicalPyramidAnalyseFilter + * \brief Multiscale analysis filter using the morphological pyramid algorithm. + * + * Pyramidal decomposition is based on the following statement : once an + * image has been smoothed with a linear filter, it does not contain + * any more high-frequency details. Therefore, it can be down-sampled + * without any loss of information, according to Shannon Theorem. By + * iterating the same smoothing on the down-sampled image, a + * multi-resolution decomposition of the scene is + * computed. If the smoothing filter is a morphological filter, this + * is no longer true, as the filter is not linear. However, by keeping + * the details possibly lost in the down-sampling operation, such a + * decomposition can be used. + * + * The MorphologicalPyramidAnalyseFilter provide such a + * decomposition. It's computation process is an iterative analyse + * involving smoothing by the morphological filter, computing the + * details lost in the smoothing, down-sampling the current image, and + * computing the details lost in the down-sampling. + * + * \ingroup MultiScale + * \sa MorphologicalPyramidSynthesisFilter,OpeningClosingMorphologicalFilter, + * ClosingOpeningMorphologicalFilter + */ +template <class TInputImage, class TOutputImage, class TMorphoFilter> +class MorphologicalPyramidAnalyseFilter + : public ImageToImageListFilter<TInputImage,TOutputImage> +{ +public: + /** Standard typedefs */ + typedef MorphologicalPyramidAnalyseFilter Self; + typedef ImageToImageListFilter<TInputImage,TOutputImage> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + /** Creation through object factory macro */ + itkNewMacro(Self); + /** Type macro */ + itkTypeMacro(MorphologicalPyramidAnalyseFilter,MorphologicalPyramidAnalyseFilter); + /** Input image dimension constant macro */ + itkStaticConstMacro(InputImageDimension, unsigned int,TInputImage::ImageDimension); + /** Template parameters typedefs */ + typedef TMorphoFilter MorphoFilterType; + typedef typename MorphoFilterType::KernelType KernelType; + /** Output related typedefs */ + typedef typename Superclass::OutputImageType OutputImageType; + typedef typename Superclass::OutputImageListType OutputImageListType; + typedef typename OutputImageListType::Pointer OutputImageListPointerType; + typedef typename Superclass::OutputImagePointerType OutputImagePointerType; + /** Input related typedefs */ + typedef typename Superclass::InputImageType InputImageType; + typedef typename Superclass::InputImageRegionType InputImageRegionType; + typedef typename InputImageType::Pointer InputImagePointerType; + typedef typename InputImageType::ConstPointer InputImageConstPointerType; + typedef typename InputImageType::SizeType SizeType; + typedef typename InputImageType::ValueType ValueType; + typedef typename InputImageType::PixelType PixelType; + typedef typename InputImageType::SpacingType SpacingType; + /** Size and spacing vector typedefs */ + typedef std::vector<SpacingType> SpacingVectorType; + typedef std::vector<SizeType> SizeVectorType; + /** Accessors */ + itkSetMacro(NumberOfIterations, int); + itkSetMacro(SubSampleScale, float); + itkGetConstReferenceMacro(NumberOfIterations, int); + itkGetConstReferenceMacro(SubSampleScale, float); + /** Details images lists getters */ + itkGetConstReferenceMacro(SupFiltre,OutputImageListPointerType); + itkGetConstReferenceMacro(InfFiltre,OutputImageListPointerType); + itkGetConstReferenceMacro(SupDeci,OutputImageListPointerType); + itkGetConstReferenceMacro(InfDeci,OutputImageListPointerType); + /* /\** Spacings list getters *\/ */ +/* virtual std::vector<typename TOutputImage::SpacingType> GetSpacing(); */ +/* /\** Size list getters *\/ */ +/* virtual std::vector<typename TOutputImage::SizeType> GetSize(); */ + +protected: + /** Constructor */ + MorphologicalPyramidAnalyseFilter(); + /** Destructor */ + ~MorphologicalPyramidAnalyseFilter(); + virtual void GenerateOutputInformation(){}; // does nothing + /** Main computation method */ + virtual void GenerateData(); + /** Printself method */ + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + /** + * Resample an image according to specific size and spacing. + * \param image The image to down sample. + * \param size The new size of the image. + * \param spacing The new spacing of the image. + * \return The resampled image. + */ + InputImagePointerType ResampleImage(InputImagePointerType image, SizeType size, SpacingType spacing); + + private: + /** Number of iterations of the algorithm */ + int m_NumberOfIterations; + /** Subsampling scale used */ + float m_SubSampleScale; + /** Sup details from filtering operations */ + OutputImageListPointerType m_SupFiltre; + /** Inf details from filtering operations */ + OutputImageListPointerType m_InfFiltre; + /** Sup details from subsampling operations */ + OutputImageListPointerType m_SupDeci; + /** Inf details from subsampling operations */ + OutputImageListPointerType m_InfDeci; + /** Spacings vector */ + SpacingVectorType m_Spacing; + /** Sizes vector */ + SizeVectorType m_Size; +}; +}// End namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbMorphologicalPyramidAnalyseFilter.txx" +#endif + +#endif diff --git a/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.txx b/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..855817e9134ea6e9226686fd64ad58e8e6844c2a --- /dev/null +++ b/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.txx @@ -0,0 +1,318 @@ +/*========================================================================= + +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 _otbMorphologicalPyramidAnalyseFilter_txx +#define _otbMorphologicalPyramidAnalyseFilter_txx + +#include "otbMorphologicalPyramidAnalyseFilter.h" +#include "itkSubtractImageFilter.h" +#include "itkMaximumImageFilter.h" +#include "itkImageDuplicator.h" +#include "itkResampleImageFilter.h" +#include "itkIdentityTransform.h" +#include "itkLinearInterpolateImageFunction.h" +#include "itkProgressAccumulator.h" +#include "itkImageRegionConstIterator.h" +#include "itkImageRegionIterator.h" +#include "otbMacro.h" + +namespace otb +{ + /** + * Constructor + */ + template <class TInputImage, class TOutputImage, class TMorphoFilter> + MorphologicalPyramidAnalyseFilter<TInputImage,TOutputImage, TMorphoFilter> + ::MorphologicalPyramidAnalyseFilter() + { + m_SubSampleScale = 2.0; + m_NumberOfIterations = 4; + m_SupFiltre = OutputImageListType::New(); + m_InfFiltre = OutputImageListType::New(); + m_SupDeci = OutputImageListType::New(); + m_InfDeci = OutputImageListType::New(); + } + /** + * Destructor + */ + template <class TInputImage, class TOutputImage, class TMorphoFilter> + MorphologicalPyramidAnalyseFilter<TInputImage,TOutputImage,TMorphoFilter> + ::~MorphologicalPyramidAnalyseFilter(){} + + // template <class TInputImage, class TOutputImage, class TMorphoFilter> + // std::vector<typename TOutputImage::SpacingType> + // MorphologicalPyramidAnalyseFilter<TInputImage,TOutputImage,TMorphoFilter> + // ::GetSpacing(void) + // { + // return m_Spacing; + // } + // template <class TInputImage, class TOutputImage, class TMorphoFilter> + // std::vector<typename TOutputImage::SizeType> + // MorphologicalPyramidAnalyseFilter<TInputImage,TOutputImage,TMorphoFilter> + // ::GetSize(void) + // { + // return m_Size; + // } + + /** + * Resample an image according to specific size and spacing. + * \param image The image to down sample. + * \param size The new size of the image. + * \param spacing The new spacing of the image. + * \return The resampled image. + */ + template <class TInputImage, class TOutputImage, class TMorphoFilter> + typename MorphologicalPyramidAnalyseFilter<TInputImage,TOutputImage,TMorphoFilter> + ::InputImagePointerType + MorphologicalPyramidAnalyseFilter<TInputImage,TOutputImage,TMorphoFilter> + ::ResampleImage(InputImagePointerType image, SizeType size, SpacingType spacing) + { + otbMsgDebugMacro(<<"Call to the ResampleImage method"); + // local variables + unsigned int i; + InputImagePointerType result; + + // Filters definition + typedef itk::ResampleImageFilter<InputImageType,InputImageType> ResampleFilterType; + typedef itk::IdentityTransform<double,InputImageType::ImageDimension> TransformType; + typedef itk::LinearInterpolateImageFunction<InputImageType,double> InterpolatorType; + typedef itk::ImageRegionConstIterator<InputImageType> ConstIteratorType; + typedef itk::ImageRegionIterator<InputImageType> IteratorType; + + // Resampling Filter instantiation + typename ResampleFilterType::Pointer resampler = ResampleFilterType::New(); + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); + typename TransformType::Pointer transform = TransformType::New(); + resampler->SetTransform(transform); + resampler->SetInterpolator(interpolator); + + // Resampling filter set up + resampler->SetOutputSpacing(spacing); + resampler->SetOutputOrigin(image->GetOrigin()); + resampler->SetSize(size); + //resampler->ReleaseDataFlagOn(); + + // Compute the resampled image + resampler->SetInput(image); + resampler->Update(); + result = resampler->GetOutput(); + otbMsgDebugMacro(<<"Resampling done."); + + // // Spacing, scale and size variables declarations +// // For special cases management +// typename InputImageType::RegionType::IndexType inputStart; +// typename InputImageType::RegionType::IndexType outputStart; +// typename InputImageType::RegionType::SizeType inputSize; +// typename InputImageType::RegionType inputRegion; +// typename InputImageType::RegionType outputRegion; + +// // Spmetimes the last line is black +// // In this case, we simply duplicate it +// if(spacing[0]*static_cast<float>(size[0]-1)>=(this->GetInput()->GetSpacing()[0] +// *static_cast<float>(image->GetLargestPossibleRegion().GetSize()[0]-1))) +// { +// inputStart[0]=size[0]-2; +// inputStart[1]=0; +// outputStart[0]=size[0]-1; +// outputStart[1]=0; +// inputSize[0]=1; +// inputSize[1]=size[1]; +// inputRegion.SetSize(inputSize); +// outputRegion.SetSize(inputSize); +// inputRegion.SetIndex(inputStart); +// outputRegion.SetIndex(outputStart); +// ConstIteratorType inputIt(result, inputRegion); +// IteratorType outputIt(result,outputRegion); +// // Last line duplication +// for(inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd();++inputIt,++outputIt) +// { +// outputIt.Set(inputIt.Get()); +// } +// } +// // Spmetimes the last column is black +// // In this case, we simply duplicate it +// if(spacing[1]*static_cast<float>(size[1]-1)>=(this->GetInput()->GetSpacing()[1] +// *static_cast<float>(image->GetLargestPossibleRegion().GetSize()[1]-1))) +// { +// inputStart[1]=size[1]-2; +// inputStart[0]=0; +// outputStart[1]=size[1]-1; +// outputStart[0]=0; +// inputSize[1]=1; +// inputSize[0]=size[0]; +// inputRegion.SetSize(inputSize); +// outputRegion.SetSize(inputSize); +// inputRegion.SetIndex(inputStart); +// outputRegion.SetIndex(outputStart); +// ConstIteratorType inputIt(result, inputRegion); +// IteratorType outputIt(result,outputRegion); +// // Last column duplication +// for(inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd();++inputIt,++outputIt) +// { +// outputIt.Set(inputIt.Get()); +// } +// } + return result; + } + /** + * Main computation method + */ + template <class TInputImage, class TOutputImage, class TMorphoFilter> + void + MorphologicalPyramidAnalyseFilter<TInputImage,TOutputImage,TMorphoFilter> + ::GenerateData(void) + { + // Input image pointer + OutputImageListType * OutputImageList = this->GetOutput(); + // typedefs of the filters + typedef itk::SubtractImageFilter<InputImageType,InputImageType,OutputImageType> SubtractFilterType; + typedef itk::MaximumImageFilter<InputImageType,InputImageType,InputImageType> MaxFilterType; + typedef itk::ImageDuplicator<InputImageType> DuplicatorType; + + // Input Image duplication to the currentImage Pointer + typename DuplicatorType::Pointer duplicator = DuplicatorType::New(); + duplicator->SetInputImage(this->GetInput()); + duplicator->Update(); + typename InputImageType::Pointer currentImage =duplicator->GetOutput(); + typename InputImageType::Pointer upsampled; + + // Structuring element size computation + const int structElementDimension=static_cast<int>(ceilf(this->GetSubSampleScale()/2.)); + + // Structuring element creation + KernelType structuringElement; + structuringElement.SetRadius(structElementDimension); + structuringElement.CreateStructuringElement(); + + // Filters declarations + typename MorphoFilterType::Pointer morphoFilter; + typename MaxFilterType::Pointer max; + typename SubtractFilterType::Pointer subtract1,subtract2,subtract3,subtract4; + + // Spacing and size vectors declarations + typename InputImageType::SpacingType spacing; + typename InputImageType::SizeType size; + + // local variables declarations and initialisations + int i = 0; + int j; + int sizeTmp; + //--------------------------------------------------------// + // Main loop // + //--------------------------------------------------------// + // While the number of iterations is not reached + otbMsgDebugMacro(<<"Entering main loop"); + while(i<this->GetNumberOfIterations()) + { + + // morphological filtering + morphoFilter = MorphoFilterType::New(); + morphoFilter->SetKernel(structuringElement); + morphoFilter->SetInput(currentImage); + morphoFilter->Update(); + + // Maximum between current and filtered image + max=MaxFilterType::New(); + max->SetInput1(morphoFilter->GetOutput()); + max->SetInput2(currentImage); + max->Update(); + + // SupFiltre detail image computation + subtract1 = SubtractFilterType::New(); + subtract1->SetInput1(max->GetOutput()); + subtract1->SetInput2(morphoFilter->GetOutput()); + subtract1->Update(); + otbMsgDebugMacro(<<"MorphologicalPyramidAnalyseFilter: subtract1 OK "<<subtract1->GetOutput()->GetLargestPossibleRegion().GetSize()); + m_SupFiltre->PushBack(subtract1->GetOutput()); + otbMsgDebugMacro("MorphologicalPyramidAnalyseFilter: step "<<i<<" - Image appended to m_SupFiltre"); + + // InfFiltre detail image computation + subtract2 = SubtractFilterType::New(); + subtract2->SetInput1(max->GetOutput()); + subtract2->SetInput2(currentImage); + subtract2->Update(); + otbMsgDebugMacro(<<"MorphologicalPyramidAnalyseFilter: subtract2 OK "<<subtract2->GetOutput()->GetLargestPossibleRegion().GetSize()); + m_InfFiltre->PushBack(subtract2->GetOutput()); + otbMsgDebugMacro("MorphologicalPyramidAnalyseFilter: step "<<i<<" - Image appended to m_InfFiltre"); + // New Size/Spacing computation + spacing = morphoFilter->GetOutput()->GetSpacing(); + size = morphoFilter->GetOutput()->GetLargestPossibleRegion().GetSize(); + m_Spacing.push_back(spacing); + m_Size.push_back(size); + otbMsgDebugMacro(<<"New size and spacing :"); + for (int j =0; j<InputImageType::ImageDimension;j++) + { + sizeTmp=size[j]; + size[j]=static_cast<int>(round(static_cast<double>(sizeTmp)/this->GetSubSampleScale())); + spacing[j]=spacing[j]*((static_cast<double>(sizeTmp))/(static_cast<double>(size[j]))); + otbMsgDebugMacro(<<" "<<size[j]<<", "<<spacing[j]); + } + + // Image subsampling + // Current image becomes the newly subsampled image + currentImage = ResampleImage(morphoFilter->GetOutput(),size,spacing); + otbMsgDebugMacro(<<"MorphologicalPyramidAnalyseFilter: DownSampling OK "<<currentImage->GetLargestPossibleRegion().GetSize()); + // New current image is appeneded to the output list + OutputImageList->PushBack(currentImage); + + // Image upsampling + upsampled = ResampleImage(currentImage,m_Size.back(),m_Spacing.back()); + otbMsgDebugMacro(<<"MorphologicalPyramidAnalyseFilter: UpSampling OK "<<upsampled->GetLargestPossibleRegion().GetSize()); + // Computation of the details lost in the subsampling operation + max=MaxFilterType::New(); + max->SetInput1(morphoFilter->GetOutput()); + max->SetInput2(upsampled); + max->Update(); + otbMsgDebugMacro(<<"MorphologicalPyramidAnalyseFilter: Max OK "<<max->GetOutput()->GetLargestPossibleRegion().GetSize()); + + // InfDeci detail image computation + subtract4 = SubtractFilterType::New(); + subtract4->SetInput1(max->GetOutput()); + subtract4->SetInput2(morphoFilter->GetOutput()); + subtract4->Update(); + otbMsgDebugMacro(<<"MorphologicalPyramidAnalyseFilter: subtract4 OK "<<subtract4->GetOutput()->GetLargestPossibleRegion().GetSize()); + m_InfDeci->PushBack(subtract4->GetOutput()); + otbMsgDebugMacro("MorphologicalPyramidAnalyseFilter: step "<<i<<" - Image appended to m_InfDeci"); + + // SupDeci detail image computation + subtract3 = SubtractFilterType::New(); + subtract3->SetInput1(max->GetOutput()); + subtract3->SetInput2(upsampled); + subtract3->Update(); + otbMsgDebugMacro(<<"MorphologicalPyramidAnalyseFilter: subtract3 OK "<<subtract3->GetOutput()->GetLargestPossibleRegion().GetSize()); + m_SupDeci->PushBack(subtract3->GetOutput()); + otbMsgDebugMacro("MorphologicalPyramidAnalyseFilter: step "<<i<<" - Image appended to m_SupDeci"); + + // Iteration ounter incrementation + i++; + } + otbMsgDebugMacro(<<"Exiting main loop"); + } + /** + * PrintSelf method + */ + template <class TInputImage, class TOutputImage, class TMorphoFilter> + void + MorphologicalPyramidAnalyseFilter<TInputImage,TOutputImage,TMorphoFilter> + ::PrintSelf(std::ostream& os, itk::Indent indent) const + { + Superclass::PrintSelf(os, indent); + os << indent << "SubSampleScale: " << m_SubSampleScale << std::endl; + os << indent << "NumberOfIterations: " << m_NumberOfIterations << std::endl; + } +} // End namespace otb +#endif diff --git a/Testing/Code/BasicFilters/CMakeLists.txt b/Testing/Code/BasicFilters/CMakeLists.txt index b2bd0a9cdbe4a504866ff53b3b6383da68a0fe17..e6ac43de2cb02a1ba86d796e2e7b33e89f2c0729 100755 --- a/Testing/Code/BasicFilters/CMakeLists.txt +++ b/Testing/Code/BasicFilters/CMakeLists.txt @@ -67,10 +67,10 @@ ADD_TEST(bfTuOpeningClosingFilterNew ${BASICFILTERS_TESTS} ADD_TEST(bfTvOpeningClosingFilter ${BASICFILTERS_TESTS} --compare-image ${TOL} ${BASELINE}/bfFiltreOpeningClosing_1.tif - ${TEMP}/ROI_IKO_PAN_LesHalles_OC_MorphoFilter_1.tif + ${TEMP}/bfFiltreOpeningClosing_1.tif otbOpeningClosingMorphologicalFilter ${INPUTDATA}/ROI_IKO_PAN_LesHalles.tif - ${TEMP}/ROI_IKO_PAN_LesHalles_OC_MorphoFilter_1.tif + ${TEMP}/bfFiltreOpeningClosing_1.tif 1) # ------- otb::ClosingOpeningMorphologicalFilter ------------------------------ @@ -80,10 +80,10 @@ ADD_TEST(bfTuClosingOpeningFilterNew ${BASICFILTERS_TESTS} ADD_TEST(bfTvClosingOpeningFilter ${BASICFILTERS_TESTS} --compare-image ${TOL} ${BASELINE}/bfFiltreClosingOpening_1.tif - ${TEMP}/ROI_IKO_PAN_LesHalles_CO_MorphoFilter_1.tif + ${TEMP}/bfFiltreClosingOpening_1.tif otbClosingOpeningMorphologicalFilter ${INPUTDATA}/ROI_IKO_PAN_LesHalles.tif - ${TEMP}/ROI_IKO_PAN_LesHalles_CO_MorphoFilter_1.tif + ${TEMP}/bfFiltreClosingOpening_1.tif 1) # A enrichir diff --git a/Testing/Code/Common/CMakeLists.txt b/Testing/Code/Common/CMakeLists.txt index 41c0b2ac4e8299693140133018e152e00f213b25..3e7368592c5182fd56a5d0b3fa6565169d296945 100644 --- a/Testing/Code/Common/CMakeLists.txt +++ b/Testing/Code/Common/CMakeLists.txt @@ -245,10 +245,10 @@ ADD_TEST(coTuImageListNew ${COMMON_TESTS} ADD_TEST(coTvImageList ${COMMON_TESTS} --compare-image ${TOL} ${INPUTDATA}/amst.png - ${TEMP}/coImageList_amst.png + ${TEMP}/amst.png otbImageList ${INPUTDATA}/amst.png - ${TEMP}/coImageList_amst.png + ${TEMP}/amst.png ) # ------- otb::ImageListSource ------------------------------------------- diff --git a/Testing/Code/Common/otbObjectList.cxx b/Testing/Code/Common/otbObjectList.cxx index e8bff9c630fa05ec73408cd664ffa9b726d5846b..8eaefa5728f21733a8829fd1448eb12130c04788 100644 --- a/Testing/Code/Common/otbObjectList.cxx +++ b/Testing/Code/Common/otbObjectList.cxx @@ -24,7 +24,7 @@ void fail(char * failString) { - std::cout<<"Test failed in "<<failString<<std::endl; + std::cerr<<"Test failed in "<<failString<<std::endl; exit(-1); } @@ -123,6 +123,11 @@ int otbObjectList(int argc, char * argv[]) // Testing iterator ImageListType::Iterator iter = imageList->Begin(); + + if(!(iter!=imageList->End())) + { + fail("Iterator/Begin()!=Iterator/End()"); + } unsigned int index = 0; while(iter!=imageList->End()) { @@ -130,11 +135,11 @@ int otbObjectList(int argc, char * argv[]) { fail("Iterator/1/iter.Get()"); } - else if(index==1&&(reader2->GetOutput()!=iter.Get())) + if((index==1)&&(reader2->GetOutput()!=iter.Get())) { fail("Iterator/2/iter.Get()"); } - else + if(index>1) { fail("Iterator/OutOfBound/iter.Get()"); } @@ -151,11 +156,11 @@ int otbObjectList(int argc, char * argv[]) { fail("ConstIterator/1/iter.Get()"); } - else if(index==1&&(reader2->GetOutput()!=constIter.Get())) + if((index==1)&&(reader2->GetOutput()!=constIter.Get())) { fail("ConstIterator/2/iter.Get()"); } - else + if(index>1) { fail("ConstIterator/OutOfBound/iter.Get()"); } @@ -165,18 +170,23 @@ int otbObjectList(int argc, char * argv[]) //Testing reverse iterator ImageListType::ReverseIterator revIter = imageList->ReverseBegin(); + if(!(revIter!=imageList->ReverseEnd())) + { + fail("ReverseIterator/ReverseBegin()!=ReverseIterator/ReverseEnd()"); + } + index = 0; while(revIter!=imageList->ReverseEnd()) { - if((index==0)&&(reader1->GetOutput()!=revIter.Get())) + if((index==0)&&(reader2->GetOutput()!=revIter.Get())) { fail("ReverseIterator/1/iter.Get()"); } - else if(index==1&&(reader2->GetOutput()!=revIter.Get())) + if((index==1)&&(reader1->GetOutput()!=revIter.Get())) { fail("ReverseIterator/2/iter.Get()"); } - else + if(index>1) { fail("ReverseIterator/OutOfBound/iter.Get()"); } @@ -189,15 +199,15 @@ int otbObjectList(int argc, char * argv[]) index = 0; while(revConstIter!=imageList->ReverseEnd()) { - if((index==0)&&(reader1->GetOutput()!=revConstIter.Get())) + if((index==0)&&(reader2->GetOutput()!=revConstIter.Get())) { fail("ReverseConstIterator/1/iter.Get()"); } - else if(index==1&&(reader2->GetOutput()!=revConstIter.Get())) + if((index==1)&&(reader1->GetOutput()!=revConstIter.Get())) { fail("ReverseConstIterator/2/iter.Get()"); } - else + if(index>1) { fail("ReverseConstIterator/OutOfBound/iter.Get()"); } diff --git a/Testing/Code/MultiScale/CMakeLists.txt b/Testing/Code/MultiScale/CMakeLists.txt index 10aaef6e51312358658ecf72594e591b95b3e05c..537918e5a4b14424950785b83603daeab99f7945 100644 --- a/Testing/Code/MultiScale/CMakeLists.txt +++ b/Testing/Code/MultiScale/CMakeLists.txt @@ -16,13 +16,32 @@ SET(MULTISCALE_TESTS ${CXX_TEST_PATH}/otbMultiScaleTests) # ------- otb::MorphologicalPyramidAnalyseFilter ---------- -ADD_TEST(msTuMorphologicalPyramidAnalyseFilterNew ${MULTISCALE_TESTS} - otbMorphologicalPyramidAnalyseFilterNew) +ADD_TEST(msTuMorphoPyrAnalyseFilterNew ${MULTISCALE_TESTS} + otbMorphologicalPyramidAnalyseFilterNew) + +ADD_TEST(msTvMorphoPyrAnalyseFilter ${MULTISCALE_TESTS} + --compare-n-images ${TOL} 5 + ${BASELINE}/msPyrAn_mire_log_an_2.png + ${TEMP}/msPyrAn_mire_log_an_2.png + ${BASELINE}/msPyrAn_mire_log_sf_2.png + ${TEMP}/msPyrAn_mire_log_sf_2.png + ${BASELINE}/msPyrAn_mire_log_if_2.png + ${TEMP}/msPyrAn_mire_log_if_2.png + ${BASELINE}/msPyrAn_mire_log_sd_2.png + ${TEMP}/msPyrAn_mire_log_sd_2.png + ${BASELINE}/msPyrAn_mire_log_id_2.png + ${TEMP}/msPyrAn_mire_log_id_2.png + otbMorphologicalPyramidAnalyseFilter + ${INPUTDATA}/mire_log.png + ${TEMP}/msPyrAn_mire_log + png + 2 + 2.0) # ------- Fichiers sources CXX ----------------------------------- SET(BasicMultiScale_SRCS otbMorphologicalPyramidAnalyseFilterNew.cxx -#otbMorphologicalPyramidAnalyseFilter.cxx +otbMorphologicalPyramidAnalyseFilter.cxx ) diff --git a/Testing/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.cxx b/Testing/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..52443d8dccc57a911e11b1bf962f725f4a6d1986 --- /dev/null +++ b/Testing/Code/MultiScale/otbMorphologicalPyramidAnalyseFilter.cxx @@ -0,0 +1,134 @@ +/*========================================================================= + +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 "otbMorphologicalPyramidAnalyseFilter.h" +#include "otbOpeningClosingMorphologicalFilter.h" +#include "itkBinaryBallStructuringElement.h" +#include "otbImageFileReader.h" +#include "otbImageFileWriter.h" +#include "otbImage.h" + +int otbMorphologicalPyramidAnalyseFilter(int argc, char * argv[]) +{ + try + { + const char * inputFilename = argv[1]; + const char * outputFilenamePrefix = argv[2]; + const char * outputFilenameSuffix = argv[3]; + const unsigned int numberOfIterations = atoi(argv[4]); + const float subSampleScale = atof(argv[5]); + + const unsigned int Dimension = 2; + typedef unsigned char InputPixelType; + typedef unsigned char OutputPixelType; + + typedef otb::Image<InputPixelType,Dimension> InputImageType; + typedef otb::Image<OutputPixelType,Dimension> OutputImageType; + + typedef otb::ImageFileReader<InputImageType> ReaderType; + typedef otb::ImageFileWriter<OutputImageType> WriterType; + + typedef itk::BinaryBallStructuringElement<InputPixelType,Dimension> StructuringElementType; + typedef otb::OpeningClosingMorphologicalFilter<InputImageType,InputImageType,StructuringElementType> + OpeningClosingFilterType; + typedef otb::MorphologicalPyramidAnalyseFilter<InputImageType,OutputImageType,OpeningClosingFilterType> + PyramidFilterType; + typedef PyramidFilterType::OutputImageListType::Iterator ImageListIterator; + + // Reading input image + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(inputFilename); + + // Instantiation + PyramidFilterType::Pointer pyramid = PyramidFilterType::New(); + pyramid->SetNumberOfIterations(numberOfIterations); + pyramid->SetSubSampleScale(subSampleScale); + pyramid->SetInput(reader->GetOutput()); + pyramid->Update(); + + + // Retrieving iterators on the results images + ImageListIterator itAnalyse = pyramid->GetOutput()->Begin(); + ImageListIterator itSupFiltre = pyramid->GetSupFiltre()->Begin(); + ImageListIterator itInfFiltre = pyramid->GetInfFiltre()->Begin(); + ImageListIterator itInfDeci = pyramid->GetSupDeci()->Begin(); + ImageListIterator itSupDeci = pyramid->GetInfDeci()->Begin(); + + WriterType::Pointer writer = WriterType::New(); + + int i=1; + // Writing the results images + std::cout<<(itAnalyse!=(pyramid->GetOutput()->End()))<<std::endl; + while((itAnalyse!=pyramid->GetOutput()->End()) + &&(itSupFiltre!=pyramid->GetSupFiltre()->End()) + &&(itInfFiltre!=pyramid->GetInfFiltre()->End()) + &&(itInfDeci!=pyramid->GetInfDeci()->End()) + &&(itSupDeci!=pyramid->GetSupDeci()->End()) + ) + { + std::stringstream oss; + oss<<outputFilenamePrefix<<"_an_"<<i<<"."<<outputFilenameSuffix; + writer->SetInput(itAnalyse.Get()); + writer->SetFileName(oss.str().c_str()); + writer->Update(); + oss.str(""); + oss<<outputFilenamePrefix<<"_sf_"<<i<<"."<<outputFilenameSuffix; + writer->SetInput(itSupFiltre.Get()); + writer->SetFileName(oss.str().c_str()); + writer->Update(); + oss.str(""); + oss<<outputFilenamePrefix<<"_if_"<<i<<"."<<outputFilenameSuffix; + writer->SetInput(itInfFiltre.Get()); + writer->SetFileName(oss.str().c_str()); + writer->Update(); + oss.str(""); + oss<<outputFilenamePrefix<<"_id_"<<i<<"."<<outputFilenameSuffix; + writer->SetInput(itInfDeci.Get()); + writer->SetFileName(oss.str().c_str()); + writer->Update(); + std::cout<<"File "<<oss<<" written"<<std::endl; + oss.str(""); + oss<<outputFilenamePrefix<<"_sd_"<<i<<"."<<outputFilenameSuffix; + writer->SetInput(itSupDeci.Get()); + writer->SetFileName(oss.str().c_str()); + writer->Update(); + oss.str(""); + ++itAnalyse; + ++itSupFiltre; + ++itInfFiltre; + ++itInfDeci; + ++itSupDeci; + ++i; + } + } + 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/MultiScale/otbMorphologicalPyramidAnalyseFilterNew.cxx b/Testing/Code/MultiScale/otbMorphologicalPyramidAnalyseFilterNew.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d3970d502204845ded6f1bd7d99ca9c5d1c7d79a --- /dev/null +++ b/Testing/Code/MultiScale/otbMorphologicalPyramidAnalyseFilterNew.cxx @@ -0,0 +1,56 @@ +/*========================================================================= + + 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 "otbMorphologicalPyramidAnalyseFilter.h" +#include "otbOpeningClosingMorphologicalFilter.h" +#include "itkBinaryBallStructuringElement.h" +#include "otbImage.h" + +int otbMorphologicalPyramidAnalyseFilterNew(int argc, char * argv[]) +{ + try + { + const unsigned int Dimension = 2; + typedef unsigned char InputPixelType; + typedef unsigned char OutputPixelType; + typedef otb::Image<InputPixelType,Dimension> InputImageType; + typedef otb::Image<OutputPixelType,Dimension> OutputImageType; + typedef itk::BinaryBallStructuringElement<InputPixelType,Dimension> StructuringElementType; + typedef otb::OpeningClosingMorphologicalFilter<InputImageType,InputImageType,StructuringElementType> + OpeningClosingFilterType; + typedef otb::MorphologicalPyramidAnalyseFilter<InputImageType,OutputImageType,OpeningClosingFilterType> + PyramidFilterType; + // Instantiation + PyramidFilterType::Pointer pyramid = PyramidFilterType::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; +} diff --git a/Testing/Code/MultiScale/otbMultiScaleTests.cxx b/Testing/Code/MultiScale/otbMultiScaleTests.cxx index ea6d1b34fec294065afdd75c78ece09b46447378..5433d46e8011e01158536693a826296f963b8c64 100644 --- a/Testing/Code/MultiScale/otbMultiScaleTests.cxx +++ b/Testing/Code/MultiScale/otbMultiScaleTests.cxx @@ -27,5 +27,5 @@ void RegisterTests() { REGISTER_TEST(otbMorphologicalPyramidAnalyseFilterNew); - +REGISTER_TEST(otbMorphologicalPyramidAnalyseFilter); } diff --git a/otbIncludeDirectories.cmake b/otbIncludeDirectories.cmake index c7129447b5c49b99c634633a70c9f3f5f932873a..c7690b553b7e154846cd5d60010946bb5bf8899a 100644 --- a/otbIncludeDirectories.cmake +++ b/otbIncludeDirectories.cmake @@ -15,6 +15,7 @@ SET(OTB_INCLUDE_DIRS_BUILD_TREE ${OTB_INCLUDE_DIRS_BUILD_TREE} ${OTB_SOURCE_DIR}/Code/ChangeDetection ${OTB_SOURCE_DIR}/Code/FeatureExtraction ${OTB_SOURCE_DIR}/Code/Learning + ${OTB_SOURCE_DIR}/Code/MultiScale ${OTB_SOURCE_DIR}/Code/Visu ${OTB_BINARY_DIR}/Code/Visu ) @@ -65,6 +66,7 @@ SET(OTB_INCLUDE_DIRS_INSTALL_TREE ${OTB_INCLUDE_DIRS_INSTALL_TREE} ${OTB_INSTALL_INCLUDE_DIR}/ChangeDetection ${OTB_INSTALL_INCLUDE_DIR}/FeatureExtraction ${OTB_INSTALL_INCLUDE_DIR}/Learning + ${OTB_INSTALL_INCLUDE_DIR}/MultiScale ${OTB_INSTALL_INCLUDE_DIR}/Visu ${OTB_INSTALL_INCLUDE_DIR}/Utilities ${OTB_INSTALL_INCLUDE_DIR}/Utilities/ITK