From f1908566cf3af73f5dc931941b6f3269b9d4c0f7 Mon Sep 17 00:00:00 2001 From: Gregoire Mercier <gregoire.mercier@telecom-bretagne.eu> Date: Mon, 13 Apr 2009 14:36:22 +0200 Subject: [PATCH] ADD: directional subsampling in otbSubsampledImageRegionConstIterator --- Code/BasicFilters/otbSubsampleImageFilter.h | 18 +++++-- Code/BasicFilters/otbSubsampleImageFilter.txx | 47 +++++++++++++------ .../otbSubsampledImageRegionConstIterator.h | 44 ++++++++++------- .../otbSubsampledImageRegionConstIterator.txx | 12 +++-- Code/IO/otbImageSeriesFileReader.h | 6 ++- Code/MultiScale/otbStationaryFilterBank.h | 3 ++ 6 files changed, 88 insertions(+), 42 deletions(-) diff --git a/Code/BasicFilters/otbSubsampleImageFilter.h b/Code/BasicFilters/otbSubsampleImageFilter.h index 4e2e7a4dd9..d733edb289 100644 --- a/Code/BasicFilters/otbSubsampleImageFilter.h +++ b/Code/BasicFilters/otbSubsampleImageFilter.h @@ -75,6 +75,7 @@ public: typedef TInputImage InputImageType; typedef typename InputImageType::RegionType InputImageRegionType; typedef typename InputImageType::IndexType InputImageIndexType; + typedef typename InputImageIndexType::IndexValueType InputImageIndexValueType; typedef TOutputImage OutputImageType; typedef typename OutputImageType::RegionType OutputImageRegionType; @@ -83,16 +84,25 @@ public: typedef typename OutputImageType::PixelType OutputPixelType; /** Set/Get the SubsampleFactor */ - itkGetMacro(SubsampleFactor,unsigned int); - itkSetMacro(SubsampleFactor,unsigned int); + itkGetMacro(SubsampleFactor,const InputImageIndexType &); + itkSetMacro(SubsampleFactor,InputImageIndexType &); + void SetSubSampleFactor( InputImageIndexValueType factor ) + { + InputImageIndexType indexFactor; + indexFactor.Fill( factor ); + SetSubSampleFactor( indexFactor ); + } protected: SubsampleImageFilter () { - m_SubsampleFactor = 1; + m_SubsampleFactor.Fill( 1 ); } virtual ~SubsampleImageFilter() {} + /** Internal test function to check if there is any direction to subsample */ + bool IsSubsampleFactorOne () const; + /** Since input and output image are very likely to be of different size. * Region estimation functions has to be reimplemented */ @@ -116,7 +126,7 @@ private: SubsampleImageFilter ( const Self & ); // purposely not implemented void operator= ( const Self & ); // purposely not implemented - unsigned int m_SubsampleFactor; + InputImageIndexType m_SubsampleFactor; }; // end of class } // end of namespace otb diff --git a/Code/BasicFilters/otbSubsampleImageFilter.txx b/Code/BasicFilters/otbSubsampleImageFilter.txx index 01eba921ee..1c6259c91e 100644 --- a/Code/BasicFilters/otbSubsampleImageFilter.txx +++ b/Code/BasicFilters/otbSubsampleImageFilter.txx @@ -40,7 +40,27 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation > ::PrintSelf( std::ostream & os, itk::Indent indent ) const { Superclass::PrintSelf( os, indent ); - os << indent << "SubsampleFactor = " << m_SubsampleFactor << "\n"; + os << indent << "SubsampleFactor = [" << m_SubsampleFactor[0]; + for ( unsigned int i = 1; i < InputImageDimension; i++ ) + { + os << ", " << m_SubsampleFactor[i]; + } + os << "]\n"; +} + +template < class TInputImage, class TOutputImage, + InverseOrForwardTransformationEnum TDirectionOfTransformation > +bool +SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation > +::IsSubsampleFactorOne () const +{ + for ( unsigned int i = 0; i < InputImageDimension; i++ ) + { + if ( m_SubsampleFactor[i] != 1 ) + return false; + } + + return true; } template < class TInputImage, class TOutputImage, @@ -51,7 +71,7 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation > { Superclass::GenerateOutputInformation(); - if ( GetSubsampleFactor() > 1 ) + if ( !IsSubsampleFactorOne() ) { OutputImageRegionType newRegion; this->CallCopyInputRegionToOutputRegion( newRegion, this->GetInput()->GetLargestPossibleRegion() ); @@ -78,8 +98,8 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation > for ( unsigned int i = 0; i < InputImageDimension; i++ ) { - destIndex[i] = srcIndex[i] / GetSubsampleFactor(); - destSize[i] = ( srcSize[i] - 1 ) / GetSubsampleFactor() + 1; + destIndex[i] = srcIndex[i] / m_SubsampleFactor[i]; + destSize[i] = ( srcSize[i] - 1 ) / m_SubsampleFactor[i] + 1; } destRegion.SetIndex( destIndex ); @@ -106,8 +126,8 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation > for ( unsigned int i = 0; i < InputImageDimension; i++ ) { - destIndex[i] = srcIndex[i] * GetSubsampleFactor(); - destSize[i] = ( srcSize[i] - 1 ) * GetSubsampleFactor() + 1; + destIndex[i] = srcIndex[i] * m_SubsampleFactor[i]; + destSize[i] = ( srcSize[i] - 1 ) * m_SubsampleFactor[i] + 1; } destRegion.SetIndex( destIndex ); @@ -122,19 +142,16 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation > ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId) { + SubsampledImageRegionIterator< OutputImageType > outputIter + ( this->GetOutput(), outputRegionForThread ); + outputIter.SetSubsampleFactor(1); + outputIter.GoToBegin(); + InputImageRegionType inputRegionForThread; this->CallCopyOutputRegionToInputRegion( inputRegionForThread, outputRegionForThread ); SubsampledImageRegionConstIterator< InputImageType > inputIter ( this->GetInput(), inputRegionForThread ); - inputIter.SetSubsampleFactor( static_cast<int>( DirectionOfTransformation ) == FORWARD ? - GetSubsampleFactor() : 1 ); - inputIter.GoToBegin(); - - SubsampledImageRegionIterator< OutputImageType > outputIter - ( this->GetOutput(), outputRegionForThread ); - outputIter.SetSubsampleFactor(1); - outputIter.GoToBegin(); switch ( DirectionOfTransformation ) { @@ -164,7 +181,7 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation > OutputImageIndexType outputIndex; for ( unsigned int i = 0; i < OutputImageDimension; i++ ) { - outputIndex[i] = inputIndex[i] * GetSubsampleFactor(); + outputIndex[i] = inputIndex[i] * m_SubsampleFactor[i]; } outputIter.SetLocation( outputIndex ); outputIter.Set( static_cast< OutputPixelType >( inputIter.Get() ) ); diff --git a/Code/Common/otbSubsampledImageRegionConstIterator.h b/Code/Common/otbSubsampledImageRegionConstIterator.h index c1bfa8cf68..cf33939be5 100644 --- a/Code/Common/otbSubsampledImageRegionConstIterator.h +++ b/Code/Common/otbSubsampledImageRegionConstIterator.h @@ -32,6 +32,8 @@ namespace otb { * scan over an image. It runs one pixel over X (in row, line, slice... dimensions), * if X is the (integer) value of the SubsampleFactor. * + * Specific value of the subsample factor may be given for each dimension. + * * \ingroup ImageIterator * \sa StationaryFilterBank */ @@ -97,7 +99,7 @@ public: /** Default constructor. Needed since we provide a cast constructor. */ SubsampledImageRegionConstIterator() : itk::ImageRegionConstIterator<TImage> () { - m_SubsampleFactor = 1; + m_SubsampleFactor.Fill(1); m_SubSampledEndOffset = this->m_EndOffset; const IndexType& startIndex = this->m_Region.GetIndex(); @@ -115,7 +117,7 @@ public: const RegionType ®ion) : itk::ImageRegionConstIterator< TImage > ( ptr, region ) { - m_SubsampleFactor = 1; + m_SubsampleFactor.Fill( 1 ); m_SubSampledEndOffset = this->m_EndOffset; const IndexType& startIndex = this->m_Region.GetIndex(); @@ -136,7 +138,7 @@ public: SubsampledImageRegionConstIterator( const itk::ImageIterator<TImage> &it ) : itk::ImageRegionConstIterator< TImage >( it ) { - m_SubsampleFactor = 1; + m_SubsampleFactor.Fill( 1 ); m_SubSampledEndOffset = this->m_EndOffset; const IndexType& startIndex = this->m_Region.GetIndex(); @@ -157,7 +159,7 @@ public: SubsampledImageRegionConstIterator( const itk::ImageConstIterator<TImage> &it) : itk::ImageRegionConstIterator< TImage >( it ) { - m_SubsampleFactor = 1; + m_SubsampleFactor.Fill( 1 ); const IndexType& startIndex = this->m_Region.GetIndex(); const SizeType& size = this->m_Region.GetSize(); @@ -170,8 +172,16 @@ public: m_SubSampledEndOffset = this->m_Image->ComputeOffset( m_LastUsableIndex ) + 1; } + /** Set an isotropic subsampling factor */ + void SetSubsampleFactor ( typename IndexType::IndexValueType factor ) + { + IndexType index; + index.Fill( factor ); + SetSubsampleFactor( index ); + } + /** Set / Get the subsample factor */ - void SetSubsampleFactor ( unsigned int factor ) + void SetSubsampleFactor ( const IndexType & factor ) { this->m_SubsampleFactor = factor; @@ -182,13 +192,13 @@ public: for ( unsigned int i = 0; i < ImageIteratorDimension; i++ ) { m_LastUsableIndex[i] = startIndex[i] - + static_cast<IndexValueType>( m_SubsampleFactor * ( (size[i]-1) / m_SubsampleFactor ) ); + + static_cast<IndexValueType>( m_SubsampleFactor[i] * ( (size[i]-1) / m_SubsampleFactor[i] ) ); } m_SubSampledEndOffset = this->m_Image->ComputeOffset( m_LastUsableIndex ) + 1; } - unsigned int GetSubsampleFactor () const + const IndexType & GetSubsampleFactor () const { return this->m_SubsampleFactor; } @@ -203,7 +213,7 @@ public: this->m_SpanBeginOffset = this->m_Offset; this->m_SpanEndOffset = this->m_Offset - + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) ) + + static_cast<IndexValueType>( m_SubsampleFactor[0] * ((size[0]-1) / m_SubsampleFactor[0]) ) + 1; } @@ -259,14 +269,14 @@ public: { // On the contrary to itk::ImageRegionConstIterator, m_Offset to // not incremented before the test - if( this->m_Offset + m_SubsampleFactor >= this->m_SpanEndOffset ) + if( this->m_Offset + m_SubsampleFactor[0] >= this->m_SpanEndOffset ) { this->Increment(); } else { // Now, the increment is performed - this->m_Offset += m_SubsampleFactor; + this->m_Offset += m_SubsampleFactor[0]; } return *this; } @@ -282,14 +292,14 @@ public: { // On the contrary to itk::ImageRegionConstIterator, m_Offset // is not decremented here (it may become negative!) - if ( this->m_Offset < this->m_SpanBeginOffset + m_SubsampleFactor ) + if ( this->m_Offset < this->m_SpanBeginOffset + m_SubsampleFactor[0] ) { this->Decrement(); } else { // Now we can - this->m_Offset -= m_SubsampleFactor; + this->m_Offset -= m_SubsampleFactor[0]; } return *this; } @@ -303,7 +313,7 @@ public: const SizeType& size = this->m_Region.GetSize(); this->m_SpanEndOffset = this->m_Offset - + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) ) + + static_cast<IndexValueType>( m_SubsampleFactor[0] * ((size[0]-1) / m_SubsampleFactor[0]) ) + 1; this->m_SpanBeginOffset = this->m_Offset; } @@ -314,7 +324,7 @@ public: const SizeType& size = this->m_Region.GetSize(); this->m_SpanEndOffset = this->m_Offset - + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) ) + + static_cast<IndexValueType>( m_SubsampleFactor[0] * ((size[0]-1) / m_SubsampleFactor[0]) ) + 1; this->m_SpanBeginOffset = this->m_Offset; } @@ -339,9 +349,9 @@ public: for ( unsigned int i = 0; i < ImageIteratorDimension; i++ ) { - startIndex[i] /= m_SubsampleFactor; + startIndex[i] /= m_SubsampleFactor[i]; --size[i]; - size[i] /= m_SubsampleFactor; + size[i] /= m_SubsampleFactor[i]; ++size[i]; } @@ -359,7 +369,7 @@ public: } protected: - unsigned int m_SubsampleFactor; + IndexType m_SubsampleFactor; unsigned long m_SubSampledEndOffset; IndexType m_LastUsableIndex; diff --git a/Code/Common/otbSubsampledImageRegionConstIterator.txx b/Code/Common/otbSubsampledImageRegionConstIterator.txx index 57755008f5..51d1792836 100644 --- a/Code/Common/otbSubsampledImageRegionConstIterator.txx +++ b/Code/Common/otbSubsampledImageRegionConstIterator.txx @@ -42,7 +42,7 @@ SubsampledImageRegionConstIterator< TImage > // Check to see if we are past the last pixel in the region // Note that ++ind[0] moves to the next pixel along the row. - ind[0] += static_cast<IndexValueType>(m_SubsampleFactor); + ind[0] += m_SubsampleFactor[0]; bool done = (ind[0] > m_LastUsableIndex[0] ); for (unsigned int i=1; done && i < ImageIteratorDimension; i++) { @@ -58,12 +58,13 @@ SubsampledImageRegionConstIterator< TImage > && (ind[dim] > m_LastUsableIndex[dim]) ) { ind[dim] = startIndex[dim]; - ind[++dim] += static_cast<IndexValueType>(m_SubsampleFactor); + dim++; + ind[dim] += m_SubsampleFactor[dim]; } } this->m_Offset = this->m_Image->ComputeOffset( ind ); this->m_SpanEndOffset = this->m_Offset - + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) ) + + static_cast<IndexValueType>( m_SubsampleFactor[0] * ((size[0]-1) / m_SubsampleFactor[0]) ) + 1; this->m_SpanBeginOffset = this->m_Offset; } @@ -83,7 +84,7 @@ SubsampledImageRegionConstIterator< TImage > // Check to see if we are past the first pixel in the region // Note that --ind[0] moves to the previous pixel along the row. - ind[0] -= static_cast< IndexValueType >( m_SubsampleFactor ); + ind[0] -= m_SubsampleFactor[0]; done = (ind[0] <= startIndex[0] - 1); for (unsigned int i=1; done && i < ImageIteratorDimension; i++) { @@ -99,7 +100,8 @@ SubsampledImageRegionConstIterator< TImage > && (ind[dim] < startIndex[dim]) ) { ind[dim] = m_LastUsableIndex[dim]; - ind[++dim] -= static_cast<IndexValueType>( m_SubsampleFactor ); + dim++; + ind[dim] -= m_SubsampleFactor[dim]; } } this->m_Offset = this->m_Image->ComputeOffset( ind ); diff --git a/Code/IO/otbImageSeriesFileReader.h b/Code/IO/otbImageSeriesFileReader.h index 538c15fb14..7f4ac334f2 100644 --- a/Code/IO/otbImageSeriesFileReader.h +++ b/Code/IO/otbImageSeriesFileReader.h @@ -35,7 +35,11 @@ namespace otb { /** * \class ImagerSeriesFileReader - * \brief Todo + * \brief Reader class dedicated to image series reading + * + * Actually, this class is mostly dedicated to read ENVI META FILE. Specialisations + * of the template are given relatively to the king of image (or vector image) used + * in input and/or output. * * * \see ImageFileReader diff --git a/Code/MultiScale/otbStationaryFilterBank.h b/Code/MultiScale/otbStationaryFilterBank.h index 7c28379130..07b4239aec 100644 --- a/Code/MultiScale/otbStationaryFilterBank.h +++ b/Code/MultiScale/otbStationaryFilterBank.h @@ -72,6 +72,9 @@ namespace otb { * At this step, it would have been interesting to implements a DirectionalInnerProductImageFilter to synchronize * the pipeline through a composite filter * + * The two choice (FORWARD/INVERSE) yield specific implementation of the templates (header redeclaration + * is given at bottom of of otbFilterBank.h + * * \sa LowPassHaarOperator * \sa HighPassHaarOperator * \sa LowPassSplineBiOrthogonalOperator -- GitLab