From 05c8ebc97c936752ab1f75d2720447466d2bc5ba Mon Sep 17 00:00:00 2001 From: Julien Michel <julien.michel@c-s.fr> Date: Mon, 27 Nov 2006 11:37:50 +0000 Subject: [PATCH] Ajout du filtre de segmentation de la pyramide morphologique. --- .../otbMorphologicalPyramidSegmenter.h | 149 +++++++++ .../otbMorphologicalPyramidSegmenter.txx | 303 ++++++++++++++++++ Testing/Code/MultiScale/CMakeLists.txt | 35 ++ .../otbMorphologicalPyramidSegmenter.cxx | 84 +++++ .../otbMorphologicalPyramidSegmenterNew.cxx | 54 ++++ .../Code/MultiScale/otbMultiScaleTests.cxx | 2 + 6 files changed, 627 insertions(+) create mode 100644 Code/MultiScale/otbMorphologicalPyramidSegmenter.h create mode 100644 Code/MultiScale/otbMorphologicalPyramidSegmenter.txx create mode 100644 Testing/Code/MultiScale/otbMorphologicalPyramidSegmenter.cxx create mode 100644 Testing/Code/MultiScale/otbMorphologicalPyramidSegmenterNew.cxx diff --git a/Code/MultiScale/otbMorphologicalPyramidSegmenter.h b/Code/MultiScale/otbMorphologicalPyramidSegmenter.h new file mode 100644 index 0000000000..76b6f90ad2 --- /dev/null +++ b/Code/MultiScale/otbMorphologicalPyramidSegmenter.h @@ -0,0 +1,149 @@ +/*========================================================================= + +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 _otbMorphologicalPyramidSegmenter_h +#define _otbMorphologicalPyramidSegmenter_h + +#include "itkImageToImageFilter.h" + +namespace otb +{ + namespace morphologicalPyramid + { + /** + * \class Segmenter + * \brief This class performs the segmentation of a detail image extracted from a + * morphological pyramid analysis. + * + * This class performs the segmentation of a detail image extracted from a + * morphological pyramid analysis. + * + * The Segmentation is perfomed using the ConnectedThresholdImageFilter. The seeds + * are extracted from the image using the ImageToPointSetFilter. The thresolds are set + * by using quantiles computed with the HistogramGenerator. + * + * \sa MorphologicalPyramidAnalyseFilter + * \sa MorphologicalPyramidSynthesisFilter + * \sa ResampleImageFilter + * \sa LinearInterpolateImageFunction + * \sa ScaleTransform + */ + template <class TInputImage, class TOutputImage> + class Segmenter + : public itk::ImageToImageFilter<TInputImage,TOutputImage> + { + public : + /** Standard typedefs */ + typedef Segmenter Self; + typedef itk::ImageToImageFilter<TInputImage,TOutputImage> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + /** Creation through object factory macro */ + itkNewMacro(Self); + /** Type macro */ + itkTypeMacro(Segmenter,ImageToImageFilter); + /** Template parameters typedefs */ + typedef TInputImage InputImageType; + typedef typename InputImageType::PixelType InputPixelType; + typedef typename InputImageType::Pointer InputImagePointerType; + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::Pointer OutputImagePointerType; + typedef typename OutputImageType::PixelType OutputPixelType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::SizeType SizeType; + typedef typename OutputImageType::SpacingType SpacingType; + + /** ImageDimension constants */ + itkStaticConstMacro(DetailsImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OriginalImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TOutputImage::ImageDimension); + /** + * Set the details image. + * \param detailsImage The details image from the morphological pyramid + */ + void SetDetailsImage(const InputImageType * detailsImage); + /** + * Set the details image. + * \return detailsImage The input details image. + */ + InputImageType * GetDetailsImage(void); + /** + * Set the original image. + * \param originalImage The original image to segment. + */ + void SetOriginalImage(const InputImageType * originalImage); + /** + * Get the original image. + * \return originalImage The original image to segment. + */ + InputImageType * GetOriginalImage(void); + + /** Min object size parameter accessor */ + itkSetMacro(MinimumObjectSize,unsigned long); + itkGetMacro(MinimumObjectSize,unsigned long); + itkSetMacro(SeedsQuantile,float); + itkGetMacro(SeedsQuantile,float); + itkSetMacro(ConnectedThresholdQuantile,float); + itkGetMacro(ConnectedThresholdQuantile,float); + itkSetMacro(SegmentDarkDetailsBool,bool); + itkGetMacro(SegmentDarkDetailsBool,bool); + itkBooleanMacro(SegmentDarkDetailsBool); + itkGetMacro(NumberOfObjects,OutputPixelType); + + protected: + /** Constructor */ + Segmenter(); + /** Destructor */ + ~Segmenter() {}; + /** Main computation method */ + void GenerateData(void); + /** PrintSelf method */ + void PrintSelf(std::ostream& os, itk::Indent indent) const; + /** + * Configure the input datas. + */ + void GenerateInputRequestedRegion(void); + /** + * Configure the output data. + */ + void EnlargeOutputRequestedRegion(void); + + private : + Segmenter(const Self&); // purposely not implemented + void operator=(const Self&); // purposely not implemented + /** Minimum size for the segmented object */ + unsigned long m_MinimumObjectSize; + /** Quantile for seeds determination */ + float m_SeedsQuantile; + /** Quantile to set the connectedThresholdFilter threshold */ + float m_ConnectedThresholdQuantile; + /** Set to true if the details to segment are darker than background */ + bool m_SegmentDarkDetailsBool; + /** Number of segmented objects */ + OutputPixelType m_NumberOfObjects; + }; + } // End namespace morphologicalPyramid +}// End namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbMorphologicalPyramidSegmenter.txx" +#endif + +#endif diff --git a/Code/MultiScale/otbMorphologicalPyramidSegmenter.txx b/Code/MultiScale/otbMorphologicalPyramidSegmenter.txx new file mode 100644 index 0000000000..b0d6c7c2ea --- /dev/null +++ b/Code/MultiScale/otbMorphologicalPyramidSegmenter.txx @@ -0,0 +1,303 @@ +/*========================================================================= + + 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 _otbMorphologicalPyramidSegmenter_txx +#define _otbMorphologicalPyramidSegmenter_txx + +#include "otbMorphologicalPyramidSegmenter.h" + +#include "otbImage.h" +#include "itkConnectedThresholdImageFilter.h" +#include "itkConnectedComponentImageFilter.h" +#include "itkRelabelComponentImageFilter.h" +#include "itkThresholdImageFilter.h" +#include "itkMultiplyImageFilter.h" +#include "itkCastImageFilter.h" +#include "itkInvertIntensityImageFilter.h" +#include "itkRescaleIntensityImageFilter.h" +#include "otbThresholdImageToPointSetFilter.h" +#include "itkScalarImageToHistogramGenerator.h" + +namespace otb +{ +namespace morphologicalPyramid +{ +/** + * Constructor + */ +template <class TInputImage,class TOuputImage> +Segmenter<TInputImage, TOuputImage> +::Segmenter() +{ + this->SetNumberOfRequiredInputs(2); +} +/** + * Set the details image. + * \param detailsImage The details image from the morphological pyramid + */ +template <class TInputImage,class TOuputImage> +void +Segmenter<TInputImage, TOuputImage> +::SetDetailsImage(const InputImageType * detailsImage) +{ +this->SetNthInput(0,const_cast<TInputImage *>(detailsImage)); +} + /** + * Set the details image. + * \return detailsImage The input details image. + */ +template <class TInputImage,class TOuputImage> +typename Segmenter<TInputImage, TOuputImage>::InputImageType * +Segmenter<TInputImage, TOuputImage> +::GetDetailsImage(void) +{ + return const_cast<InputImageType *>(this->GetInput(0)); +} + /** + * Set the original image. + * \param originalImage The original image to segment. + */ +template <class TInputImage,class TOuputImage> +void +Segmenter<TInputImage, TOuputImage> +::SetOriginalImage(const InputImageType * originalImage) +{ + this->SetNthInput(1,const_cast<TInputImage *>(originalImage)); +} +/** + * Get the original image. + * \return originalImage The original image to segment. + */ +template <class TInputImage,class TOuputImage> +typename Segmenter<TInputImage, TOuputImage>::InputImageType * +Segmenter<TInputImage, TOuputImage> +::GetOriginalImage(void) +{ + return const_cast<InputImageType *>(this->GetInput(1)); +} +/** + * Configure the input datas. + */ +template <class TInputImage,class TOuputImage> +void +Segmenter<TInputImage, TOuputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the inputs + InputImagePointerType detailsPtr = + const_cast< InputImageType * >( this->GetInput(0) ); + + InputImagePointerType origPtr = + const_cast< InputImageType * >( this->GetInput(1) ); + + if ( !detailsPtr || !origPtr ) + { + return; + } + + // We need to + // configure the inputs such that all the data is available. + detailsPtr->SetRequestedRegion(detailsPtr->GetLargestPossibleRegion()); + origPtr->SetRequestedRegion(origPtr->GetLargestPossibleRegion()); +} +/** + * Configure the output data + */ +template <class TInputImage,class TOuputImage> +void +Segmenter<TInputImage, TOuputImage> +::EnlargeOutputRequestedRegion(void) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + +/** + * Main computation method + */ +template <class TInputImage,class TOuputImage> +void +Segmenter<TInputImage, TOuputImage> +::GenerateData() +{ + // Input images pointers + InputImagePointerType details = this->GetDetailsImage(); + InputImagePointerType original = this->GetOriginalImage(); + + // Typedefs for details image enhancement + typedef float FloatPixelType; + typedef otb::Image<FloatPixelType,InputImageType::ImageDimension> FloatImageType; + typedef itk::InvertIntensityImageFilter<InputImageType,InputImageType> InvertFilterType; + typedef itk::MultiplyImageFilter<FloatImageType,FloatImageType,FloatImageType> MultiplyFilterType; + typedef itk::CastImageFilter<InputImageType,FloatImageType> CastImageFilterType; + typedef itk::RescaleIntensityImageFilter<FloatImageType,InputImageType> RescaleFilterType; + + //Typedefs for seeds extraction + typedef itk::PointSet<InputPixelType,InputImageType::ImageDimension> PointSetType; + typedef otb::ThresholdImageToPointSetFilter<InputImageType,PointSetType> PointSetFilterType; + typedef typename PointSetType::PointsContainer::Iterator PointSetIteratorType; + typedef typename PointSetType::PointType PointType; + + // Typedefs for segmentation + typedef itk::ConnectedThresholdImageFilter<InputImageType,InputImageType> ConnectedFilterType; + typedef itk::ConnectedComponentImageFilter<InputImageType,OutputImageType> LabelFilterType; + typedef itk::RelabelComponentImageFilter<OutputImageType,OutputImageType> RelabelFilterType; + typedef itk::ThresholdImageFilter<OutputImageType> ThresholdFilterType; + + // Typedefs for statistics computation + typedef itk::Statistics::ScalarImageToHistogramGenerator<InputImageType> HistGeneratorType; + typedef typename HistGeneratorType::HistogramType HistogramType; + + ///////////////////////////////////// + //// Details image enhancement ////// + ///////////////////////////////////// + + // Filters instantiation + typename InvertFilterType::Pointer invert; + typename CastImageFilterType::Pointer cast1 = CastImageFilterType::New(); + typename CastImageFilterType::Pointer cast2 = CastImageFilterType::New(); + typename MultiplyFilterType::Pointer mult = MultiplyFilterType::New(); + typename RescaleFilterType::Pointer rescaler = RescaleFilterType::New(); + + // Pipeline connection + cast1->SetInput(details); + // If we want to segment darker detail, the original image must have its itensity inverted + if(m_SegmentDarkDetailsBool) + { + invert = InvertFilterType::New(); + invert->SetInput(original); + cast2->SetInput(invert->GetOutput()); + } + else + { + cast2->SetInput(original); + } + mult->SetInput1(cast1->GetOutput()); + mult->SetInput2(cast2->GetOutput()); + rescaler->SetInput(mult->GetOutput()); + rescaler->SetOutputMinimum(0); + rescaler->SetOutputMaximum(255); + rescaler->Update(); + + + ///////////////////////////////////// + //// Thresholds computation ///////// + ///////////////////////////////////// + + // Filter instantiation + typename HistGeneratorType::Pointer histogram = HistGeneratorType::New(); + // Thresholds are computed from the quantile + histogram->SetInput(rescaler->GetOutput()); + histogram->SetNumberOfBins(255); + histogram->SetMarginalScale(10.0); + histogram->Compute(); + InputPixelType pointSetThreshold = + static_cast<InputPixelType>(histogram->GetOutput()->Quantile(0,m_SeedsQuantile)); + InputPixelType connectedThresholdValue = + static_cast<InputPixelType>(histogram->GetOutput()->Quantile(0,m_ConnectedThresholdQuantile)); + + ///////////////////////////////////// + //// Seeds extraction /////////////// + ///////////////////////////////////// + + typename PointSetFilterType::Pointer pointSetFilter = PointSetFilterType::New(); + pointSetFilter->SetInput(0,details); + pointSetFilter->SetThreshold(pointSetThreshold); + pointSetFilter->Update(); + + ///////////////////////////////////// + //// Segmentation /////////////////// + ///////////////////////////////////// + + // Filters instantiation + typename ConnectedFilterType::Pointer connectedThreshold = ConnectedFilterType::New(); + typename LabelFilterType::Pointer labeler = LabelFilterType::New(); + typename RelabelFilterType::Pointer relabeler = RelabelFilterType::New(); + typename ThresholdFilterType::Pointer threshold = ThresholdFilterType::New(); + + //Passing seeds to the connected filter + connectedThreshold = ConnectedFilterType::New(); + connectedThreshold->ClearSeeds(); + connectedThreshold->SetInput(rescaler->GetOutput()); + PointSetIteratorType it = pointSetFilter->GetOutput()->GetPoints()->Begin(); + while(it!=pointSetFilter->GetOutput()->GetPoints()->End()) + { + typename OutputImageType::IndexType index; + index[0]=static_cast<long int>(it.Value()[0]*(rescaler->GetOutput()->GetSpacing()[0])); + index[1]=static_cast<long int>(it.Value()[1]*(rescaler->GetOutput()->GetSpacing()[1])); + connectedThreshold->AddSeed(index); + it++; + } + + // segmentation + connectedThreshold->SetLower(connectedThresholdValue); + + // labelling + labeler = LabelFilterType::New(); + relabeler = RelabelFilterType::New(); + labeler->SetInput(connectedThreshold->GetOutput()); + relabeler->SetInput(labeler->GetOutput()); + relabeler->SetMinimumObjectSize(m_MinimumObjectSize); + relabeler->Update(); + + // In some cases it might happen that the whole extent of the image is segmented as a single region. + // Since this is not desirable, we test this case here to avoid it. + threshold = ThresholdFilterType::New(); + threshold->SetInput(relabeler->GetOutput()); + OutputPixelType num = 0; + if(relabeler->GetNumberOfObjects()==1) + { + int surface = rescaler->GetOutput()->GetLargestPossibleRegion().GetSize()[0] + *rescaler->GetOutput()->GetLargestPossibleRegion().GetSize()[1]; + if(relabeler->GetSizeOfObjectsInPixels()[0]==surface) + { + num = 0; + } + else + { + num=1; + } + } + else + { + num= static_cast<OutputPixelType>(relabeler->GetNumberOfObjects()); + } + threshold->ThresholdOutside(0,num); + + // Output connection + threshold->GraftOutput(this->GetOutput()); + threshold->Update(); + this->GraftOutput(threshold->GetOutput()); + m_NumberOfObjects = num; +} +/** + * PrintSelf method + */ +template <class TInputImage,class TOuputImage> +void +Segmenter<TInputImage, TOuputImage> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os,indent); + +} +} // End namespace morphologicalPyramid +} // End namespace otb +#endif diff --git a/Testing/Code/MultiScale/CMakeLists.txt b/Testing/Code/MultiScale/CMakeLists.txt index 04bf371282..7b2e4f6060 100644 --- a/Testing/Code/MultiScale/CMakeLists.txt +++ b/Testing/Code/MultiScale/CMakeLists.txt @@ -95,6 +95,39 @@ ADD_TEST(msTvMorphoPyrMRToMSConverter ${MULTISCALE_TESTS} 4 2.0) +# ------- otb::MorphologicalPyramidSegmenter ---------- + +ADD_TEST(msTuMorphoPyrSegmenterNew ${MULTISCALE_TESTS} + otbMorphologicalPyramidSegmenterNew) + +ADD_TEST(msTvMorphoPyrSegmentBright ${MULTISCALE_TESTS} + --compare-image ${TOL} + ${BASELINE}/msPyrSegmenter_IKO_Halles_4_2_sf.tif + ${TEMP}/msPyrSegmenter_IKO_Halles_4_2_sf.tif + otbMorphologicalPyramidSegmenter + ${TEMP}/msPyrMRToMS_IKO_Halles_4_2_sf_full.tif + ${INPUTDATA}/ROI_IKO_PAN_LesHalles.tif + ${TEMP}/msPyrSegmenter_IKO_Halles_4_2_sf.tif + 0 + 0.9 + 0.9 + 10 +) + +ADD_TEST(msTvMorphoPyrSegmentDark ${MULTISCALE_TESTS} + --compare-image ${TOL} + ${BASELINE}/msPyrSegmenter_IKO_Halles_4_2_if.tif + ${TEMP}/msPyrSegmenter_IKO_Halles_4_2_if.tif + otbMorphologicalPyramidSegmenter + ${TEMP}/msPyrMRToMS_IKO_Halles_4_2_if_full.tif + ${INPUTDATA}/ROI_IKO_PAN_LesHalles.tif + ${TEMP}/msPyrSegmenter_IKO_Halles_4_2_if.tif + 1 + 0.9 + 0.9 + 10 +) + # ------- Fichiers sources CXX ----------------------------------- SET(BasicMultiScale_SRCS otbMorphologicalPyramidResamplerNew.cxx @@ -105,6 +138,8 @@ otbMorphologicalPyramidSynthesisFilterNew.cxx otbMorphologicalPyramidSynthesisFilter.cxx otbMorphologicalPyramidMRToMSConverterNew.cxx otbMorphologicalPyramidMRToMSConverter.cxx +otbMorphologicalPyramidSegmenterNew.cxx +otbMorphologicalPyramidSegmenter.cxx ) diff --git a/Testing/Code/MultiScale/otbMorphologicalPyramidSegmenter.cxx b/Testing/Code/MultiScale/otbMorphologicalPyramidSegmenter.cxx new file mode 100644 index 0000000000..ed19a9028a --- /dev/null +++ b/Testing/Code/MultiScale/otbMorphologicalPyramidSegmenter.cxx @@ -0,0 +1,84 @@ +/*========================================================================= + +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 "otbMorphologicalPyramidSegmenter.h" +#include "otbImageFileReader.h" +#include "otbImageFileWriter.h" +#include "otbImage.h" + +int otbMorphologicalPyramidSegmenter(int argc, char * argv[]) +{ + try + { + const char* inputFilename = argv[1]; + const char* originalFilename = argv[2]; + const char* outputFilename1 = argv[3]; + const bool segmentDark = atoi(argv[4]); + const float seedsQuantile = atof(argv[5]); + const float segmentationQuantile = atof(argv[6]); + const unsigned int minObjectSize = atoi(argv[7]); + + const unsigned int Dimension = 2; + typedef unsigned char InputPixelType; + typedef unsigned short OutputPixelType; + + typedef otb::Image<InputPixelType,Dimension> InputImageType; + typedef otb::Image<OutputPixelType,Dimension> OutputImageType; + + typedef otb::ImageFileReader<InputImageType> ReaderType; + typedef otb::ImageFileWriter<OutputImageType> WriterType; + + typedef otb::morphologicalPyramid::Segmenter<InputImageType,OutputImageType> + SegmenterType; + + // Input images reading + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(inputFilename); + ReaderType::Pointer reader2 = ReaderType::New(); + reader2->SetFileName(originalFilename); + + // Instantiation + SegmenterType::Pointer segmenter = SegmenterType::New(); + segmenter->SetDetailsImage(reader->GetOutput()); + segmenter->SetOriginalImage(reader2->GetOutput()); + segmenter->SetSegmentDarkDetailsBool(segmentDark); + segmenter->SetSeedsQuantile(seedsQuantile); + segmenter->SetConnectedThresholdQuantile(segmentationQuantile); + segmenter->SetMinimumObjectSize(minObjectSize); + + // File writing + WriterType::Pointer writer = WriterType::New(); + writer->SetInput(segmenter->GetOutput()); + writer->SetFileName(outputFilename1); + writer->Update(); + } + 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/otbMorphologicalPyramidSegmenterNew.cxx b/Testing/Code/MultiScale/otbMorphologicalPyramidSegmenterNew.cxx new file mode 100644 index 0000000000..0f21b12953 --- /dev/null +++ b/Testing/Code/MultiScale/otbMorphologicalPyramidSegmenterNew.cxx @@ -0,0 +1,54 @@ +/*========================================================================= + +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 "otbMorphologicalPyramidSegmenter.h" +#include "otbImage.h" + +int otbMorphologicalPyramidSegmenterNew(int argc, char * argv[]) +{ + try + { + const unsigned int Dimension = 2; + typedef unsigned char InputPixelType; + typedef unsigned short OutputPixelType; + + typedef otb::Image<InputPixelType,Dimension> InputImageType; + typedef otb::Image<OutputPixelType,Dimension> OutputImageType; + + typedef otb::morphologicalPyramid::Segmenter<InputImageType,OutputImageType> + SegmenterType; + + // Instantiation + SegmenterType::Pointer segmenter = SegmenterType::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 2333ee854d..18b1ba8c84 100644 --- a/Testing/Code/MultiScale/otbMultiScaleTests.cxx +++ b/Testing/Code/MultiScale/otbMultiScaleTests.cxx @@ -34,4 +34,6 @@ REGISTER_TEST(otbMorphologicalPyramidSynthesisFilterNew); REGISTER_TEST(otbMorphologicalPyramidSynthesisFilter); REGISTER_TEST(otbMorphologicalPyramidMRToMSConverterNew); REGISTER_TEST(otbMorphologicalPyramidMRToMSConverter); +REGISTER_TEST(otbMorphologicalPyramidSegmenterNew); +REGISTER_TEST(otbMorphologicalPyramidSegmenter); } -- GitLab