Commit b323ae23 authored by Rashad Kanavath's avatar Rashad Kanavath

Merge branches 'app_domain_transform' and 'develop' of...

Merge branches 'app_domain_transform' and 'develop' of https://git.orfeo-toolbox.org/git/otb into develop
parents 2dc3ad09 aea415a3
project(OTBAppDomainTransform)
otb_module_impl()
otb_create_application(
NAME DomainTransform
SOURCES otbDomainTransform.cxx
LINK_LIBRARIES ${${otb-module}_LIBRARIES})
/*=========================================================================
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 "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"
#include "otbWaveletImageFilter.h"
#include "otbWaveletInverseImageFilter.h"
#include "otbWaveletGenerator.h"
#include <itkConfigure.h>
#include <itkForwardFFTImageFilter.h>
#include <itkInverseFFTImageFilter.h>
#include <itkUnaryFunctorImageFilter.h>
namespace otb
{
namespace Wrapper
{
template< class TInput, class TOutput>
class FromComplexPixel
{
public:
FromComplexPixel ( ) { };
~FromComplexPixel( ) { };
bool operator!=( const FromComplexPixel & ) const
{
return false;
}
bool operator==( const FromComplexPixel & other ) const
{
return !(*this != other);
}
inline TOutput operator( )( const TInput & A ) const
{
TOutput out;
out.SetSize(2);
out[0] = A.real();
out[1] = A.imag();
return out;
}
};
template< class TInput, class TOutput>
class ToComplexPixel
{
public:
ToComplexPixel ( ) { };
~ToComplexPixel( ) { };
bool operator!=( const ToComplexPixel & ) const
{
return false;
}
bool operator==( const ToComplexPixel & other ) const
{
return !(*this != other);
}
inline TOutput operator( )( const TInput & A ) const
{
TOutput out(A[0], A[1]);
return out;
}
};
class DomainTransform : public Application
{
public:
/** Standard class typedefs. */
typedef DomainTransform Self;
typedef Application Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
typedef float TInputPixel;
typedef float TOutputPixel;
/** Standard macro */
itkNewMacro(Self);
itkTypeMacro(Self, otb::Application);
private:
void DoInit() ITK_OVERRIDE
{
SetName("DomainTransform");
const char * app_descr = "Domain Transform application for wavelet and fourier";
SetDescription(app_descr);
// Documentation
SetDocName(app_descr);
SetDocLongDescription("TODO");
SetDocLimitations("None");
SetDocAuthors("OTB-Team");
SetDocSeeAlso("otbWaveletImageFilter, otbWaveletInverseImageFilter, otbWaveletTransform");
AddDocTag(Tags::Filter);
AddParameter(ParameterType_InputImage, "in", "Input Image");
SetParameterDescription("in", "This will take an input image to be transformed image. For FFT inverse transform, it expects a complex image as two-band image in which first band represent real part and second band represent imaginary part.");
AddRAMParameter();
AddParameter(ParameterType_Choice, "mode", "mode");
SetParameterDescription("mode", "This parameter allows one to select between fft(fourier) and wavelet");
AddChoice("mode.fft", "FFT transform");
SetParameterDescription("mode.fft", "FFT transform");
AddChoice("mode.wavelet", "wavelet");
SetParameterDescription("mode.wavelet", "Wavelet transform");
AddParameter(ParameterType_Choice,
"mode.wavelet.form",
"Select wavelet form. default is HAAR");
AddChoice("mode.wavelet.form.haar", "HAAR");
AddChoice("mode.wavelet.form.db4", "DAUBECHIES4");
AddChoice("mode.wavelet.form.db6", "DAUBECHIES6");
AddChoice("mode.wavelet.form.db8", "DAUBECHIES8");
AddChoice("mode.wavelet.form.db12", "DAUBECHIES12");
AddChoice("mode.wavelet.form.db20", "DAUBECHIES20");
AddChoice("mode.wavelet.form.sb24", "SPLINE_BIORTHOGONAL_2_4");
AddChoice("mode.wavelet.form.sb44", "SPLINE_BIORTHOGONAL_4_4");
AddChoice("mode.wavelet.form.sym8", "SYMLET8");
//Default value
SetParameterString("mode", "wavelet");
SetParameterString("mode.wavelet.form", "haar");
AddParameter(ParameterType_Choice,
"dir",
"dir: forward/inverse");
AddChoice("dir.fwd", "fwd");
AddChoice("dir.inv", "inv");
AddParameter(ParameterType_OutputImage, "out", "Output Image");
SetParameterDescription("out", "This parameter holds the output file name to which transformed image will be written. This has a slightly different behaviour depending on transform type. \n For Wavelet, output is a single band image for both forward and inverse transform. \n For FFT forward transform, output is two band image where first band represents real part and second band represents imaginary part of a complex image.");
SetDocExampleParameterValue("in", "input.tif");
SetDocExampleParameterValue("mode.wavelet.form", "haar");
SetDocExampleParameterValue("out", "output_wavelet_haar.tif");
}
void DoUpdateParameters() ITK_OVERRIDE
{
// wavelet and fourier are mutually exclusive parameters.
// check it here
#if 0
if ( HasUserValue("mode.wavelet.form") &&
GetParameterString("mode") == "fft"
)
{
std::stringstream oss;
oss << std::endl
<< this->GetNameOfClass() << "::DoUpdateParameters() "
<< "Cannot use 'mode.wavelet.form' and '-mode fft' at same time"
<< std::endl;
throw std::runtime_error( oss.str() );
}
#endif
}
void DoExecute() ITK_OVERRIDE
{
int dir = GetParameterInt("dir");
int mode = GetParameterInt("mode");
if( dir != 0 && dir != 1)
{
itkExceptionMacro( << "-dir is '"
<< dir << "'."
<< "It must be either 'fwd' or 'inv'");
}
if( mode != 0 && mode != 1)
{
itkExceptionMacro( << "mode is '"
<< mode << "'."
<< "It must must be either 'fft' or 'wavelet'");
}
if ( mode == 1)
{
int wavelet_type = GetParameterInt("mode.wavelet.form");
switch (wavelet_type)
{
case 0:
DoWaveletTransform<otb::Wavelet::HAAR> ( dir );
break;
case 1:
DoWaveletTransform< otb::Wavelet::DB4 > ( dir );
break;
case 2:
DoWaveletTransform<otb::Wavelet::DB4> ( dir );
break;
case 3:
DoWaveletTransform<otb::Wavelet::DB6> ( dir );
break;
case 4:
DoWaveletTransform<otb::Wavelet::DB8> ( dir );
break;
case 5:
DoWaveletTransform<otb::Wavelet::DB12> ( dir );
break;
case 6:
DoWaveletTransform<otb::Wavelet::DB20> ( dir );
break;
case 7:
DoWaveletTransform<otb::Wavelet::SPLINE_BIORTHOGONAL_2_4 > ( dir );
break;
case 8:
DoWaveletTransform<otb::Wavelet::SPLINE_BIORTHOGONAL_4_4> ( dir );
break;
case 9:
DoWaveletTransform<otb::Wavelet::SYMLET8> ( dir );
break;
default:
itkExceptionMacro( << "Invalid wavelet type: '" << wavelet_type << "'");
break;
}
}
// fft ttransform
else
{
//forward fft
if (dir == 0 )
{
typedef otb::Image<TInputPixel> TInputImage;
typedef typename TInputImage::Pointer TInputImagePointer;
//get input paramter as otb::Image<TInputPixel>
TInputImagePointer inImage = GetParameterImage<TInputImage>("in");
inImage->UpdateOutputInformation();
//typedef itk::::ForwardFFTImageFilter over otbImage< TInputPixel >
typedef itk::ForwardFFTImageFilter < TInputImage> FFTFilter;
FFTFilter::Pointer fwdFilter = FFTFilter::New();
fwdFilter->SetInput( inImage );
//typedef VectorImage for output of UnaryFunctorImageFilter
typedef otb::VectorImage<TOutputPixel> TOutputImage;
//UnaryFunctorImageFilter for Complex to VectorImage
typedef itk::UnaryFunctorImageFilter<
typename FFTFilter::OutputImageType,
TOutputImage,
FromComplexPixel<
typename FFTFilter::OutputImageType::PixelType,
TOutputImage::PixelType> > UnaryFunctorImageFilter;
//convert complex pixel to variable length vector
//with unaryfunctor image filter
UnaryFunctorImageFilter::Pointer unaryFunctorImageFilter
= UnaryFunctorImageFilter::New();
unaryFunctorImageFilter->SetInput(fwdFilter->GetOutput());
unaryFunctorImageFilter->Update();
//set output image
SetParameterOutputImage<TOutputImage>
( "out", unaryFunctorImageFilter->GetOutput() );
}
//inverse fft
else
{
typedef otb::VectorImage<TInputPixel> TInputImage;
typedef typename TInputImage::Pointer TInputImagePointer;
TInputImagePointer inImage = GetParameterImage("in");
inImage->UpdateOutputInformation();
// typedef TComplexImage for InverseFFTImageFilter input
// This a image type of std::complex<TInputPixel>
typedef otb::Image<
std::complex<TInputPixel>, 2 > TComplexImage;
//typedef TOutputImage for InverseFFTImageFilter output
typedef otb::Image< TOutputPixel > TOutputImage;
// a unary functor to convert vectorimage to complex image
typedef itk::UnaryFunctorImageFilter
<TInputImage,
TComplexImage,
ToComplexPixel
<TInputImage::PixelType,
TComplexImage::PixelType> > UnaryFunctorImageFilter;
UnaryFunctorImageFilter::Pointer
unary_filter = UnaryFunctorImageFilter::New();
unary_filter->SetInput(inImage);
//typedef itk::::InverseFFTImageFilter over TComplexImage
typedef itk::InverseFFTImageFilter
< TComplexImage,
TOutputImage > FFTFilter;
FFTFilter::Pointer invFilter = FFTFilter::New();
invFilter->SetInput( unary_filter->GetOutput() );
invFilter->Update();
//set output image
SetParameterOutputImage<TOutputImage>( "out", invFilter->GetOutput() );
}
}
}
template<otb::Wavelet::Wavelet TWaveletOperator>
void DoWaveletTransform(const int dir,
const std::string inkey = "in",
const std::string outkey = "out")
{
typedef otb::Image< TInputPixel > TInputImage;
typedef otb::Image< TOutputPixel > TOutputImage;
typedef typename TInputImage::Pointer TInputImagePointer;
TInputImagePointer inImage = GetParameterImage<TInputImage>(inkey);
inImage->UpdateOutputInformation();
if( dir == 0)
{
typedef otb::WaveletImageFilter<
TInputImage,
TOutputImage,
TWaveletOperator> TWaveletImageFilter;
typedef typename
TWaveletImageFilter::Pointer
TWaveletImageFilterPointer;
TWaveletImageFilterPointer waveletImageFilter =
TWaveletImageFilter::New();
waveletImageFilter->SetInput(inImage);
waveletImageFilter->Update();
SetParameterOutputImage<TOutputImage>(outkey, waveletImageFilter->GetOutput() );
}
else
{
typedef otb::WaveletInverseImageFilter<
TInputImage,
TOutputImage,
TWaveletOperator > TWaveletImageFilter;
typedef typename
TWaveletImageFilter::Pointer
TWaveletImageFilterPointer;
TWaveletImageFilterPointer waveletImageFilter =
TWaveletImageFilter::New();
waveletImageFilter->SetInput(inImage);
waveletImageFilter->Update();
SetParameterOutputImage<TOutputImage>( outkey, waveletImageFilter->GetOutput() );
}
}
};
}
}
OTB_APPLICATION_EXPORT(otb::Wrapper::DomainTransform)
set(DOCUMENTATION "TODO")
otb_module(OTBAppDomainTransform
DEPENDS
OTBWavelet
OTBApplicationEngine
TEST_DEPENDS
OTBTestKernel
OTBCommandLine
DESCRIPTION
"${DOCUMENTATION}"
)
......@@ -83,7 +83,7 @@ SubsampleImageFilter<TInputImage, TOutputImage, TDirectionOfTransformation>
{
Superclass::CallCopyOutputRegionToInputRegion(destRegion, srcRegion);
if (static_cast<int>(DirectionOfTransformation) == Wavelet::INVERSE)
if (DirectionOfTransformation == Wavelet::INVERSE)
{
typename OutputImageRegionType::IndexType srcIndex = srcRegion.GetIndex();
typename OutputImageRegionType::SizeType srcSize = srcRegion.GetSize();
......@@ -112,7 +112,7 @@ SubsampleImageFilter<TInputImage, TOutputImage, TDirectionOfTransformation>
{
Superclass::CallCopyInputRegionToOutputRegion(destRegion, srcRegion);
if (static_cast<int>(DirectionOfTransformation) == Wavelet::INVERSE)
if (DirectionOfTransformation == Wavelet::INVERSE)
{
typename InputImageRegionType::IndexType srcIndex = srcRegion.GetIndex();
typename InputImageRegionType::SizeType srcSize = srcRegion.GetSize();
......@@ -161,8 +161,7 @@ SubsampleImageFilter<TInputImage, TOutputImage, TDirectionOfTransformation>
SubsampledImageRegionConstIterator<InputImageType> inputIter
(this->GetInput(), inputRegionForThread);
if (static_cast<int>(itkGetStaticConstMacro(DirectionOfTransformation))
== static_cast<int>(Wavelet::FORWARD))
if (DirectionOfTransformation == Wavelet::FORWARD)
{
inputIter.SetSubsampleFactor(GetSubsampleFactor());
inputIter.GoToBegin();
......
......@@ -399,6 +399,11 @@ protected:
WaveletFilterBank();
~WaveletFilterBank() ITK_OVERRIDE {}
void VerifyInputInformation() ITK_OVERRIDE
{
}
/** GenerateOutputInformation
* Set the size of the output image depending on the decimation factor
* Copy information from the input image if existing.
......
......@@ -27,9 +27,6 @@
#include "itkPeriodicBoundaryCondition.h"
// FIXME
#define __myDebug__ 0
namespace otb {
/**
......@@ -66,11 +63,9 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::FORWARD>
if (GetSubsampleImageFactor() == 1) return;
#if __myDebug__
otbGenericMsgDebugMacro(<< " down sampling output regions by a factor of " << GetSubsampleImageFactor());
otbGenericMsgDebugMacro(<< "initial region " << this->GetInput()->GetLargestPossibleRegion().GetSize()[0]
<< "," << this->GetInput()->GetLargestPossibleRegion().GetSize()[1]);
#endif
OutputImageRegionType newRegion;
this->CallCopyInputRegionToOutputRegion(newRegion, this->GetInput()->GetLargestPossibleRegion());
......@@ -80,9 +75,8 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::FORWARD>
this->GetOutput(i)->SetRegions(newRegion);
}
#if __myDebug__
otbGenericMsgDebugMacro(<< "new region output " << newRegion.GetSize()[0] << "," << newRegion.GetSize()[1]);
#endif
}
template <class TInputImage, class TOutputImage, class TWaveletOperator>
......@@ -642,21 +636,18 @@ WaveletFilterBank<TInputImage, TOutputImage, TWaveletOperator, Wavelet::INVERSE>
}
}
#if __myDebug__
otbGenericMsgDebugMacro(<< " up sampling output regions by a factor of " << GetSubsampleImageFactor());
otbGenericMsgDebugMacro(<< "initial region "
<< this->GetInput(0)->GetLargestPossibleRegion().GetSize()[0]
<< "," << this->GetInput(0)->GetLargestPossibleRegion().GetSize()[1]);
#endif
OutputImageRegionType newRegion;
this->CallCopyInputRegionToOutputRegion(newRegion, this->GetInput(0)->GetLargestPossibleRegion());
this->GetOutput()->SetRegions(newRegion);
#if __myDebug__
otbGenericMsgDebugMacro(<< "new region output " << newRegion.GetSize()[0] << "," << newRegion.GetSize()[1]);
#endif
}
template <class TInputImage, class TOutputImage, class TWaveletOperator>
......
/*=========================================================================
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 otbWaveletImageFilter_h
#define otbWaveletImageFilter_h
#include "otbWaveletOperator.h"
#include "otbWaveletFilterBank.h"
#include "otbWaveletTransform.h"
#include "otbWaveletsBandsListToWaveletsSynopsisImageFilter.h"
namespace otb {
/** \class WaveletImageFilter
* \brief
*
* \ingroup OTBWavelet
* \sa WaveletInverseImageFilter
*/
template < class TInputImage,
class TOutputImage,
Wavelet::Wavelet TMotherWaveletOperator >
class WaveletImageFilter :
public itk::ImageToImageFilter< TInputImage, TOutputImage >
{
public:
/** Standard class typedefs. */
typedef TInputImage InputImageType;
typedef TOutputImage OutputImageType;
itkStaticConstMacro( ImageDimension, unsigned int, InputImageType::ImageDimension );
itkStaticConstMacro( MotherWaveletOperator, short, TMotherWaveletOperator );
itkStaticConstMacro( DirectionOfTransformation, short, otb::Wavelet::FORWARD );
typedef WaveletImageFilter<InputImageType,OutputImageType, TMotherWaveletOperator> Self;
typedef itk::ImageToImageFilter<InputImageType, OutputImageType> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
typedef typename InputImageType::PixelType InputPixelType;
typedef otb::WaveletOperator< TMotherWaveletOperator, otb::Wavelet::FORWARD, InputPixelType, ImageDimension >
WaveletOperatorType;
typedef otb::WaveletFilterBank< InputImageType, InputImageType, WaveletOperatorType, otb::Wavelet::FORWARD >
FilterBankType;
typedef otb::WaveletTransform< InputImageType, InputImageType, FilterBankType, otb::Wavelet::FORWARD >
WaveletTransformFilterType;
typedef typename WaveletTransformFilterType::Pointer
WaveletTransformFilterPointerType;
typedef typename WaveletTransformFilterType::OutputImageListType
WaveletTransformFilterOutputImageListType;
typedef otb::WaveletsBandsListToWaveletsSynopsisImageFilter<WaveletTransformFilterOutputImageListType, OutputImageType>
WaveletBandsListToWaveletsSynopsisImageFilterType;
typedef typename WaveletBandsListToWaveletsSynopsisImageFilterType::Pointer
WaveletBandsListToWaveletsSynopsisImageFilterPointerType;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(WaveletImageFilter, ImageToImageFilter);
itkGetMacro(NumberOfDecompositions,unsigned int);
itkSetMacro(NumberOfDecompositions,unsigned int);
protected:
WaveletImageFilter();
virtual ~WaveletImageFilter();
virtual void GenerateInputRequestedRegion();
virtual void GenerateData();
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
private:
WaveletImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
WaveletTransformFilterPointerType m_WaveletTransform;
WaveletBandsListToWaveletsSynopsisImageFilterPointerType m_WaveletBandsListToWaveletsSynopsis;
unsigned int m_NumberOfDecompositions;
};
}
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbWaveletImageFilter.txx"
#endif
#endif
/*=========================================================================
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 otbWaveletImageFilter_txx
#define otbWaveletImageFilter_txx
#include "otbWaveletImageFilter.h"
namespace otb
{
/** Constructor */
template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator>
WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator>
::WaveletImageFilter() : m_NumberOfDecompositions(2)
{
m_WaveletTransform = WaveletTransformFilterType::New();
m_WaveletTransform->SetSubsampleImageFactor(2);
m_WaveletBandsListToWaveletsSynopsis = WaveletBandsListToWaveletsSynopsisImageFilterType::New();
// Force to use a unique thread otherwise there is a bug on Mac
//m_WaveletBandsListToWaveletsSynopsis->SetNumberOfThreads(1);
m_WaveletBandsListToWaveletsSynopsis->SetInput( m_WaveletTransform->GetOutput() );
}
/** Destructor */
template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator>
WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator>
::~WaveletImageFilter()
{
}
/**
* GenerateInputRequestedRegion
*/
template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator>
void
WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator>
::GenerateInputRequestedRegion(void)
{
// call the superclass' implementation of this method
Superclass::GenerateInputRequestedRegion();
// get pointers to the inputs
typename InputImageType::Pointer input =
const_cast<InputImageType *> (this->GetInput());
if ( !input )
{
return;
}
input->SetRequestedRegionToLargestPossibleRegion();
}
/**
* Main computation method
*/
template <class TInputImage, class TOutputImage, Wavelet::Wavelet TMotherWaveletOperator>
void
WaveletImageFilter<TInputImage, TOutputImage, TMotherWaveletOperator>
::GenerateData()