Commit e721bb8e authored by Ludovic Hussonnois's avatar Ludovic Hussonnois

MRG: Merge branch 'mantis-1279' into release-5.10

parents 18c8bbd3 a365e734
......@@ -110,8 +110,8 @@ private:
* This functor applies the
* \f[ \frac{XS}{\mathrm{Filtered}(PAN)}PAN \f]
* operation. It is intended for internal use only.
*
* \ingroup OTBPanSharpening
*
* \ingroup OTBPanSharpening
*/
class FusionFunctor
{
......@@ -142,6 +142,83 @@ private:
}
};
/** \class NoDataFusionFunctor
* This functor applies the following operation if there is no data :
* \f[ \frac{XS}{\mathrm{Filtered}(PAN)}PAN \f]
* It is intended for internal use only.
*
* \ingroup OTBPanSharpening
*/
class NoDataFusionFunctor
{
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
{
// Build output pixel
typename TOutputImageType::PixelType output(xsPixel.Size());
// Check for no data Pan value
if( m_NoDataValuePanAvailable && sharpPanchroPixel == m_NoDataValuePan )
{
for ( unsigned int i = 0; i < xsPixel.Size(); ++i )
{
output[i] = static_cast<typename TOutputImageType::InternalPixelType>( m_NoDataValuesXs[i] );
}
return output;
}
TInternalPrecision scale = 1.;
if(vcl_abs(smoothPanchroPixel) > 1e-10)
{
scale = sharpPanchroPixel/smoothPanchroPixel;
}
// Perform fusion for each band with appropriate casting
for(unsigned int i = 0; i < xsPixel.Size(); ++i)
{
output[i] = ( m_NoDataValuesXsAvailable[i] && (xsPixel[i] == m_NoDataValuesXs[i]) ) ?
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) {
m_NoDataValuePanAvailable = noDataAvailable;
}
void SetNoDataValuePan(typename TPanImageType::PixelType noDataValue) {
m_NoDataValuePan = noDataValue;
}
void SetNoDataValuesXsAvailable(std::vector<bool> noDataValuesAvailable) {
m_NoDataValuesXsAvailable = noDataValuesAvailable;
}
void SetNoDataValuesXs(std::vector<typename TXsImageType::InternalPixelType> noDataValues) {
m_NoDataValuesXs = noDataValues;
}
private:
/** No data flags and values for APN image */
bool m_NoDataValuePanAvailable;
typename TPanImageType::InternalPixelType m_NoDataValuePan;
/** No data flags and values for XS image */
std::vector<bool> m_NoDataValuesXsAvailable;
std::vector<typename TXsImageType::InternalPixelType> m_NoDataValuesXs;
};
/**
* Typedef of the TernaryFunctorImageFilter applying the fusion functor to
* p, p_smooth and xs.
......@@ -152,6 +229,16 @@ private:
TOutputImageType,
FusionFunctor> FusionFilterType;
/**
* Typedef of the TernaryFunctorImageFilter applying the no data fusion functor to
* p, p_smooth and xs.
*/
typedef itk::TernaryFunctorImageFilter<TXsImageType,
InternalImageType,
TPanImageType,
TOutputImageType,
NoDataFusionFunctor> NoDataFusionFilterType;
/** Typedef of the convolution filter performing smoothing */
typedef otb::ConvolutionImageFilter
<TPanImageType,
......@@ -160,10 +247,16 @@ private:
TInternalPrecision> ConvolutionFilterType;
/** Pointer to the internal convolution filter */
typename ConvolutionFilterType::Pointer m_ConvolutionFilter;
typename ConvolutionFilterType::Pointer m_ConvolutionFilter;
/** Pointer to the fusion filter */
typename FusionFilterType::Pointer m_FusionFilter;
typename FusionFilterType::Pointer m_FusionFilter;
/** Pointer to the fusion filter */
typename NoDataFusionFilterType::Pointer m_NoDataFusionFilter;
/** Boolean used for no data */
bool m_UseNoData;
/** Radius used for the smoothing filter */
RadiusType m_Radius;
......
......@@ -32,6 +32,7 @@ SimpleRcsPanSharpeningFusionImageFilter
{
// Fix number of required inputs
this->SetNumberOfRequiredInputs(2);
this->m_UseNoData = false;
// Instantiate convolution filter
m_ConvolutionFilter = ConvolutionFilterType::New();
......@@ -42,15 +43,6 @@ SimpleRcsPanSharpeningFusionImageFilter
m_Filter.SetSize(7 * 7);
m_Filter.Fill(1);
// Instantiate fusion filter
m_FusionFilter = FusionFilterType::New();
m_FusionFilter->SetInput2(m_ConvolutionFilter->GetOutput());
// Set-up progress reporting
m_ProgressAccumulator = itk::ProgressAccumulator::New();
m_ProgressAccumulator->SetMiniPipelineFilter(this);
m_ProgressAccumulator->RegisterInternalFilter(m_ConvolutionFilter, 0.9);
m_ProgressAccumulator->RegisterInternalFilter(m_FusionFilter, 0.1);
}
template <class TPanImageType, class TXsImageType, class TOutputImageType, class TInternalPrecision>
......@@ -127,18 +119,89 @@ SimpleRcsPanSharpeningFusionImageFilter
itkExceptionMacro(<< "SimpleRcsPanSharpeningFusionImageFilter: Wrong Pan/Xs size");
}
//Process the fusion
// Set-up progress reporting
m_ProgressAccumulator = itk::ProgressAccumulator::New();
m_ProgressAccumulator->SetMiniPipelineFilter(this);
m_ProgressAccumulator->RegisterInternalFilter(m_ConvolutionFilter, 0.9);
m_ConvolutionFilter->SetInput(this->GetPanInput());
m_ConvolutionFilter->SetRadius(this->m_Radius);
m_ConvolutionFilter->SetFilter(this->m_Filter);
m_FusionFilter->SetInput1(this->GetXsInput());
m_FusionFilter->SetInput3(this->GetPanInput());
typedef typename TPanImageType::InternalPixelType PanPixelType;
typedef typename TXsImageType::InternalPixelType XsPixelType;
// Write no-data flags for Pan image
std::vector<bool> tmpNoDataValuePanAvailable;
std::vector<double> tmpNoDataValuePan;
bool noDataValuePanAvailable = false;
PanPixelType noDataValuePan = 0;
bool retPan = itk::ExposeMetaData<std::vector<bool> >( this->GetPanInput()->GetMetaDataDictionary(), MetaDataKey::NoDataValueAvailable, tmpNoDataValuePanAvailable );
retPan &= itk::ExposeMetaData<std::vector<double> >( this->GetPanInput()->GetMetaDataDictionary(), MetaDataKey::NoDataValue, tmpNoDataValuePan );
if(retPan && tmpNoDataValuePanAvailable.size() > 0 && tmpNoDataValuePan.size() > 0)
{
noDataValuePanAvailable = tmpNoDataValuePanAvailable[0] && retPan;
noDataValuePan = static_cast<PanPixelType>( tmpNoDataValuePan[0] );
}
// Write no-data flags for Xs image
std::vector<bool> noDataValuesXsAvailable;
std::vector<double> tmpNoDataValuesXs;
std::vector<XsPixelType> noDataValuesXs;
bool retXs = itk::ExposeMetaData<std::vector<bool> >( this->GetXsInput()->GetMetaDataDictionary(), MetaDataKey::NoDataValueAvailable, noDataValuesXsAvailable );
retXs &= itk::ExposeMetaData<std::vector<double> >( this->GetXsInput()->GetMetaDataDictionary(), MetaDataKey::NoDataValue, tmpNoDataValuesXs );
// Check if noData is needed and update noDataValuesAvailable with return function value
if ( retPan || retXs )
{
m_UseNoData = noDataValuePanAvailable;
for ( unsigned int i = 0; i < tmpNoDataValuesXs.size() && i < noDataValuesXsAvailable.size(); ++i )
{
noDataValuesXs.push_back( static_cast<XsPixelType>(tmpNoDataValuesXs[i]) );
m_UseNoData |= (noDataValuesXsAvailable[i] = (noDataValuesXsAvailable[i] && retXs));
}
}
// Instantiate fusion filter
if ( m_UseNoData )
{
m_NoDataFusionFilter = NoDataFusionFilterType::New();
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->SetInput1( this->GetXsInput() );
m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() );
m_NoDataFusionFilter->SetInput3( this->GetPanInput() );
// Wire composite filter
m_NoDataFusionFilter->GraftOutput( this->GetOutput() );
m_NoDataFusionFilter->Update();
this->GraftOutput( m_NoDataFusionFilter->GetOutput() );
}
else
{
m_FusionFilter = FusionFilterType::New();
m_ProgressAccumulator->RegisterInternalFilter( m_FusionFilter, 0.1 );
m_FusionFilter->SetInput1( this->GetXsInput() );
m_FusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() );
m_FusionFilter->SetInput3( this->GetPanInput() );
// Wire composite filter
m_FusionFilter->GraftOutput( this->GetOutput() );
m_FusionFilter->Update();
this->GraftOutput( m_FusionFilter->GetOutput() );
}
// Wire composite filter
m_FusionFilter->GraftOutput(this->GetOutput());
m_FusionFilter->Update();
this->GraftOutput(m_FusionFilter->GetOutput());
}
template <class TPanImageType, class TXsImageType, class TOutputImageType, class TInternalPrecision>
......
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