From 67585c0a51ea3e3b5717e39852f8bdb9d4a51f9d Mon Sep 17 00:00:00 2001 From: Jonathan Guinet <jonathan.guinet@c-s.fr> Date: Mon, 16 May 2011 15:43:43 +0200 Subject: [PATCH] REFAC class otb class inheritance and method overloading to clean code. --- .../otbLabelObjectOpeningMuParserFilter.h | 2 + .../otbLabelObjectOpeningMuParserFilter.txx | 67 ++++-- .../otbRelabelComponentImageFilter.h | 168 +------------ .../otbRelabelComponentImageFilter.txx | 222 +----------------- ...bBandsStatisticsAttributesLabelMapFilter.h | 2 + ...andsStatisticsAttributesLabelMapFilter.txx | 70 ++++-- Code/OBIA/otbLabelMapToLabelImageFilter.txx | 28 +-- Code/OBIA/otbShapeAttributesLabelMapFilter.h | 3 + .../OBIA/otbShapeAttributesLabelMapFilter.txx | 63 +++-- 9 files changed, 152 insertions(+), 473 deletions(-) diff --git a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h index b34c95a2f4..29fb1a19d4 100644 --- a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h +++ b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h @@ -113,6 +113,8 @@ void DisplayVar() const; /** return list of Mu Parser varialbes and address**/ const std::map<std::string, double*>& GetVar() const; +virtual void AllocateOutputs(); + void GenerateInputRequestedRegion(); void EnlargeOutputRequestedRegion(itk::DataObject *){}; diff --git a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx index dbc8c0d77d..ada358c96f 100644 --- a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx +++ b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx @@ -109,36 +109,53 @@ void LabelObjectOpeningMuParserFilter<TImage, TFunction>::SetAttributes(std::vec this->m_Functor.SetAttributes(shapeAttributes, statAttributes, nbOfBands); } +/** Get the reduced attribute set */ template < class TImage, class TFunction> -void LabelObjectOpeningMuParserFilter<TImage, TFunction>::GenerateInputRequestedRegion() -{ - ImagePointer input = const_cast<ImageType *>(this->GetInput()); +void LabelObjectOpeningMuParserFilter<TImage, TFunction> +::AllocateOutputs() + { + // if told to run in place and the types support it, + if( this->GetInPlace() && this->CanRunInPlace() ) + { + // Graft this first input to the output. Later, we'll need to + // remove the input's hold on the bulk data. + // + ImagePointer inputAsOutput = dynamic_cast<TImage *>(const_cast<TImage *>(this->GetInput())); - if ( !input ) - { return; } + if( inputAsOutput ) + { + + this->GraftOutput( inputAsOutput ); + this->GetOutput()->SetLargestPossibleRegion(this->GetOutput()->GetLargestPossibleRegion()); + this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion()); + this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetBufferedRegion()); + + } - for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx) + // If there are more than one outputs, allocate the remaining outputs + for (unsigned int i=1; i < this->GetNumberOfOutputs(); i++) { - ImagePointer input = const_cast<ImageType *>(this->GetInput(idx)); - if (!input.IsNull()) - { - input->SetRequestedRegionToLargestPossibleRegion(); - // Check whether the input is an image of the appropriate - // dimension (use ProcessObject's version of the GetInput() - // method since it returns the input as a pointer to a - // DataObject as opposed to the subclass version which - // static_casts the input to an TInputImage). - - // Use the function object RegionCopier to copy the output region - // to the input. The default region copier has default implementations - // to handle the cases where the input and output are the same - // dimension, the input a higher dimension than the output, and the - // input a lower dimension than the output. - InputImageRegionType inputRegion; - this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion()); - input->SetRequestedRegion( inputRegion ); - } + ImagePointer outputPtr; + + outputPtr = this->GetOutput(i); + outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion()); + outputPtr->Allocate(); } + } + else + { + Superclass::AllocateOutputs(); + // copy the content of the input image to the output image (will be done by ImageSource AllocateOutputs Method) + // would never occur : inputasoutput condition is always true, since output and input type is TImage for + // LabelObjectOpeningMuParserFilter class + } +} + + +template < class TImage, class TFunction> +void LabelObjectOpeningMuParserFilter<TImage, TFunction>::GenerateInputRequestedRegion() +{ + itk::ImageToImageFilter<TImage,TImage>::GenerateInputRequestedRegion(); } diff --git a/Code/BasicFilters/otbRelabelComponentImageFilter.h b/Code/BasicFilters/otbRelabelComponentImageFilter.h index 21ae2eb688..6807e8c4c1 100644 --- a/Code/BasicFilters/otbRelabelComponentImageFilter.h +++ b/Code/BasicFilters/otbRelabelComponentImageFilter.h @@ -17,7 +17,7 @@ #ifndef __otbRelabelComponentImageFilter_h #define __otbRelabelComponentImageFilter_h -#include "itkInPlaceImageFilter.h" +#include "itkRelabelComponentImageFilter.h" #include "itkImage.h" #include <vector> @@ -72,14 +72,14 @@ namespace otb template <class TInputImage, class TOutputImage> class ITK_EXPORT RelabelComponentImageFilter : - public itk::InPlaceImageFilter< TInputImage, TOutputImage > + public itk::RelabelComponentImageFilter< TInputImage, TOutputImage > { public: /** * Standard "Self" & Superclass typedef. */ typedef RelabelComponentImageFilter Self; - typedef itk::InPlaceImageFilter< TInputImage, TOutputImage > Superclass; + typedef itk::RelabelComponentImageFilter < TInputImage, TOutputImage > Superclass; /** * Types from the Superclass @@ -124,176 +124,24 @@ public: */ itkNewMacro(Self); - /** Type used as identifier for the different component lables. */ + /** Type used as identifier for the different component labels. */ typedef unsigned long int LabelType; /** Type used to count number of pixels in objects. */ typedef unsigned long int ObjectSizeType; - /** Get the number of objects in the image. This information is only - * valid after the filter has executed. */ - itkGetConstMacro(NumberOfObjects, LabelType); - - /** Get the original number of objects in the image before small - * objects were discarded. This information is only valid after - * the filter has executed. If the caller has not specified a - * minimum object size, OriginalNumberOfObjects is the same as - * NumberOfObjects. */ - itkGetConstMacro(OriginalNumberOfObjects, LabelType); - - /** Get/Set the number of objects enumerated and described when the - * filter is printed. */ - itkSetMacro(NumberOfObjectsToPrint, LabelType); - itkGetConstReferenceMacro(NumberOfObjectsToPrint, LabelType); - - /** Set the minimum size in pixels for an object. All objects - * smaller than this size will be discarded and will not appear - * in the output label map. NumberOfObjects will count only the - * objects whose pixel counts are greater than or equal to the - * minimum size. Call GetOriginalNumberOfObjects to find out how - * many objects were present in the original label map. */ - itkSetMacro(MinimumObjectSize, ObjectSizeType); - - /** Get the caller-defined minimum size of an object in pixels. - * If the caller has not set the minimum, 0 will be returned, - * which is to be interpreted as meaning that no minimum exists, - * and all objects in the original label map will be passed - * through to the output. */ - itkGetConstMacro(MinimumObjectSize, ObjectSizeType); - - /** Get the size of each object in pixels. This information is only - * valid after the filter has executed. Size of the background is - * not calculated. Size of object #1 is - * GetSizeOfObjectsInPixels()[0]. Size of object #2 is - * GetSizeOfObjectsInPixels()[1]. Etc. */ - const std::vector<ObjectSizeType>& GetSizeOfObjectsInPixels() const - { return m_SizeOfObjectsInPixels; } - - /** Get the size of each object in physical space (in units of pixel - * size). This information is only valid after the filter has - * executed. Size of the background is not calculated. Size of - * object #1 is GetSizeOfObjectsInPhysicalUnits()[0]. Size of object - * #2 is GetSizeOfObjectsInPhysicalUnits()[1]. Etc. */ - const std::vector<float>& GetSizeOfObjectsInPhysicalUnits() const - { return m_SizeOfObjectsInPhysicalUnits; } - - /** Get the size of a particular object in pixels. This information is only - * valid after the filter has executed. Size of the background - * (object #0) is not calculated. */ - ObjectSizeType GetSizeOfObjectInPixels( LabelType obj ) const - { - if (obj > 0 && obj <= m_NumberOfObjects) - { - return m_SizeOfObjectsInPixels[obj-1]; - } - else - { - return 0; - } - } - - /** Get the size of a particular object in physical space (in units of pixel - * size). This information is only valid after the filter has - * executed. Size of the background (object #0) is not calculated. */ - float GetSizeOfObjectInPhysicalUnits( LabelType obj ) const - { - if (obj > 0 && obj <= m_NumberOfObjects) - { - return m_SizeOfObjectsInPhysicalUnits[obj-1]; - } - else - { - return 0; - } - } - -#ifdef ITK_USE_CONCEPT_CHECKING - /** Begin concept checking */ - itkConceptMacro(InputEqualityComparableCheck, - (itk::Concept::EqualityComparable<InputPixelType>)); - itkConceptMacro(UnsignedLongConvertibleToInputCheck, - (itk::Concept::Convertible<LabelType, InputPixelType>)); - itkConceptMacro(OutputLongConvertibleToUnsignedLongCheck, - (itk::Concept::Convertible<OutputPixelType, LabelType>)); - itkConceptMacro(InputConvertibleToOutputCheck, - (itk::Concept::Convertible<InputPixelType, OutputPixelType>)); - itkConceptMacro(SameDimensionCheck, - (itk::Concept::SameDimension<InputImageDimension, ImageDimension>)); - /** End concept checking */ -#endif - protected: - RelabelComponentImageFilter() - : m_NumberOfObjects(0), m_NumberOfObjectsToPrint(10), - m_OriginalNumberOfObjects(0), m_MinimumObjectSize(0) - { this->InPlaceOff(); } + RelabelComponentImageFilter(); virtual ~RelabelComponentImageFilter() {} - RelabelComponentImageFilter(const Self&) {} - /** - * Standard pipeline method. - */ - void GenerateData(); - - /** RelabelComponentImageFilter needs the entire input. Therefore - * it must provide an implementation GenerateInputRequestedRegion(). - * \sa ProcessObject::GenerateInputRequestedRegion(). */ void GenerateInputRequestedRegion(); - /** - * Initialize parameters. - */ - void Init(); - - /** Standard printself method */ - void PrintSelf(std::ostream& os, itk::Indent indent) const; - - struct RelabelComponentObjectType - { - LabelType m_ObjectNumber; - ObjectSizeType m_SizeInPixels; - float m_SizeInPhysicalUnits; - }; - - // put the function objects here for sorting in descending order - class RelabelComponentSizeInPixelsComparator - { - public: - bool operator()(const RelabelComponentObjectType&a, - const RelabelComponentObjectType &b) - { - if (a.m_SizeInPixels > b.m_SizeInPixels) - { - return true; - } - else if (a.m_SizeInPixels < b.m_SizeInPixels) - { - return false; - } - // size in pixels and physical units are the same, sort based on - // original object number - else if (a.m_ObjectNumber < b.m_ObjectNumber) - { - return true; - } - else - { - return false; - } - } - }; - + void EnlargeOutputRequestedRegion(itk::DataObject *){}; private: - - LabelType m_NumberOfObjects; - LabelType m_NumberOfObjectsToPrint; - LabelType m_OriginalNumberOfObjects; - ObjectSizeType m_MinimumObjectSize; - - std::vector<ObjectSizeType> m_SizeOfObjectsInPixels; - std::vector<float> m_SizeOfObjectsInPhysicalUnits; + RelabelComponentImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented }; diff --git a/Code/BasicFilters/otbRelabelComponentImageFilter.txx b/Code/BasicFilters/otbRelabelComponentImageFilter.txx index d2a81849e7..6d27b1193d 100644 --- a/Code/BasicFilters/otbRelabelComponentImageFilter.txx +++ b/Code/BasicFilters/otbRelabelComponentImageFilter.txx @@ -28,232 +28,22 @@ namespace otb { -template< class TInputImage, class TOutputImage > -void -RelabelComponentImageFilter< TInputImage, TOutputImage > -::GenerateInputRequestedRegion() +template <class TInputImage, class TOutputImage> +RelabelComponentImageFilter<TInputImage, TOutputImage> +::RelabelComponentImageFilter() { - - itk::ImageToImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion(); } template< class TInputImage, class TOutputImage > void RelabelComponentImageFilter< TInputImage, TOutputImage > -::GenerateData() +::GenerateInputRequestedRegion() { - unsigned long i; - - // Use a map to keep track of the size of each object. Object - // number -> ObjectType (which has Object number and the two sizes) - typedef itk::hash_map<LabelType, RelabelComponentObjectType> MapType; - MapType sizeMap; - typename MapType::iterator mapIt; - typedef typename MapType::value_type MapValueType; - - // Get the input and the output - typename TInputImage::ConstPointer input = this->GetInput(); - typename TOutputImage::Pointer output = this->GetOutput(); - - // Setup a progress reporter. We have 2 stages to the algorithm so - // use the total number of pixels accessed. We walk the entire input - // in the first pass, then walk just the output requested region in - // the second pass. - itk::ProgressReporter progress(this, 0, - input->GetRequestedRegion().GetNumberOfPixels() + - output->GetRequestedRegion().GetNumberOfPixels()); - - - // Calculate the size of pixel - float physicalPixelSize = 1.0; - for (i=0; i < TInputImage::ImageDimension; ++i) - { - physicalPixelSize *= input->GetSpacing()[i]; - } - - RelabelComponentObjectType initialSize; - initialSize.m_SizeInPixels = 1; - initialSize.m_SizeInPhysicalUnits = physicalPixelSize; - - // First pass: walk the entire input image and determine what - // labels are used and the number of pixels used in each label. - // - - // walk the input - itk::ImageRegionConstIterator<InputImageType> it(input, input->GetRequestedRegion()); - it.GoToBegin(); - - while (!it.IsAtEnd()) - { - // Get the input pixel value - const LabelType inputValue = static_cast< LabelType>( it.Get() ); - - // if the input pixel is not the background - if (inputValue != itk::NumericTraits<LabelType>::Zero) - { - // Does this label already exist - mapIt = sizeMap.find( inputValue ); - if ( mapIt == sizeMap.end() ) - { - // label is not currently in the map - initialSize.m_ObjectNumber = inputValue; - sizeMap.insert( MapValueType( inputValue, initialSize ) ); - } - else - { - // label is already in the map, update the values - (*mapIt).second.m_SizeInPixels++; - (*mapIt).second.m_SizeInPhysicalUnits += physicalPixelSize; - } - } - - // increment the iterators - ++it; - progress.CompletedPixel(); - } - - // Now we need to reorder the labels. Use the m_ObjectSortingOrder - // to determine how to sort the objects. Define a map for converting - // input labels to output labels. - // - typedef std::vector<RelabelComponentObjectType> VectorType; - VectorType sizeVector; - typename VectorType::iterator vit; - - typedef std::map< LabelType, LabelType > RelabelMapType; - RelabelMapType relabelMap; - - // copy the original object map to a vector so we can sort it - for (mapIt = sizeMap.begin(); mapIt != sizeMap.end(); ++mapIt) - { - sizeVector.push_back( (*mapIt).second ); - } - - // sort the objects by size and define the map to use to relabel the image - std::sort(sizeVector.begin(), sizeVector.end(), RelabelComponentSizeInPixelsComparator() ); - - // create a lookup table to map the input label to the output label. - // cache the object sizes for later access by the user - m_NumberOfObjects = sizeVector.size(); - m_OriginalNumberOfObjects = sizeVector.size(); - m_SizeOfObjectsInPixels.clear(); - m_SizeOfObjectsInPixels.resize(m_NumberOfObjects); - m_SizeOfObjectsInPhysicalUnits.clear(); - m_SizeOfObjectsInPhysicalUnits.resize(m_NumberOfObjects); - int NumberOfObjectsRemoved = 0; - for (i=0, vit = sizeVector.begin(); vit != sizeVector.end(); ++vit, ++i) - { - - // if we find an object smaller than the minimum size, we - // terminate the loop. - if (m_MinimumObjectSize > 0 && (*vit).m_SizeInPixels < m_MinimumObjectSize) - { - // map small objects to the background - NumberOfObjectsRemoved++; - relabelMap.insert(RelabelMapType::value_type( (*vit).m_ObjectNumber, 0)); - } - else - { - // map for input labels to output labels (Note we use i+1 in the - // map since index 0 is the background) - relabelMap.insert(RelabelMapType::value_type( (*vit).m_ObjectNumber, i+1)); - - // cache object sizes for later access by the user - m_SizeOfObjectsInPixels[i] = (*vit).m_SizeInPixels; - m_SizeOfObjectsInPhysicalUnits[i] = (*vit).m_SizeInPhysicalUnits; - } - - } - - // update number of objects and resize cache vectors if we have removed small objects - m_NumberOfObjects -= NumberOfObjectsRemoved; - if (NumberOfObjectsRemoved > 0) - { - m_SizeOfObjectsInPixels.resize(m_NumberOfObjects); - m_SizeOfObjectsInPhysicalUnits.resize(m_NumberOfObjects); - } - - // Second pass: walk just the output requested region and relabel - // the necessary pixels. - // - - // Allocate the output - this->AllocateOutputs(); - - // Remap the labels. Note we only walk the region of the output - // that was requested. This may be a subset of the input image. - OutputPixelType outputValue; - itk::ImageRegionIterator<OutputImageType> oit; - oit = itk::ImageRegionIterator<OutputImageType>(output, - output->GetRequestedRegion()); - it = itk::ImageRegionConstIterator<InputImageType>(input, - output->GetRequestedRegion()); - - it.GoToBegin(); - oit.GoToBegin(); - while ( !oit.IsAtEnd() ) - { - const LabelType inputValue = static_cast< LabelType>( it.Get() ); - - if (inputValue != itk::NumericTraits<LabelType>::Zero) - { - - // lookup the mapped label - outputValue = static_cast<OutputPixelType>(relabelMap[inputValue]); - oit.Set( outputValue ); - } - else - { - oit.Set( inputValue ); - } - - // increment the iterators - ++it; - ++oit; - progress.CompletedPixel(); - } + itk::ImageToImageFilter<TInputImage,TOutputImage>::GenerateInputRequestedRegion(); } -template< class TInputImage, class TOutputImage > -void -RelabelComponentImageFilter< TInputImage, TOutputImage > -::PrintSelf(std::ostream& os, itk::Indent indent) const -{ - Superclass::PrintSelf(os, indent); - - os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl; - os << indent << "OriginalNumberOfObjects: " << m_OriginalNumberOfObjects << std::endl; - os << indent << "NumberOfObjectsToPrint: " - << m_NumberOfObjectsToPrint << std::endl; - os << indent << "MinimumObjectSizez: " << m_MinimumObjectSize << std::endl; - - std::vector<ObjectSizeType>::const_iterator it; - std::vector<float>::const_iterator fit; - LabelType i; - - // limit the number of objects to print - LabelType numPrint = m_NumberOfObjectsToPrint; - if (numPrint > m_SizeOfObjectsInPixels.size()) - { - numPrint = m_SizeOfObjectsInPixels.size(); - } - - - for (i=0, it = m_SizeOfObjectsInPixels.begin(), - fit = m_SizeOfObjectsInPhysicalUnits.begin(); - i < numPrint; ++it, ++fit, ++i) - { - os << indent << "Object #" << i+1 << ": " << *it << " pixels, " - << *fit << " physical units" << std::endl; - } - if (numPrint < m_SizeOfObjectsInPixels.size()) - { - os << indent << "..." << std::endl; - } -} - -} // end namespace itk +} // end namespace otb #endif diff --git a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h index 501e230e82..19bd205a21 100644 --- a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h +++ b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h @@ -186,6 +186,8 @@ protected: /** Destructor */ ~BandsStatisticsAttributesLabelMapFilter() {} + virtual void AllocateOutputs(); + void GenerateInputRequestedRegion(); void EnlargeOutputRequestedRegion(itk::DataObject *){}; diff --git a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx index 64a34e798f..e6bd417c7e 100644 --- a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx +++ b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx @@ -210,34 +210,58 @@ BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage> return this->GetFunctor().GetReducedAttributeSet(); } + template <class TImage, class TFeatureImage> void BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage> -::GenerateInputRequestedRegion() -{ +::AllocateOutputs() + { + // if told to run in place and the types support it, + if( this->GetInPlace() && this->CanRunInPlace() ) + { + // Graft this first input to the output. Later, we'll need to + // remove the input's hold on the bulk data. + // + ImagePointer inputAsOutput = dynamic_cast<TImage *>(const_cast<TImage *>(this->GetInput())); - for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx) + if( inputAsOutput ) { - ImagePointer input = const_cast<ImageType *>(this->GetInput(idx)); - if (!input.IsNull()) - { - input->SetRequestedRegionToLargestPossibleRegion(); - // Check whether the input is an image of the appropriate - // dimension (use ProcessObject's version of the GetInput() - // method since it returns the input as a pointer to a - // DataObject as opposed to the subclass version which - // static_casts the input to an TInputImage). - - // Use the function object RegionCopier to copy the output region - // to the input. The default region copier has default implementations - // to handle the cases where the input and output are the same - // dimension, the input a higher dimension than the output, and the - // input a lower dimension than the output. - InputImageRegionType inputRegion; - this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion()); - input->SetRequestedRegion( inputRegion ); - } + + this->GraftOutput( inputAsOutput ); + this->GetOutput()->SetLargestPossibleRegion(this->GetOutput()->GetLargestPossibleRegion()); + this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion()); + this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetBufferedRegion()); + } + + // If there are more than one outputs, allocate the remaining outputs + for (unsigned int i=1; i < this->GetNumberOfOutputs(); i++) + { + ImagePointer outputPtr; + + outputPtr = this->GetOutput(i); + outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion()); + outputPtr->Allocate(); + } + } + else + { + // + + Superclass::AllocateOutputs(); + // copy the content of the input image to the output image (will be done by ImageSource AllocateOutputs Method) + // would never occur : inputasoutput condition is always true, since output and input type is TImage for + // BandsStatisticsAttributesLabelMapFilter class + } +} + + +template <class TImage, class TFeatureImage> +void +BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage> +::GenerateInputRequestedRegion() +{ + itk::ImageToImageFilter<TImage,TImage>::GenerateInputRequestedRegion(); } @@ -281,5 +305,5 @@ BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage> Superclass::PrintSelf(os, indent); } -} // end namespace itk +} // end namespace otb #endif diff --git a/Code/OBIA/otbLabelMapToLabelImageFilter.txx b/Code/OBIA/otbLabelMapToLabelImageFilter.txx index 8eff1966a8..5bd3a8886f 100644 --- a/Code/OBIA/otbLabelMapToLabelImageFilter.txx +++ b/Code/OBIA/otbLabelMapToLabelImageFilter.txx @@ -35,34 +35,8 @@ void LabelMapToLabelImageFilter<TInputImage, TOutputImage> ::GenerateInputRequestedRegion() { - - - for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx) - { - InputImagePointer input = const_cast<InputImageType *>(this->GetInput(idx)); - if (!input.IsNull()) - { - input->SetRequestedRegionToLargestPossibleRegion(); - // Check whether the input is an image of the appropriate - // dimension (use ProcessObject's version of the GetInput() - // method since it returns the input as a pointer to a - // DataObject as opposed to the subclass version which - // static_casts the input to an TInputImage). - - // Use the function object RegionCopier to copy the output region - // to the input. The default region copier has default implementations - // to handle the cases where the input and output are the same - // dimension, the input a higher dimension than the output, and the - // input a lower dimension than the output. - InputImageRegionType inputRegion; - this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion()); - input->SetRequestedRegion( inputRegion ); - } - } - - + itk::ImageToImageFilter<TInputImage,TOutputImage>::GenerateInputRequestedRegion(); } - }// end namespace otb #endif diff --git a/Code/OBIA/otbShapeAttributesLabelMapFilter.h b/Code/OBIA/otbShapeAttributesLabelMapFilter.h index ed4b358604..6a554901ca 100644 --- a/Code/OBIA/otbShapeAttributesLabelMapFilter.h +++ b/Code/OBIA/otbShapeAttributesLabelMapFilter.h @@ -205,6 +205,7 @@ public: typedef itk::SmartPointer<const Self> ConstPointer; typedef typename ImageType::Pointer ImagePointer; + /** ImageDimension constants */ itkStaticConstMacro(ImageDimension, unsigned int, TImage::ImageDimension); @@ -258,6 +259,8 @@ protected: /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const; + virtual void AllocateOutputs(); + /** Things to to before threaded data generation */ virtual void BeforeThreadedGenerateData(); diff --git a/Code/OBIA/otbShapeAttributesLabelMapFilter.txx b/Code/OBIA/otbShapeAttributesLabelMapFilter.txx index dc9ebbec33..f541524d15 100644 --- a/Code/OBIA/otbShapeAttributesLabelMapFilter.txx +++ b/Code/OBIA/otbShapeAttributesLabelMapFilter.txx @@ -834,33 +834,52 @@ ShapeAttributesLabelMapFilter<TImage, TLabelImage> template <class TImage, class TLabelImage> void ShapeAttributesLabelMapFilter<TImage, TLabelImage> -::GenerateInputRequestedRegion() -{ +::AllocateOutputs() + { + // if told to run in place and the types support it, + if( this->GetInPlace() && this->CanRunInPlace() ) + { + // Graft this first input to the output. Later, we'll need to + // remove the input's hold on the bulk data. + // + ImagePointer inputAsOutput = dynamic_cast<TImage *>(const_cast<TImage *>(this->GetInput())); - for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx) + if( inputAsOutput ) { - ImagePointer input = const_cast<ImageType *>(this->GetInput(idx)); - if (!input.IsNull()) - { - input->SetRequestedRegionToLargestPossibleRegion(); - // Check whether the input is an image of the appropriate - // dimension (use ProcessObject's version of the GetInput() - // method since it returns the input as a pointer to a - // DataObject as opposed to the subclass version which - // static_casts the input to an TInputImage). - - // Use the function object RegionCopier to copy the output region - // to the input. The default region copier has default implementations - // to handle the cases where the input and output are the same - // dimension, the input a higher dimension than the output, and the - // input a lower dimension than the output. - InputImageRegionType inputRegion; - this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion()); - input->SetRequestedRegion( inputRegion ); - } + + this->GraftOutput( inputAsOutput ); + this->GetOutput()->SetLargestPossibleRegion(this->GetOutput()->GetLargestPossibleRegion()); + this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion()); + this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetBufferedRegion()); + } + // If there are more than one outputs, allocate the remaining outputs + for (unsigned int i=1; i < this->GetNumberOfOutputs(); i++) + { + ImagePointer outputPtr; + + outputPtr = this->GetOutput(i); + outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion()); + outputPtr->Allocate(); + } + } + else + { + // + Superclass::AllocateOutputs(); + // copy the content of the input image to the output image (will be done by ImageSource AllocateOutputs Method) + // would never occur : inputasoutput condition is always true, since output and input type is TImage for + // ShapeAttributesLabelMapFilter class + } +} +template <class TImage, class TLabelImage> +void +ShapeAttributesLabelMapFilter<TImage, TLabelImage> +::GenerateInputRequestedRegion() +{ + itk::ImageToImageFilter<TImage,TImage>::GenerateInputRequestedRegion(); } -- GitLab