Skip to content
Snippets Groups Projects
Forked from Main Repositories / otb
33541 commits behind the upstream repository.
otbLogPolarResampleImageFilter.txx 12.94 KiB
/*=========================================================================

  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 _otbLogPolarResampleImageFilter_txx
#define _otbLogPolarResampleImageFilter_txx

#include "otbLogPolarResampleImageFilter.h"
#include "itkObjectFactory.h"
#include "itkIdentityTransform.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkProgressReporter.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkImageLinearIteratorWithIndex.h"
#include "itkSpecialCoordinatesImage.h"

namespace otb
{

/**
 * Initialize new instance
 */
template <class TInputImage,  class TInterpolator>
LogPolarResampleImageFilter<TInputImage, TInterpolator>
::LogPolarResampleImageFilter()
{
  m_RadialNumberOfSamples  = 128;
  m_AngularNumberOfSamples = 128;
  
  m_RadialStep  = 1.0;
  m_AngularStep = 1.0;    

  m_AngularStepIsConfigured = false;
  m_RadialStepIsConfigured  = false;


  m_OriginIsAtCenter  = true;
  m_DefaultPixelValue = 0;
  m_Sigma             = 0.5;
  
  m_Interpolator      = itk::LinearInterpolateImageFunction<InputImageType, CoordRepType>::New();
  
}

/**
 * Print out a description of self
 *
 */
template <class TInputImage, class TInterpolator>
void 
LogPolarResampleImageFilter<TInputImage, TInterpolator>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
  Superclass::PrintSelf(os,indent);
  os << indent << "m_RadialStep: " << m_RadialStep << std::endl;
  os << indent << "m_AngularStep: " << m_AngularStep << std::endl;
  os << indent << "m_RadialNumberOfSamples: " << m_RadialNumberOfSamples << std::endl;
  os << indent << "m_AngularNumberOfSamples: " << m_AngularNumberOfSamples << std::endl;
  os << indent << "m_OriginIsAtCenter: " << (m_OriginIsAtCenter ? "On" : "Off") << std::endl;
  os << indent << "m_DefaultPixelValue: " << m_DefaultPixelValue << std::endl;
  os << indent << "m_Interpolator: " << m_Interpolator.GetPointer() << std::endl;
 
  return;
}



/**
 * Set up state of filter before multi-threading.
 * InterpolatorType::SetInputImage is not thread-safe and hence
 * has to be set up before ThreadedGenerateData
 */
template <class TInputImage, class TInterpolator>
void 
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::BeforeThreadedGenerateData()
{

  if( !m_Interpolator )
    {
    itkExceptionMacro(<< "Interpolator not set"<<std::endl);
    }

  // Connect input image to interpolator
  m_Interpolator->SetInputImage( this->GetInput() );

}


/**
 * Set up state of filter after multi-threading.
 */
template <class TInputImage, class TInterpolator>
void 
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::AfterThreadedGenerateData()
{
  // Disconnect input image from the interpolator
  m_Interpolator->SetInputImage( NULL );

}

/**
 * ThreadedGenerateData
 */
template <class TInputImage, class TInterpolator>
void 
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::ThreadedGenerateData(
  const OutputImageRegionType& outputRegionForThread,
  int threadId)
{
  // Get the output pointers
  OutputImagePointer      outputPtr = this->GetOutput();

  // Get ths input pointers
  InputImageConstPointer inputPtr=this->GetInput();

  // Create an iterator that will walk the output region for this thread.
  typedef itk::ImageRegionIteratorWithIndex<TInputImage> OutputIterator;

  OutputIterator outIt(outputPtr, outputRegionForThread);

  // Define a few indices that will be used to translate from an input pixel
  // to an output pixel
  PointType outputPoint;         // Coordinates of current output pixel
  PointType inputPoint;          // Coordinates of current input pixel

  typedef itk::ContinuousIndex<CoordRepType, OutputImageDimension> ContinuousIndexType;
  ContinuousIndexType inputIndex;

  // Support for progress methods/callbacks
  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
        
  typedef typename InterpolatorType::OutputType OutputType;

  // Min/max values of the output pixel type AND these values
  // represented as the output type of the interpolator
  const OutputPixelType minOutputValue =  itk::NumericTraits<OutputPixelType >::NonpositiveMin();
  const OutputPixelType maxOutputValue =  itk::NumericTraits<OutputPixelType >::max();

  // Walk the output region
  outIt.GoToBegin();

  while ( !outIt.IsAtEnd() )
    {
    // Determine the index of the current output pixel
    outputPtr->TransformIndexToPhysicalPoint( outIt.GetIndex(), outputPoint );

    // Compute corresponding input pixel position
    double Theta = outputPoint[0]*m_AngularStep*acos(-1.0)/180.0;
    double Rho   = outputPoint[1]*m_RadialStep;

    inputPoint[0] = exp(Rho) * cos(Theta);
    inputPoint[1] = exp(Rho) * sin(Theta);
  
    if(m_OriginIsAtCenter == true)
      {
      inputPoint[0] += inputPtr->GetLargestPossibleRegion().GetSize()[0]/2.;
      inputPoint[1] += inputPtr->GetLargestPossibleRegion().GetSize()[1]/2.;
      }
    
     
    inputPtr->TransformPhysicalPointToContinuousIndex(inputPoint, inputIndex);

    
    // Evaluate input at right position and copy to the output
    if( m_Interpolator->IsInsideBuffer(inputIndex) )
      {
      OutputPixelType pixval;
      double valueTemp = static_cast<double>(m_Interpolator->EvaluateAtContinuousIndex(inputIndex) );
      valueTemp *= exp(m_Sigma * Rho);
      valueTemp *= m_RadialStep; 
      OutputPixelType value = static_cast<OutputPixelType>(valueTemp);
      
      if( value < minOutputValue )
        {
        pixval = minOutputValue;
        }
      else if( value > maxOutputValue )
        {
        pixval = maxOutputValue;
        }
      else 
        {
        pixval = static_cast<OutputPixelType>( value );
        }
      outIt.Set( pixval );      
      }
    else
      {
      outIt.Set(m_DefaultPixelValue); // default background value
      }
    progress.CompletedPixel();
    ++outIt;
    }

  return;
  
}




/** 
 * Inform pipeline of necessary input image region
 *
 * Determining the actual input region is non-trivial, especially
 * when we cannot assume anything about the transform being used.
 * So we do the easy thing and request the entire input image.
 */
template <class TInputImage, class TInterpolator>
void 
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::GenerateInputRequestedRegion()
{
  // call the superclass's implementation of this method
  Superclass::GenerateInputRequestedRegion();

  if ( !this->GetInput() )
    {
    return;
    }

  // get pointers to the input and output
  InputImagePointer  inputPtr  = 
    const_cast< TInputImage *>( this->GetInput() );

  // Request the entire input image
  InputImageRegionType inputRegion;
  inputRegion = inputPtr->GetLargestPossibleRegion();
  inputPtr->SetLargestPossibleRegion(inputRegion);
  inputPtr->SetRequestedRegion(inputRegion);

  return;
}


/** 
 * Inform pipeline of required output region
 */
template <class TInputImage, class TInterpolator>
void 
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::GenerateOutputInformation()
{
  // call the superclass' implementation of this method
  Superclass::GenerateOutputInformation();

  // get pointers to the input and output
  InputImagePointer  inputPtr  = const_cast< TInputImage *>( this->GetInput() );
  OutputImagePointer outputPtr = this->GetOutput();
  if ( !inputPtr )
    {
    return;
    }
    
  if(m_RadialStepIsConfigured == true)
    {
    std::cout << "1" << std::endl;
    CalculateRadialNumberOfSamples();
    }  
    else
    {
    std::cout << "2" << std::endl;
    CalculateRadialStep();
    }      

  if(m_AngularStepIsConfigured == true)
    {
    std::cout << "3" << std::endl;
    CalculateAngularNumberOfSamples();
    }  
    else
    {
    std::cout << "4" << std::endl;
    CalculateAngularStep();
    }      


  SizeType                Size;                // Size of the output image
  
  Size[0] = static_cast<SizeValueType>(m_AngularNumberOfSamples);
  Size[1] = static_cast<SizeValueType>(m_RadialNumberOfSamples);

  std::cout << "Size : " << Size << std::endl;
  
  OutputImageRegionType    outputLargestPossibleRegion;
  outputLargestPossibleRegion.SetSize( Size );
  outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );

  return;
}



/** 
 * Verify if any of the components has been modified.
 */
template <class TInputImage, class TInterpolator>
unsigned long 
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::GetMTime( void ) const
{
  unsigned long latestTime = itk::Object::GetMTime(); 


  if( m_Interpolator )
    {
    if( latestTime < m_Interpolator->GetMTime() )
      {
      latestTime = m_Interpolator->GetMTime();
      }
    }

  return latestTime;
}


template <class TInputImage, class TInterpolator>
void
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::CalculateRadialNumberOfSamples()
{

  // get pointers to the input and output
  InputImagePointer  inputPtr  = const_cast< TInputImage *>( this->GetInput() );

  if ( !inputPtr )
    {
    return;
    }
  
  SizeType                Size;                // Size of the output image
  Size = inputPtr->GetLargestPossibleRegion().GetSize();

  double Radial_max = sqrt(Size[0]*Size[0]+Size[1]*Size[1]);
  if(m_OriginIsAtCenter == true)
    {
    Radial_max /= 2.0;
    }    
  if( m_RadialStep <=0. )
    {
    itkExceptionMacro(<< "LogPolarResampleImageFilter::CalculateRadialNumberOfSamples() m_RadialStep must be greater than zero: " <<std::endl);
    }
  m_RadialNumberOfSamples = log(Radial_max) / m_RadialStep;

  double bx = log(m_RadialNumberOfSamples) / log(2.0);
  if(int(bx)!=bx)
    {
     m_RadialNumberOfSamples = pow(2,int(bx)+1);
    }  	
}

template <class TInputImage, class TInterpolator>
void
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::CalculateAngularNumberOfSamples()
{
  double Angular_max = 90.0; 
  if(m_OriginIsAtCenter == true)
    {
    Angular_max = 360.0;
    }

  if( m_RadialStep <=0.0 )
    {
    itkExceptionMacro(<< "LogPolarResampleImageFilter::CalculateAngularNumberOfSamples() m_RadialStep must be greater than zero"<<std::endl);
    }

  m_AngularNumberOfSamples = Angular_max / m_AngularStep;

  double by = log(m_AngularNumberOfSamples) / log(2.0);
  if(int(by)!=by)
    {
     m_AngularNumberOfSamples = pow(2,int(by)+1);
    }
}

template <class TInputImage, class TInterpolator>
void
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::CalculateRadialStep()
{
  // get pointers to the input and output
  InputImagePointer  inputPtr  = const_cast< TInputImage *>( this->GetInput() );

  SizeType                Size;                // Size of the output image
  Size = inputPtr->GetLargestPossibleRegion().GetSize();

  if( m_RadialNumberOfSamples <1 )
    {
    itkExceptionMacro(<< "LogPolarResampleImageFilter::CalculateRadialStep() m_RadialNumberOfSamples must be greater than one"<<std::endl);
    }

  double by = log(m_RadialNumberOfSamples) / log(2.0);
  if(int(by)!=by)
    {
     m_RadialNumberOfSamples = pow(2,int(by)+1);
    }

  double Radial_max = sqrt(Size[0]*Size[0]+Size[1]*Size[1]);
  if(m_OriginIsAtCenter == true)
    {
    Radial_max /= 2.0;
    }   
  m_RadialStep = log(Radial_max) / m_RadialNumberOfSamples ;   
}

template <class TInputImage, class TInterpolator>
void
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::CalculateAngularStep()
{  
  if( m_RadialNumberOfSamples <1 )
    {
    itkExceptionMacro(<< "LogPolarResampleImageFilter::CalculateAngularStep() m_RadialNumberOfSamples must be greater than one"<<std::endl);
    }
  double by = log(m_AngularNumberOfSamples) / log(2.0);
  if(int(by)!=by)
    {
     m_AngularNumberOfSamples = pow(2,int(by)+1);
    }

  double Angular_max = 90.0; 
  if(m_OriginIsAtCenter == true)
    {
    Angular_max = 360.0;
    }

  m_AngularStep = Angular_max / m_AngularNumberOfSamples;

}

template <class TInputImage, class TInterpolator>
void
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::SetAngularStep(double angularStep)
{
  m_AngularStep = angularStep;
  m_AngularStepIsConfigured = true;
}

template <class TInputImage, class TInterpolator>
void
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::SetRadialStep(double radialStep)
{
  m_RadialStep = radialStep;
  m_RadialStepIsConfigured = true;
}

template <class TInputImage, class TInterpolator>
void
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::SetAngularNumberOfSamples(double angularNumberOfSamples)
{
  m_AngularNumberOfSamples = angularNumberOfSamples;
  m_AngularStepIsConfigured = false;
}

template <class TInputImage, class TInterpolator>
void
LogPolarResampleImageFilter<TInputImage,TInterpolator>
::SetRadialNumberOfSamples(double radialNumberOfSamples)
{
  m_RadialNumberOfSamples = radialNumberOfSamples;
  m_RadialStepIsConfigured = false;
}



} // end namespace otb

#endif