Commit 89359fb0 authored by Julien Michel's avatar Julien Michel

Merge branch 'refactor-sinclairimagefilter' into 'develop'

Refactor filters in Polarimetry module to use new FunctorFilter

See merge request !318
parents b6432bd9 36dd35bf
......@@ -22,12 +22,13 @@
#ifndef otbMuellerToPolarisationDegreeAndPowerImageFilter_h
#define otbMuellerToPolarisationDegreeAndPowerImageFilter_h
#include "otbUnaryFunctorImageFilter.h"
#include "itkNumericTraits.h"
#include "itkMatrix.h"
#include "itkVector.h"
#include "otbMath.h"
#include "otbFunctorImageFilter.h"
namespace otb
{
......@@ -67,6 +68,8 @@ namespace Functor {
* - channel #2 : \f$ DegP_{min} \f$
* - channel #3 : \f$ DegP_{max} \f$
*
* Use otb::MuellerToPolarisationDegreeAndPowerImageFilter to apply
*
* \ingroup Functor
* \ingroup SARPolarimetry
*
......@@ -84,8 +87,8 @@ public:
typedef itk::Matrix<double, 4, 4> MuellerMatrixType;
typedef itk::Vector<double, 4> StokesVectorType;
inline TOutput operator()( const TInput & Mueller ) const
{
inline void operator()(TOutput& result, const TInput& Mueller) const
{
double P;
double deg_pol;
double tau;
......@@ -98,9 +101,6 @@ public:
double l_PolarisationDegreeMin(itk::NumericTraits<double>::max());
double l_PolarisationDegreeMax(itk::NumericTraits<double>::min());
TOutput result;
result.SetSize(m_NumberOfComponentsPerPixel);
MuellerMatrixType muellerMatrix;
muellerMatrix[0][0] = Mueller[0];
muellerMatrix[0][1] = Mueller[1];
......@@ -172,70 +172,35 @@ public:
result[1] = l_PowerMax;
result[2] = l_PolarisationDegreeMin;
result[3] = l_PolarisationDegreeMax;
return result;
}
unsigned int GetOutputSize()
{
return m_NumberOfComponentsPerPixel;
constexpr size_t OutputSize(...) const
{
// Size of the result
return 4;
}
/** Constructor */
MuellerToPolarisationDegreeAndPowerFunctor() : m_NumberOfComponentsPerPixel(4), m_Epsilon(1e-6), m_PI_90(2*CONST_PI_180) {}
/** Destructor */
virtual ~MuellerToPolarisationDegreeAndPowerFunctor() {}
private:
unsigned int m_NumberOfComponentsPerPixel;
const double m_Epsilon;
const double m_PI_90;
static constexpr double m_Epsilon = 1e-6;
static constexpr double m_PI_90 = 2 * CONST_PI_180;
};
}
} // namespace Functor
/** \class otbMuellerToPolarisationDegreeAndPowerImageFilter
* \brief Compute the polarization degree and power (4 channels : Power min and max, Polarization degree min and max)
* from the Mueller image (16 real channels)
* For more details, please refer to the class MuellerToPolarisationDegreeAndPowerFunctor.
*
* \ingroup SARPolarimetry
* \sa MuellerToPolarisationDegreeAndPowerFunctor
/**
* \typedef MuellerToPolarisationDegreeAndPowerImageFilter
* \brief Applies otb::Functor::MuellerToPolarisationDegreeAndPowerFunctor
* \sa otb::Functor::MuellerToPolarisationDegreeAndPowerFunctor
*
* Set inputs with:
* \code
* SetVariadicInput<0>(inputPtr);
* \endcode
*
* \ingroup OTBPolarimetry
*/
template <class TInputImage, class TOutputImage>
class ITK_EXPORT MuellerToPolarisationDegreeAndPowerImageFilter :
public UnaryFunctorImageFilter<TInputImage, TOutputImage, Functor::MuellerToPolarisationDegreeAndPowerFunctor<
typename TInputImage::PixelType, typename TOutputImage::PixelType> >
{
public:
/** Standard class typedefs. */
typedef MuellerToPolarisationDegreeAndPowerImageFilter Self;
typedef typename Functor::MuellerToPolarisationDegreeAndPowerFunctor<
typename TInputImage::PixelType, typename TOutputImage::PixelType> FunctionType;
typedef UnaryFunctorImageFilter<TInputImage, TOutputImage, FunctionType> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
template <typename TInputImage, typename TOutputImage>
using MuellerToPolarisationDegreeAndPowerImageFilter =
FunctorImageFilter<Functor::MuellerToPolarisationDegreeAndPowerFunctor<typename TInputImage::PixelType, typename TOutputImage::PixelType>>;
/** Runtime information support. */
itkTypeMacro(MuellerToPolarisationDegreeAndPowerImageFilter, UnaryFunctorImageFilter);
protected:
MuellerToPolarisationDegreeAndPowerImageFilter() {}
~MuellerToPolarisationDegreeAndPowerImageFilter() override {}
private:
MuellerToPolarisationDegreeAndPowerImageFilter(const Self&) = delete;
void operator=(const Self&) = delete;
};
} // end namespace otb
......
......@@ -22,7 +22,7 @@
#ifndef otbMuellerToReciprocalCovarianceImageFilter_h
#define otbMuellerToReciprocalCovarianceImageFilter_h
#include "otbUnaryFunctorImageFilter.h"
#include "otbFunctorImageFilter.h"
namespace otb
{
......@@ -54,6 +54,8 @@ namespace Functor {
* The output image has 6 channels : the diagonal and the upper element of the reciprocal matrix.
* Element are stored from left to right, line by line.
*
* Use otb::MuellerToReciprocalCovarianceImageFilter to apply
*
* \ingroup Functor
* \ingroup SARPolarimetry
*
......@@ -71,12 +73,8 @@ public:
typedef std::complex<double> ComplexType;
typedef typename TOutput::ValueType OutputValueType;
inline TOutput operator()( const TInput & Mueller ) const
inline void operator()(TOutput& result, const TInput& Mueller) const
{
TOutput result;
result.SetSize(m_NumberOfComponentsPerPixel);
// Keep the upper diagonal of the matrix
const double M11 = static_cast<double>(Mueller[0]);
const double M12 = static_cast<double>(Mueller[1]);
......@@ -89,7 +87,7 @@ public:
const double M34 = static_cast<double>(Mueller[11]);
const double M44 = static_cast<double>(Mueller[15]);
const ComplexType A(0.5*(M11+M22+2*M12));
const ComplexType B(0.5*std::sqrt(2.0)*(M13+M23), 0.5*std::sqrt(2.0)*(M14+M24));
const ComplexType C(-0.5*(M33+M44), -M34);
......@@ -103,67 +101,32 @@ public:
result[3] = static_cast<OutputValueType>( E );
result[4] = static_cast<OutputValueType>( F );
result[5] = static_cast<OutputValueType>( I );
return result;
}
unsigned int GetOutputSize()
{
return m_NumberOfComponentsPerPixel;
}
/** Constructor */
MuellerToReciprocalCovarianceFunctor() : m_NumberOfComponentsPerPixel(6) {}
/** Destructor */
virtual ~MuellerToReciprocalCovarianceFunctor() {}
private:
unsigned int m_NumberOfComponentsPerPixel;
constexpr size_t OutputSize(...) const
{
// Size of the result
return 6;
}
};
}
} // namespace Functor
/** \class otbMuellerToReciprocalCovarianceImageFilter
* \brief Compute the MLC image
* from the Mueller image (16 real channels)
* For more details, lease refer to the class MuellerToReciprocalCovarianceFunctor.
*
* \ingroup SARPolarimetry
* \sa MuellerToReciprocalCovarianceFunctor
/**
* \typedef MuellerToReciprocalCovarianceImageFilter
* \brief Applies otb::Functor::MuellerToReciprocalCovarianceFunctor
* \sa otb::Functor::MuellerToReciprocalCovarianceFunctor
*
* Set inputs with:
* \code
* SetVariadicInput<0>(inputPtr);
* \endcode
*
* \ingroup OTBPolarimetry
*/
template <class TInputImage, class TOutputImage>
class ITK_EXPORT MuellerToReciprocalCovarianceImageFilter :
public UnaryFunctorImageFilter<TInputImage, TOutputImage, Functor::MuellerToReciprocalCovarianceFunctor<
typename TInputImage::PixelType, typename TOutputImage::PixelType> >
{
public:
/** Standard class typedefs. */
typedef MuellerToReciprocalCovarianceImageFilter Self;
typedef Functor::MuellerToReciprocalCovarianceFunctor<
typename TInputImage::PixelType, typename TOutputImage::PixelType> FunctionType;
typedef UnaryFunctorImageFilter<TInputImage, TOutputImage, FunctionType> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
template <typename TInputImage, typename TOutputImage>
using MuellerToReciprocalCovarianceImageFilter =
FunctorImageFilter<Functor::MuellerToReciprocalCovarianceFunctor<typename TInputImage::PixelType, typename TOutputImage::PixelType>>;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Runtime information support. */
itkTypeMacro(MuellerToReciprocalCovarianceImageFilter, UnaryFunctorImageFilter);
protected:
MuellerToReciprocalCovarianceImageFilter() {}
~MuellerToReciprocalCovarianceImageFilter() override {}
private:
MuellerToReciprocalCovarianceImageFilter(const Self&) = delete;
void operator=(const Self&) = delete;
};
} // end namespace otb
......
/*
* Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef otbPolarimetryTags_h
#define otbPolarimetryTags_h
namespace otb
{
namespace polarimetry_tags
{
struct hh
{
};
struct hv
{
};
struct vh
{
};
struct vv
{
};
struct hv_or_vh
{
};
} // end namespace polarimetry_tags
} // end namespace otb
#endif
......@@ -22,20 +22,23 @@
#ifndef otbReciprocalBarnesDecompImageFilter_h
#define otbReciprocalBarnesDecompImageFilter_h
#include "otbUnaryFunctorImageFilter.h"
#include "otbMath.h"
#include "vnl/algo/vnl_complex_eigensystem.h"
#include <algorithm>
#include "otbFunctorImageFilter.h"
namespace otb
{
namespace Functor {
/** \class otbBarnesDecompFunctor
*
*
* \brief Evaluate the Huynen decomposition from the reciprocal Sinclair matrix image.
*
* Use otb::BarnesDecompImageFilter to apply
*
* \ingroup OTBPolarimetry
*/
template< class TInput, class TOutput>
......@@ -49,14 +52,11 @@ public:
typedef std::vector<double> VectorType;
typedef typename TOutput::ValueType OutputValueType;
inline void operator()(TOutput& result, const TInput& Covariance) const
{
VNLMatrixType qi(3, 1);
inline TOutput operator()( const TInput & Covariance ) const
{
TOutput result;
result.SetSize(m_NumberOfComponentsPerPixel);
VNLMatrixType qi(3,1);
VNLMatrixType cov(3, 3);
cov[0][0] = ComplexType(Covariance[0]);
......@@ -70,95 +70,62 @@ public:
cov[2][2] = ComplexType(Covariance[5]);
qi[0][0]=ComplexType(1.,0.);
qi[1][0]=ComplexType(0.,0.);
qi[2][0]=ComplexType(0.,0.);
ComplexType norm = (qi.conjugate_transpose()*cov*qi)[0][0];
VNLMatrixType ki = cov*qi / std::sqrt(norm);
qi[0][0] = ComplexType(1., 0.);
qi[1][0] = ComplexType(0., 0.);
qi[2][0] = ComplexType(0., 0.);
ComplexType norm = (qi.conjugate_transpose() * cov * qi)[0][0];
VNLMatrixType ki = cov * qi / std::sqrt(norm);
result[0] = static_cast<OutputValueType>(ki[0][0]);
result[1] = static_cast<OutputValueType>(ki[1][0]);
result[2] = static_cast<OutputValueType>(ki[2][0]);
qi[0][0]=ComplexType(0.,0.);
qi[1][0]=ComplexType(1./std::sqrt(2.),0.);
qi[2][0]=ComplexType(0.,1./std::sqrt(2.));
norm = (qi.conjugate_transpose()*cov*qi)[0][0];
ki = cov*qi / std::sqrt(norm);
qi[0][0] = ComplexType(0., 0.);
qi[1][0] = ComplexType(1. / std::sqrt(2.), 0.);
qi[2][0] = ComplexType(0., 1. / std::sqrt(2.));
norm = (qi.conjugate_transpose() * cov * qi)[0][0];
ki = cov * qi / std::sqrt(norm);
result[3] = static_cast<OutputValueType>(ki[0][0]);
result[4] = static_cast<OutputValueType>(ki[1][0]);
result[5] = static_cast<OutputValueType>(ki[2][0]);
qi[0][0]=ComplexType(0.,0.);
qi[1][0]=ComplexType(0.,1./std::sqrt(2.));
qi[2][0]=ComplexType(1./std::sqrt(2.),0.);
norm = (qi.conjugate_transpose()*cov*qi)[0][0];
ki = cov*qi / std::sqrt(norm);
qi[1][0] = ComplexType(0., 1. / std::sqrt(2.));
qi[2][0] = ComplexType(1. / std::sqrt(2.), 0.);
norm = (qi.conjugate_transpose() * cov * qi)[0][0];
ki = cov * qi / std::sqrt(norm);
result[6] = static_cast<OutputValueType>(ki[0][0]);
result[7] = static_cast<OutputValueType>(ki[1][0]);
result[8] = static_cast<OutputValueType>(ki[2][0]);
}
return result;
}
unsigned int GetOutputSize()
{
return m_NumberOfComponentsPerPixel;
}
/** Constructor */
ReciprocalBarnesDecompFunctor() : m_Epsilon(1e-6) {}
/** Destructor */
virtual ~ReciprocalBarnesDecompFunctor() {}
constexpr size_t OutputSize(...) const
{
// Size of the result
return 9;
}
private:
itkStaticConstMacro(m_NumberOfComponentsPerPixel, unsigned int, 9);
const double m_Epsilon;
static constexpr double m_Epsilon = 1e-6;
};
}
} // namespace Functor
/** \class otbBarnesDecompImageFilter
* \brief Compute the Barnes decomposition image (9 complex channels)
* from the Reciprocal Covariance image (6 complex channels)
/**
* \typedef ReciprocalBarnesDecompImageFilter
* \brief Applies otb::Functor::ReciprocalBarnesDecompFunctor
* \sa otb::Functor::ReciprocalBarnesDecompFunctor
*
* For more details, please refer to the class ReciprocalBarnesDecompFunctor.
* Set inputs with:
* \code
* SetVariadicInput<0>(inputPtr);
* \endcode
*
* \ingroup OTBPolarimetry
* \sa ReciprocalBarnesDecompFunctor
*/
template <class TInputImage, class TOutputImage>
class ITK_EXPORT ReciprocalBarnesDecompImageFilter :
public otb::UnaryFunctorImageFilter<TInputImage, TOutputImage, Functor::ReciprocalBarnesDecompFunctor<
typename TInputImage::PixelType, typename TOutputImage::PixelType> >
{
public:
/** Standard class typedefs. */
typedef ReciprocalBarnesDecompImageFilter Self;
typedef typename Functor::ReciprocalBarnesDecompFunctor<
typename TInputImage::PixelType, typename TOutputImage::PixelType> FunctionType;
typedef otb::UnaryFunctorImageFilter<TInputImage, TOutputImage, FunctionType> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Runtime information support. */
itkTypeMacro(ReciprocalBarnesDecompImageFilter, UnaryFunctorImageFilter);
protected:
ReciprocalBarnesDecompImageFilter() {}
~ReciprocalBarnesDecompImageFilter() override {}
private:
ReciprocalBarnesDecompImageFilter(const Self&) = delete;
void operator=(const Self&) = delete;
};
template <typename TInputImage, typename TOutputImage>
using ReciprocalBarnesDecompImageFilter =
FunctorImageFilter<Functor::ReciprocalBarnesDecompFunctor<typename TInputImage::PixelType, typename TOutputImage::PixelType>>;
} // end namespace otb
#endif
......@@ -22,7 +22,7 @@
#ifndef otbReciprocalCoherencyToReciprocalMuellerImageFilter_h
#define otbReciprocalCoherencyToReciprocalMuellerImageFilter_h
#include "otbUnaryFunctorImageFilter.h"
#include "otbFunctorImageFilter.h"
namespace otb
{
......@@ -51,9 +51,9 @@ namespace Functor {
* - channel #15 : \f$ 0.5.Re(VAL0) \f$
*
* With:
* VAL0 = C_{33}+C_{12}-C_{11}-(C_{12}-C_{22})^{*}
* VAL1 = -C_{33}+C_{12}-C_{11}-(C_{12}-C_{22})^{*}
*
* VAL0 = C_{33}+C_{12}-C_{11}-(C_{12}-C_{22})^{*}
* VAL1 = -C_{33}+C_{12}-C_{11}-(C_{12}-C_{22})^{*}
*
* Where Coherency is the input pixel and contains:
* - channel #0 : \f$ 0.5*(S_{hh}+S_{vv}).(S_{hh}+S_{vv})^{*} \f$
* - channel #1 : \f$ 0.5*(S_{hh}+S_{vv}).(S_{hh}-S_{vv})^{*} \f$
......@@ -65,6 +65,9 @@ namespace Functor {
* The output pixel has 16 channels
* Element are stored from left to right, line by line.
*
* Use otb::ReciprocalCoherencyToReciprocalMuellerImageFilter to apply
* it to an image.
*
* \ingroup SARPolarimetry
*
*
......@@ -77,100 +80,58 @@ public:
typedef typename std::complex <double> ComplexType;
typedef typename TOutput::ValueType OutputValueType;
inline TOutput operator()( const TInput & Coherency ) const
{
TOutput result;
result.SetSize(NumberOfComponentsPerPixel);
inline void operator()(TOutput& result, const TInput& Coherency) const
{
const double T1 = static_cast<double>(Coherency[0].real());
const double T2 = static_cast<double>(Coherency[3].real());
const double T3 = static_cast<double>(Coherency[5].real());
ComplexType VAL4 = static_cast<ComplexType>( (Coherency[1] - Coherency[3]) );
ComplexType VAL5 = static_cast<ComplexType>( (Coherency[1] - Coherency[0]) );
ComplexType VAL0 = static_cast<ComplexType>( Coherency[5] ) + VAL5 - std::conj(VAL4);
ComplexType VAL0 = static_cast<ComplexType>(Coherency[5]) + VAL5 - std::conj(VAL4);
ComplexType VAL1 = static_cast<ComplexType>( -Coherency[5] ) + VAL5 - std::conj(VAL4);
result[0] = 0.5*(T1+T2+T3);
result[0] = 0.5 * (T1 + T2 + T3);
result[1] = static_cast<double>( Coherency[1].real()+Coherency[3].imag() );
result[2] = static_cast<double>( Coherency[2].real() );
result[3] = static_cast<double>( Coherency[4].imag() );
result[4] = static_cast<double>( Coherency[1].real() );
result[5] = 0.5*(T1+T2-T3);
result[2] = static_cast<double>(Coherency[2].real());
result[3] = static_cast<double>(Coherency[4].imag());
result[4] = static_cast<double>(Coherency[1].real());
result[5] = 0.5 * (T1 + T2 - T3);
result[6] = static_cast<double>( Coherency[4].real() );
result[7] = static_cast<double>( Coherency[2].imag() );
result[7] = static_cast<double>(Coherency[2].imag());
result[8] = static_cast<double>( -Coherency[2].real() );
result[9] = static_cast<double>( -Coherency[4].real() );
result[10] = static_cast<double>( 0.5*VAL1.real() );
result[11] = static_cast<double>( 0.5*VAL0.imag() );
result[12] = static_cast<double>( Coherency[4].imag() );
result[13] = static_cast<double>( Coherency[2].imag() );
result[14] = static_cast<double>( 0.5*std::conj(VAL1).imag() );
result[15] = static_cast<double>( 0.5*VAL0.real() );
return result;
}
unsigned int GetOutputSize()
{
return NumberOfComponentsPerPixel;
}
/** Constructor */
ReciprocalCoherencyToReciprocalMuellerFunctor() {}
/** Destructor */
virtual ~ReciprocalCoherencyToReciprocalMuellerFunctor() {}
private:
itkStaticConstMacro(NumberOfComponentsPerPixel, unsigned int, 16);
result[10] = static_cast<double>(0.5 * VAL1.real());
result[11] = static_cast<double>(0.5 * VAL0.imag());
result[12] = static_cast<double>(Coherency[4].imag());
result[13] = static_cast<double>(Coherency[2].imag());
result[14] = static_cast<double>(0.5 * std::conj(VAL1).imag());
result[15] = static_cast<double>(0.5 * VAL0.real());
}
constexpr size_t OutputSize(...) const
{
// Size of the reciprocal mueller matrix
return 16;
}
};
}
} // namespace Functor
/** \class otbReciprocalCoherencyToReciprocalMuellerImageFilter
* \brief Compute the reciprocal Mueller matrix image (10 real channels)
* from the Reciprocal coherency image (6 complex channels)
*
* For more datails, please refer to ReciprocalCoherencyToReciprocalMuellerFunctor.
*
* \ingroup SARPolarimetry
* \sa ReciprocalCoherencyToReciprocalMuellerFunctor
/**
* \typedef ReciprocalCoherencyToReciprocalMuellerImageFilter
* \brief Applies otb::Functor::ReciprocalCoherencyToReciprocalMuellerFunctor
* \sa otb::Functor::ReciprocalCoherencyToReciprocalMuellerFunctor
*
* Set inputs with:
* \code
* SetVariadicInput<0>(inputPtr);
* \endcode
*
* \ingroup OTBPolarimetry
*/
template <class TInputImage, class TOutputImage>
class ITK_EXPORT ReciprocalCoherencyToReciprocalMuellerImageFilter :
public UnaryFunctorImageFilter<TInputImage, TOutputImage, Functor::ReciprocalCoherencyToReciprocalMuellerFunctor<
typename TInputImage::PixelType, typename TOutputImage::PixelType> >
{
public:
/** Standard class typedefs. */
typedef ReciprocalCoherencyToReciprocalMuellerImageFilter Self;
typedef typename Functor::ReciprocalCoherencyToReciprocalMuellerFunctor<
typename TInputImage::PixelType, typename TOutputImage::PixelType> FunctionType;
typedef UnaryFunctorImageFilter<TInputImage, TOutputImage, FunctionType> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Runtime information support. */
itkTypeMacro(ReciprocalCoherencyToReciprocalMuellerImageFilter, UnaryFunctorImageFilter);
protected:
ReciprocalCoherencyToReciprocalMuellerImageFilter() {}
~ReciprocalCoherencyToReciprocalMuellerImageFilter() override {}