Commit 4a2073fd authored by Julien Michel's avatar Julien Michel

Merge branch 'refactor_pansharpening_with_FunctorImageFilter' into 'develop'

Refactor PanSharpening module to use FunctorImageFilter everywhere

See merge request !325
parents 5e61ea29 c1cfefdf
......@@ -53,8 +53,6 @@ public:
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
typedef itk::ImageToImageFilter<FloatVectorImageType, FloatVectorImageType> FusionFilterType;
typedef otb::SimpleRcsPanSharpeningFusionImageFilter<FloatImageType, FloatVectorImageType, FloatVectorImageType> SimpleRCSFilterType;
typedef otb::LmvmPanSharpeningFusionImageFilter
......@@ -176,7 +174,9 @@ private:
filter->UpdateOutputInformation();
otbAppLogINFO( << "Simple RCS algorithm" );
m_FusionFilter = filter;
m_Ref.push_back(filter.GetPointer());
SetParameterOutputImage("out", filter->GetOutput());
break;
}
case 1:
......@@ -203,8 +203,9 @@ private:
filter->UpdateOutputInformation();
otbAppLogINFO( << "Lmvm algorithm" );
m_Ref.push_back(filter.GetPointer());
SetParameterOutputImage("out", filter->GetOutput());
m_FusionFilter = filter;
break;
}
case 2:
......@@ -224,7 +225,9 @@ private:
filter->UpdateOutputInformation();
otbAppLogINFO( << "Bayesian fusion algorithm" );
m_FusionFilter = filter;
m_Ref.push_back(filter.GetPointer());
SetParameterOutputImage("out", filter->GetOutput());
break;
}
......@@ -236,12 +239,9 @@ private:
}
return;
}
SetParameterOutputImage("out", m_FusionFilter->GetOutput());
}
std::vector<itk::ProcessObject::Pointer> m_Ref;
FusionFilterType::Pointer m_FusionFilter;
};
}
}
......
......@@ -26,6 +26,7 @@
#include "itkConstNeighborhoodIterator.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageScanlineIterator.h"
#include <array>
namespace otb
{
......
......@@ -24,7 +24,7 @@
#include "itkImageToImageFilter.h"
#include "otbVectorImage.h"
#include "otbStreamingStatisticsVectorImageFilter.h"
#include "otbFusionImageBase.h"
#include "otbFunctorImageFilter.h"
#include "otbStreamingMatrixTransposeMatrixImageFilter.h"
#include "otbImageToVectorImageCastFilter.h"
......@@ -100,12 +100,11 @@ public:
return m_Vcondopt;
}
inline TOutput operator ()(const TInputMultiSpectral& itkNotUsed(ms),
const TInputMultiSpectralInterp& msi,
const TInputPanchro& p)
void operator ()(TOutput & obs,
const TInputMultiSpectral& itkNotUsed(ms),
const TInputMultiSpectralInterp& msi,
const TInputPanchro& p)
{
TOutput obs;
obs.SetSize(msi.GetSize());
MatrixType obsMat, msiVect;
obsMat.SetSize(1, obs.GetSize());
msiVect.SetSize(1, msi.GetSize());
......@@ -145,7 +144,11 @@ public:
{
obs[i] = static_cast<typename TOutput::ValueType>(obsMat(0U, i));
}
return obs;
}
constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const
{
return inputsNbBands[1];
}
private:
......@@ -193,14 +196,10 @@ template <class TInputMultiSpectralImage,
class TInputPanchroImage,
class TOutputImage>
class ITK_EXPORT BayesianFusionFilter
: public FusionImageBase<TInputMultiSpectralImage,
TInputMultiSpectralInterpImage,
TInputPanchroImage,
TOutputImage,
Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType,
typename TInputMultiSpectralInterpImage::PixelType,
typename TInputPanchroImage::PixelType,
typename TOutputImage::PixelType> >
: public FunctorImageFilter<Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType,
typename TInputMultiSpectralInterpImage::PixelType,
typename TInputPanchroImage::PixelType,
typename TOutputImage::PixelType> >
{
public:
/** Extract input and output images dimensions.*/
......@@ -215,14 +214,11 @@ public:
/** "typedef" for standard classes. */
typedef BayesianFusionFilter Self;
typedef FusionImageBase<InputMultiSpectralImageType,
InputMultiSpectralInterpImageType,
InputPanchroImageType,
OutputImageType,
Functor::BayesianFunctor<typename InputMultiSpectralImageType::PixelType,
typename InputMultiSpectralInterpImageType::PixelType,
typename InputPanchroImageType::PixelType,
typename OutputImageType::PixelType> > Superclass;
using BayesianFunctorType = Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType,
typename TInputMultiSpectralInterpImage::PixelType,
typename TInputPanchroImage::PixelType,
typename TOutputImage::PixelType>;
typedef FunctorImageFilter<BayesianFunctorType> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
......@@ -230,7 +226,7 @@ public:
itkNewMacro(Self);
/** return class name. */
itkTypeMacro(BayesianFusionFilter, FusionImageBase);
itkTypeMacro(BayesianFusionFilter, FunctorImageFilter);
/** Supported images definition. */
typedef typename InputMultiSpectralImageType::PixelType InputMultiSpectralPixelType;
......@@ -266,6 +262,36 @@ public:
typedef ImageToVectorImageCastFilter<InputPanchroImageType,
InputMultiSpectralImageType> CasterType;
void SetMultiSpect(const InputMultiSpectralImageType *multiSpect)
{
this->template SetVariadicInput<0>(multiSpect);
}
void SetMultiSpectInterp(const InputMultiSpectralInterpImageType *multiSpectInterp)
{
this->template SetVariadicInput<1>(multiSpectInterp);
}
void SetPanchro(const InputPanchroImageType *panchro)
{
this->template SetVariadicInput<2>(panchro);
}
const InputMultiSpectralImageType* GetMultiSpect()
{
return this->template GetVariadicInput<0>();
}
const InputMultiSpectralInterpImageType* GetMultiSpectInterp()
{
return this->template GetVariadicInput<1>();
}
const InputPanchroImageType* GetPanchro()
{
return this->template GetVariadicInput<2>();
}
/** Set the ponderation value. */
itkSetMacro(Lambda, float);
/** Give the ponderation value. */
......@@ -297,8 +323,14 @@ public:
itkGetConstReferenceMacro(S, float);
protected:
BayesianFusionFilter();
~BayesianFusionFilter() override;
BayesianFusionFilter() : Superclass(BayesianFunctorType{},{{0,0}})
{
m_Lambda = 0.9999;
m_S = 1;
m_StatisticsHaveBeenGenerated = false;
};
~BayesianFusionFilter() override {};
/** Check if internal statistics need to be computed, and do so */
void BeforeThreadedGenerateData() override;
/** Compute internal statistics required for fusion */
......
......@@ -27,33 +27,6 @@
namespace otb
{
template <class TInputMultiSpectralImage,
class TInputMultiSpectralInterpImage,
class TInputPanchroImage,
class TOutputImage>
BayesianFusionFilter<TInputMultiSpectralImage,
TInputMultiSpectralInterpImage,
TInputPanchroImage,
TOutputImage>
::BayesianFusionFilter()
{
m_Lambda = 0.9999;
m_S = 1;
m_StatisticsHaveBeenGenerated = false;
}
template <class TInputMultiSpectralImage,
class TInputMultiSpectralInterpImage,
class TInputPanchroImage,
class TOutputImage>
BayesianFusionFilter<TInputMultiSpectralImage,
TInputMultiSpectralInterpImage,
TInputPanchroImage,
TOutputImage>
::~BayesianFusionFilter()
{
}
template <class TInputMultiSpectralImage,
class TInputMultiSpectralInterpImage,
class TInputPanchroImage,
......@@ -302,12 +275,12 @@ BayesianFusionFilter<TInputMultiSpectralImage,
//**** END TODO ****/
m_Vcondopt = m_Vcondopt.GetInverse();
// Functor initialization
this->GetFunctor().SetVcondopt(m_Vcondopt);
this->GetFunctor().SetBeta(cutBeta);
this->GetFunctor().SetAlpha(m_Beta(0, 0));
this->GetFunctor().SetCovarianceInvMatrix(m_CovarianceInvMatrix);
this->GetFunctor().SetLambda(m_Lambda);
this->GetFunctor().SetS(m_S);
this->GetModifiableFunctor().SetVcondopt(m_Vcondopt);
this->GetModifiableFunctor().SetBeta(cutBeta);
this->GetModifiableFunctor().SetAlpha(m_Beta(0, 0));
this->GetModifiableFunctor().SetCovarianceInvMatrix(m_CovarianceInvMatrix);
this->GetModifiableFunctor().SetLambda(m_Lambda);
this->GetModifiableFunctor().SetS(m_S);
// Restore the previous buffered data
multiSpecInterp->SetRequestedRegion(msiRequestedRegion);
......
/*
* 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 otbFusionImageBase_h
#define otbFusionImageBase_h
#include "itkTernaryFunctorImageFilter.h"
#include "itkNumericTraits.h"
namespace otb
{
/** \class FusionImageBase
* Basic class for every Fusion classes.
* \sa TernaryFunctorImageFilter
*
* \ingroup OTBPanSharpening
*/
template <class TInputMultiSpectralImage, class TInputMultiSpectralInterpImage, class TInputPanchroImage,
class TOutputImage, class TFunctor>
class ITK_EXPORT FusionImageBase : public itk::TernaryFunctorImageFilter<TInputMultiSpectralImage,
TInputMultiSpectralInterpImage,
TInputPanchroImage, TOutputImage, TFunctor>
{
public:
/** Extract input and output images dimensions.*/
itkStaticConstMacro(InputImageDimension, unsigned int, TInputMultiSpectralImage::ImageDimension);
itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension);
/** "typedef" to simplify the variables definition and the declaration. */
typedef TInputMultiSpectralImage InputMultiSpectralImageType;
typedef TInputMultiSpectralInterpImage InputMultiSpectralInterpImageType;
typedef TInputPanchroImage InputPanchroImageType;
typedef TOutputImage OutputImageType;
typedef TFunctor FunctorType;
/** "typedef" for standard classes. */
typedef FusionImageBase Self;
typedef itk::TernaryFunctorImageFilter<InputMultiSpectralImageType,
InputMultiSpectralInterpImageType,
InputPanchroImageType,
OutputImageType,
FunctorType> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** object factory method. */
itkNewMacro(Self);
/** return class name. */
itkTypeMacro(FusionImageBase, TernaryFunctorImageFilter);
/** Supported images definition. */
typedef typename InputMultiSpectralImageType::PixelType InputMultiSpectralPixelType;
typedef typename InputMultiSpectralInterpImageType::PixelType InputMultiSpectralInterpPixelType;
typedef typename InputPanchroImageType::PixelType InputPanchroPixelType;
typedef typename OutputImageType::PixelType OutputPixelType;
/** Real class typedef definition. */
typedef typename itk::NumericTraits<InputMultiSpectralPixelType>::RealType InputMultiSpectralRealType;
typedef typename itk::NumericTraits<InputMultiSpectralInterpPixelType>::RealType InputMultiSpectralInterpRealType;
typedef typename itk::NumericTraits<InputPanchroPixelType>::RealType InputPanchroRealType;
typedef typename InputMultiSpectralImageType::RegionType InputMultiSpectralImageRegionType;
typedef typename InputMultiSpectralInterpImageType::RegionType
InputMultiSpectralInterpImageRegionType;
typedef typename InputPanchroImageType::RegionType InputPanchroImageRegionType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
/** Image size "typedef" definition. */
typedef typename InputMultiSpectralImageType::SizeType SizeType;
void SetMultiSpect(const InputMultiSpectralImageType *multiSpect)
{
this->SetInput1(multiSpect);
}
void SetMultiSpectInterp(const InputMultiSpectralInterpImageType *multiSpectInterp)
{
this->SetInput2(multiSpectInterp);
}
void SetPanchro(const InputPanchroImageType *panchro)
{
this->SetInput3(panchro);
}
const InputMultiSpectralImageType* GetMultiSpect()
{
if (this->GetNumberOfInputs() < 1)
{
return nullptr;
}
else return (static_cast<const InputMultiSpectralImageType *>(this->itk::ProcessObject::GetInput(0)));
}
const InputMultiSpectralInterpImageType* GetMultiSpectInterp()
{
if (this->GetNumberOfInputs() < 2)
{
return nullptr;
}
else return (static_cast<const InputMultiSpectralInterpImageType *>(this->itk::ProcessObject::GetInput(1)));
}
const InputPanchroImageType* GetPanchro()
{
if (this->GetNumberOfInputs() < 3)
{
return nullptr;
}
else return (static_cast<const InputPanchroImageType *>(this->itk::ProcessObject::GetInput(2)));
}
};
} // end namespace otb
#endif
......@@ -23,8 +23,7 @@
#define otbLmvmPanSharpeningFusionImageFilter_h
#include "otbConvolutionImageFilter.h"
#include "itkUnaryFunctorImageFilter.h"
#include "itkTernaryFunctorImageFilter.h"
#include "otbFunctorImageFilter.h"
#include "otbPerBandVectorImageFilter.h"
#include "itkNoiseImageFilter.h"
#include "otbVectorImage.h"
......@@ -132,36 +131,34 @@ private:
{
public:
// Implement the fusion as a six arguments operator
typename TOutputImageType::PixelType operator()(
const typename InternalVectorImageType::PixelType& stdXsPixel,
const TInternalPrecision& smoothPanchroPixel,
const typename TPanImageType::PixelType& sharpPanchroPixel) const
void operator()(typename TOutputImageType::PixelType& output,
const typename InternalVectorImageType::PixelType& stdXsPixel,
const TInternalPrecision& smoothPanchroPixel,
const typename TPanImageType::PixelType& sharpPanchroPixel) const
{
// Build output pixel
typename TOutputImageType::PixelType output(stdXsPixel.Size());
// Perform fusion for each band with appropriate casting
for(unsigned int i = 0; i < stdXsPixel.Size(); ++i)
{
output[i] = static_cast<typename TOutputImageType::InternalPixelType>(
((sharpPanchroPixel - smoothPanchroPixel) * stdXsPixel[i]));
}
// Returns the output pixel
return output;
}
constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const
{
return inputsNbBands[0];
}
};
class FusionFunctor2
{
public:
// Implement the fusion as a six arguments operator
typename TOutputImageType::PixelType operator()(const typename TOutputImageType::PixelType& functor1Pixel,
const typename InternalVectorImageType::PixelType& smoothXsPixel,
const TInternalPrecision& stdPanchroPixel) const
void operator()(typename TOutputImageType::PixelType & output,
const typename TOutputImageType::PixelType& functor1Pixel,
const typename InternalVectorImageType::PixelType& smoothXsPixel,
const TInternalPrecision& stdPanchroPixel) const
{
// Build output pixel
typename TOutputImageType::PixelType output(smoothXsPixel.Size());
TInternalPrecision scale = 1.;
if(std::abs(stdPanchroPixel) > 1e-10)
......@@ -175,8 +172,11 @@ private:
output[i] = static_cast<typename TOutputImageType::InternalPixelType>(
((functor1Pixel[i] * scale) + smoothXsPixel[i]));
}
// Returns the output pixel
return output;
}
constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const
{
return inputsNbBands[0];
}
};
......@@ -184,24 +184,16 @@ private:
* Typedef of the TernaryFunctorImageFilter applying the fusion functor to
* p, p_smooth, p_std, xs_smooth, xs_std and xs.
*/
typedef itk::TernaryFunctorImageFilter<InternalVectorImageType,
InternalImageType,
TPanImageType,
TOutputImageType,
FusionFunctor1> FusionStep1FilterType;
typedef FunctorImageFilter<FusionFunctor1> FusionStep1FilterType;
/** Pointer to the fusion filter */
typename FusionStep1FilterType::Pointer m_FusionStep1Filter;
typename FusionStep1FilterType::Pointer m_FusionStep1Filter;
typedef itk::TernaryFunctorImageFilter<TOutputImageType,
InternalVectorImageType,
InternalImageType,
TOutputImageType,
FusionFunctor2> FusionStep2FilterType;
typedef FunctorImageFilter<FusionFunctor2> FusionStep2FilterType;
/** Pointer to the fusion filter */
typename FusionStep2FilterType::Pointer m_FusionStep2Filter;
typename FusionStep2FilterType::Pointer m_FusionStep2Filter;
/** Typedef of the convolution filter performing Pan smoothing */
......
......@@ -24,7 +24,7 @@
#include "otbConvolutionImageFilter.h"
#include "otbImage.h"
#include "itkTernaryFunctorImageFilter.h"
#include "otbFunctorImageFilter.h"
#include "itkProgressAccumulator.h"
......@@ -118,13 +118,11 @@ private:
{
public:
// Implement the fusion as a three arguments operator
typename TOutputImageType::PixelType operator()(const typename TXsImageType::PixelType& xsPixel,
void operator()(typename TOutputImageType::PixelType & output,
const typename TXsImageType::PixelType& xsPixel,
const TInternalPrecision& smoothPanchroPixel,
const typename TPanImageType::PixelType& sharpPanchroPixel) const
{
// Build output pixel
typename TOutputImageType::PixelType output(xsPixel.Size());
TInternalPrecision scale = 1.;
if(std::abs(smoothPanchroPixel) > 1e-10)
......@@ -138,8 +136,11 @@ private:
output[i] = static_cast<typename TOutputImageType::InternalPixelType>(
xsPixel[i] * scale);
}
// Returns the output pixel
return output;
}
constexpr size_t OutputSize(const std::array<size_t, 3> & inputsNbBands) const
{
return inputsNbBands[0];
}
};
......@@ -155,13 +156,11 @@ private:
{
public:
// Implement the fusion as a three arguments operator
typename TOutputImageType::PixelType operator()(const typename TXsImageType::PixelType& xsPixel,
const TInternalPrecision& smoothPanchroPixel,
const typename TPanImageType::PixelType& sharpPanchroPixel) const
void operator()(typename TOutputImageType::PixelType & output,
const typename TXsImageType::PixelType& xsPixel,
const TInternalPrecision& smoothPanchroPixel,
const typename TPanImageType::PixelType& sharpPanchroPixel) const
{
// Build output pixel
typename TOutputImageType::PixelType output(xsPixel.Size());
// Check for no data Pan value
if( m_NoDataValuePanAvailable && sharpPanchroPixel == m_NoDataValuePan )
{
......@@ -169,7 +168,7 @@ private:
{
output[i] = static_cast<typename TOutputImageType::InternalPixelType>( m_NoDataValuesXs[i] );
}
return output;
return;
}
TInternalPrecision scale = 1.;
......@@ -186,8 +185,6 @@ private:
static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] ) :
static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] * scale );
}
// Returns the output pixel
return output;
}
void SetNoDataValuePanAvailable(bool noDataAvailable) {
......@@ -206,6 +203,12 @@ private:
m_NoDataValuesXs = noDataValues;
}
constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const
{
return inputsNbBands[0];
}
NoDataFusionFunctor() : m_NoDataValuePanAvailable(false), m_NoDataValuePan(0),m_NoDataValuesXsAvailable(false), m_NoDataValuesXs() {}
private:
/** No data flags and values for APN image */
......@@ -221,24 +224,16 @@ private:
/**
* Typedef of the TernaryFunctorImageFilter applying the fusion functor to
* Typedef of the FunctorImageFilter applying the fusion functor to
* p, p_smooth and xs.
*/
typedef itk::TernaryFunctorImageFilter<TXsImageType,
InternalImageType,
TPanImageType,
TOutputImageType,
FusionFunctor> FusionFilterType;
typedef FunctorImageFilter<FusionFunctor> FusionFilterType;
/**
* Typedef of the TernaryFunctorImageFilter applying the no data fusion functor to
* Typedef of the FunctorImageFilter applying the no data fusion functor to
* p, p_smooth and xs.
*/
typedef itk::TernaryFunctorImageFilter<TXsImageType,
InternalImageType,
TPanImageType,
TOutputImageType,
NoDataFusionFunctor> NoDataFusionFilterType;
typedef FunctorImageFilter<NoDataFusionFunctor> NoDataFusionFilterType;
/** Typedef of the convolution filter performing smoothing */
typedef otb::ConvolutionImageFilter
......
......@@ -174,10 +174,10 @@ SimpleRcsPanSharpeningFusionImageFilter
m_ProgressAccumulator->RegisterInternalFilter( m_NoDataFusionFilter, 0.1 );
m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() );
m_NoDataFusionFilter->GetFunctor().SetNoDataValuesXsAvailable( noDataValuesXsAvailable );
m_NoDataFusionFilter->GetFunctor().SetNoDataValuePanAvailable( noDataValuePanAvailable );
m_NoDataFusionFilter->GetFunctor().SetNoDataValuePan( noDataValuePan );
m_NoDataFusionFilter->GetFunctor().SetNoDataValuesXs( noDataValuesXs );
m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuesXsAvailable( noDataValuesXsAvailable );
m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuePanAvailable( noDataValuePanAvailable );
m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuePan( noDataValuePan );
m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuesXs( noDataValuesXs );
m_NoDataFusionFilter->SetInput1( this->GetXsInput() );
m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() );
......
......@@ -32,7 +32,7 @@ otb_module(OTBPanSharpening
OTBITK
OTBConvolution
OTBImageManipulation
OTBFunctor
TEST_DEPENDS
OTBTestKernel
OTBImageIO
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment