Skip to content
Snippets Groups Projects
Commit 88d3d0e7 authored by Rémi Cresson's avatar Rémi Cresson
Browse files

ADD: Move Mosaic remote module in OTB

parent e7720786
No related branches found
No related tags found
No related merge requests found
/*
* Copyright (C) 1999-2011 Insight Software Consortium
* Copyright (C) 2005-2019 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 otbStreamingStatisticsWithHistMapFromLabelImageFilter_h
#define otbStreamingStatisticsWithHistMapFromLabelImageFilter_h
#include "otbPersistentImageFilter.h"
#include "itkNumericTraits.h"
#include "itkArray.h"
#include "itkSimpleDataObjectDecorator.h"
#include "otbPersistentFilterStreamingDecorator.h"
#include "otbStreamingStatisticsAccumulators.h"
namespace otb
{
/** \class PersistentStreamingStatisticsWithHistMapFromLabelImageFilter
* \brief Computes mean radiometric value for each label of a label image, based on a support VectorImage
*
* This filter persists its temporary data. It means that if you Update it n times on n different
* requested regions, the output statistics will be the statitics of the whole set of n regions.
*
* To reset the temporary data, one should call the Reset() function.
*
* To get the statistics once the regions have been processed via the pipeline, use the Synthetize() method.
*
*
* \sa StreamingStatisticsWithHistMapFromLabelImageFilter
* \ingroup Streamed
* \ingroup Multithreaded
* \ingroup MathematicalStatisticsImageFilters
*
* \ingroup OTBStatistics
*/
template<class TInputVectorImage, class TLabelImage>
class ITK_EXPORT PersistentStreamingStatisticsWithHistMapFromLabelImageFilter :
public PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
{
public:
/** Standard Self typedef */
typedef PersistentStreamingStatisticsWithHistMapFromLabelImageFilter Self;
typedef PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage> 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(PersistentStreamingStatisticsWithHistMapFromLabelImageFilter, PersistentStreamingStatisticsMapFromLabelImageFilter);
/** Image related typedefs. */
typedef TInputVectorImage VectorImageType;
typedef typename TInputVectorImage::Pointer InputVectorImagePointer;
typedef TLabelImage LabelImageType;
typedef typename TLabelImage::Pointer LabelImagePointer;
typedef typename VectorImageType::RegionType RegionType;
typedef typename VectorImageType::PixelType VectorPixelType;
typedef typename VectorImageType::PixelType::ValueType VectorPixelValueType;
typedef typename LabelImageType::PixelType LabelPixelType;
typedef itk::VariableLengthVector<double> RealVectorPixelType;
typedef StatisticsAccumulator<RealVectorPixelType> AccumulatorType;
typedef std::unordered_map<LabelPixelType, AccumulatorType > AccumulatorMapType;
typedef std::vector<AccumulatorMapType> AccumulatorMapCollectionType;
typedef std::unordered_map<LabelPixelType, RealVectorPixelType > PixelValueMapType;
typedef std::unordered_map<LabelPixelType, double> LabelPopulationMapType;
// typedef std::unordered_map<double,std::unordered_map<LabelPixelType,
// std::unordered_map<double, double>>> HistogramMap;
itkStaticConstMacro(InputImageDimension, unsigned int,
TInputVectorImage::ImageDimension);
/** Image related typedefs. */
itkStaticConstMacro(ImageDimension, unsigned int,
TInputVectorImage::ImageDimension);
itkGetMacro(NoDataValue, VectorPixelValueType);
itkSetMacro(NoDataValue, VectorPixelValueType);
itkGetMacro(UseNoDataValue, bool);
itkSetMacro(UseNoDataValue, bool);
/** Smart Pointer type to a DataObject. */
typedef typename itk::DataObject::Pointer DataObjectPointer;
typedef itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType;
typedef itk::ImageBase<InputImageDimension> ImageBaseType;
typedef typename ImageBaseType::RegionType InputImageRegionType;
/** Type of DataObjects used for scalar outputs */
typedef itk::SimpleDataObjectDecorator<PixelValueMapType> PixelValueMapObjectType;
/** Set input label image */
virtual void SetInputLabelImage( const LabelImageType *image);
/** Get input label image */
virtual const LabelImageType * GetInputLabelImage();
/** Return the computed Mean for each label in the input label image */
PixelValueMapType GetMeanValueMap() const;
/** Return the computed Standard Deviation for each label in the input label image */
PixelValueMapType GetStandardDeviationValueMap() const;
/** Return the computed Min for each label in the input label image */
PixelValueMapType GetMinValueMap() const;
/** Return the computed Max for each label in the input label image */
PixelValueMapType GetMaxValueMap() const;
/** Return the computed number of labeled pixels for each label in the input label image */
LabelPopulationMapType GetLabelPopulationMap() const;
// /** Return the computed histogram */
// HistogramMap GetHistogramMap() const;
/** Make a DataObject of the correct type to be used as the specified
* output. */
DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) override;
using Superclass::MakeOutput;
/** Pass the input through unmodified. Do this by Grafting in the
* AllocateOutputs method.
*/
void AllocateOutputs() override;
void GenerateOutputInformation() override;
void Synthetize(void) override;
void Reset(void) override;
/** Due to heterogeneous input template GenerateInputRequestedRegion must be reimplemented using explicit cast **/
/** This new implementation is inspired by the one of itk::ImageToImageFilter **/
void GenerateInputRequestedRegion() override;
protected:
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter();
~PersistentStreamingStatisticsWithHistMapFromLabelImageFilter() override {}
void PrintSelf(std::ostream& os, itk::Indent indent) const override;
void ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId ) override;
private:
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter(const Self &) = delete;
void operator =(const Self&) = delete;
VectorPixelValueType m_NoDataValue;
bool m_UseNoDataValue;
AccumulatorMapCollectionType m_AccumulatorMaps;
PixelValueMapType m_MeanRadiometricValue;
PixelValueMapType m_StDevRadiometricValue;
PixelValueMapType m_MinRadiometricValue;
PixelValueMapType m_MaxRadiometricValue;
LabelPopulationMapType m_LabelPopulation;
// HistogramMap m_Histogram;
}; // end of class PersistentStreamingStatisticsWithHistMapFromLabelImageFilter
/*===========================================================================*/
/** \class StreamingStatisticsWithHistMapFromLabelImageFilter
* \brief Computes mean radiometric value for each label of a label image, based on a support VectorImage
*
* Currently the class only computes the mean value.
*
* This class streams the whole input image through the PersistentStreamingStatisticsWithHistMapFromLabelImageFilter.
*
* This way, it allows computing the first order global statistics of this image.
* It calls the Reset() method of the PersistentStatisticsImageFilter before streaming
* the image and the Synthetize() method of the PersistentStatisticsImageFilter
* after having streamed the image to compute the statistics.
* The accessor on the results are wrapping the accessors of the
* internal PersistentStatisticsImageFilter.
*
* This filter can be used as:
* \code
* typedef otb::StreamingStatisticsWithHistMapFromLabelImageFilter<ImageType> StatisticsType;
* StatisticsType::Pointer statistics = StatisticsType::New();
* statistics->SetInput(reader->GetOutput());
* statistics->Update();
* StatisticsType::PixelValueMapType meanValueMap = statistics->GetMeanValueMap();
* StatisticsType::PixelValueMapType::const_iterator end = meanValueMap();
* for (StatisticsType::PixelValueMapType::const_iterator it = meanValueMap.begin(); it != end; ++it)
* {
* std::cout << "label : " << it->first << " , ";
* << "mean value : " << it->second << std::endl;
* }
* \endcode
*
*
* \sa PersistentStatisticsImageFilter
* \sa PersistentImageFilter
* \sa PersistentFilterStreamingDecorator
* \sa StreamingImageVirtualWriter
*
* \ingroup Streamed
* \ingroup Multithreaded
* \ingroup MathematicalStatisticsImageFilters
*
* \ingroup OTBStatistics
*/
template<class TInputVectorImage, class TLabelImage>
class ITK_EXPORT StreamingStatisticsWithHistMapFromLabelImageFilter :
public PersistentFilterStreamingDecorator<PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage> >
{
public:
/** Standard Self typedef */
typedef StreamingStatisticsWithHistMapFromLabelImageFilter Self;
typedef PersistentFilterStreamingDecorator
<PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage> > Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Type macro */
itkNewMacro(Self);
/** Creation through object factory macro */
itkTypeMacro(StreamingStatisticsWithHistMapFromLabelImageFilter, PersistentFilterStreamingDecorator);
typedef TInputVectorImage VectorImageType;
typedef TLabelImage LabelImageType;
typedef typename VectorImageType::PixelType VectorPixelType;
typedef typename VectorImageType::PixelType::ValueType VectorPixelValueType;
typedef typename Superclass::FilterType::PixelValueMapType PixelValueMapType;
typedef typename Superclass::FilterType::PixelValueMapObjectType PixelValueMapObjectType;
typedef typename Superclass::FilterType::LabelPopulationMapType LabelPopulationMapType;
// typedef typename Superclass::FilterType::HistogramMap HistogramMap;
/** Set input multispectral image */
using Superclass::SetInput;
void SetInput(const VectorImageType * input)
{
this->GetFilter()->SetInput(input);
}
/** Get input multispectral image */
const VectorImageType * GetInput()
{
return this->GetFilter()->GetInput();
}
/** Set input label image (monoband) */
void SetInputLabelImage(const LabelImageType * input)
{
this->GetFilter()->SetInputLabelImage(input);
}
/** Get input label image (monoband) */
const LabelImageType * GetInputLabelImage()
{
return this->GetFilter()->GetInputLabelImage();
}
/** Return the computed Mean for each label */
PixelValueMapType GetMeanValueMap() const
{
return this->GetFilter()->GetMeanValueMap();
}
/** Return the computed Standard Deviation for each label */
PixelValueMapType GetStandardDeviationValueMap() const
{
return this->GetFilter()->GetStandardDeviationValueMap();
}
/** Return the computed Min for each label */
PixelValueMapType GetMinValueMap() const
{
return this->GetFilter()->GetMinValueMap();
}
/** Return the computed Max for each label */
PixelValueMapType GetMaxValueMap() const
{
return this->GetFilter()->GetMaxValueMap();
}
/** Return the computed number of labeled pixels for each label */
LabelPopulationMapType GetLabelPopulationMap() const
{
return this->GetFilter()->GetLabelPopulationMap();
}
// /** Return the computed number of labeled pixels for each label */
// HistogramMap GetHistogramMap() const
// {
// return this->GetFilter()->GetHistogramMap();
// }
/** Set the no data value */
void SetNoDataValue(VectorPixelValueType value)
{
this->GetFilter()->SetNoDataValue(value);
}
/** Return the no data value */
VectorPixelValueType GetNoDataValue() const
{
return this->GetFilter()->GetNoDataValue();
}
/** Configure whether no data pixels ignored, treating each band independently */
void SetUseNoDataValue(bool useNoDataValue)
{
this->GetFilter()->SetUseNoDataValue(useNoDataValue);
}
/** Return whether no data pixels are ignored */
bool GetUseNoDataValue() const
{
return this->GetFilter()->GetUseNoDataValue();
}
protected:
/** Constructor */
StreamingStatisticsWithHistMapFromLabelImageFilter() {}
/** Destructor */
~StreamingStatisticsWithHistMapFromLabelImageFilter() override {}
private:
StreamingStatisticsWithHistMapFromLabelImageFilter(const Self &) = delete;
void operator =(const Self&) = delete;
};
} // end namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbStreamingStatisticsWithHistMapFromLabelImageFilter.hxx"
#endif
#endif
/*
* Copyright (C) 1999-2011 Insight Software Consortium
* Copyright (C) 2005-2019 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 otbStreamingStatisticsWithHistMapFromLabelImageFilter_hxx
#define otbStreamingStatisticsWithHistMapFromLabelImageFilter_hxx
#include "otbStreamingStatisticsWithHistMapFromLabelImageFilter.h"
#include "itkInputDataObjectIterator.h"
#include "itkImageRegionIterator.h"
#include "itkProgressReporter.h"
#include "otbMacro.h"
#include <cmath>
namespace otb
{
template<class TInputVectorImage, class TLabelImage>
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::PersistentStreamingStatisticsWithHistMapFromLabelImageFilter()
: m_UseNoDataValue()
{
// first output is a copy of the image, DataObject created by
// superclass
//
// allocate the data objects for the outputs which are
// just decorators around pixel types
typename PixelValueMapObjectType::Pointer output
= static_cast<PixelValueMapObjectType*>(this->MakeOutput(1).GetPointer());
this->itk::ProcessObject::SetNthOutput(1, output.GetPointer());
this->Reset();
}
template<class TInputVectorImage, class TLabelImage>
typename itk::DataObject::Pointer
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::MakeOutput(DataObjectPointerArraySizeType itkNotUsed(output))
{
return static_cast<itk::DataObject*>(PixelValueMapObjectType::New().GetPointer());
}
template<class TInputVectorImage, class TLabelImage>
void
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::SetInputLabelImage(const LabelImageType *input)
{
// Process object is not const-correct so the const_cast is required here
this->itk::ProcessObject::SetNthInput(1,
const_cast< LabelImageType * >( input ) );
}
template<class TInputVectorImage, class TLabelImage>
const typename PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::LabelImageType*
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::GetInputLabelImage()
{
return static_cast< const TLabelImage * >
(this->itk::ProcessObject::GetInput(1));
}
template<class TInputVectorImage, class TLabelImage>
typename PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::PixelValueMapType
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::GetMeanValueMap() const
{
return m_MeanRadiometricValue;
}
template<class TInputVectorImage, class TLabelImage>
typename PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::PixelValueMapType
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::GetStandardDeviationValueMap() const
{
return m_StDevRadiometricValue;
}
template<class TInputVectorImage, class TLabelImage>
typename PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::PixelValueMapType
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::GetMinValueMap() const
{
return m_MinRadiometricValue;
}
template<class TInputVectorImage, class TLabelImage>
typename PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::PixelValueMapType
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::GetMaxValueMap() const
{
return m_MaxRadiometricValue;
}
template<class TInputVectorImage, class TLabelImage>
typename PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::LabelPopulationMapType
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::GetLabelPopulationMap() const
{
return m_LabelPopulation;
}
//template<class TInputVectorImage, class TLabelImage>
//typename PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::HistogramMap
//PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
//::GetHistogramMap() const
//{
// return m_Histogram;
//}
template<class TInputVectorImage, class TLabelImage>
void
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::GenerateOutputInformation()
{
Superclass::GenerateOutputInformation();
if (this->GetInput())
{
this->GetOutput()->CopyInformation(this->GetInput());
this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
{
this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
}
}
}
template<class TInputVectorImage, class TLabelImage>
void
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::AllocateOutputs()
{
// This is commented to prevent the streaming of the whole image for the first stream strip
// It shall not cause any problem because the output image of this filter is not intended to be used.
//InputImagePointer image = const_cast< TInputImage * >( this->GetInput() );
//this->GraftOutput( image );
// Nothing that needs to be allocated for the remaining outputs
}
template<class TInputVectorImage, class TLabelImage>
void
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::Synthetize()
{
// Update temporary accumulator
AccumulatorMapType outputAcc;
auto endAcc = outputAcc.end();
for (auto const& threadAccMap: m_AccumulatorMaps)
{
for(auto const& it: threadAccMap)
{
auto label = it.first;
auto itAcc = outputAcc.find(label);
if (itAcc == endAcc)
{
outputAcc.emplace(label, it.second);
}
else
{
itAcc->second.Update(it.second);
}
}
}
// Publish output maps
for(auto& it: outputAcc)
{
const LabelPixelType label = it.first;
const auto &bandCount = it.second.GetBandCount();
const auto &sum = it.second.GetSum();
const auto &sqSum = it.second.GetSqSum();
// Count
m_LabelPopulation[label] = it.second.GetCount();
// Mean & stdev
RealVectorPixelType mean (sum);
RealVectorPixelType std (sqSum);
for (unsigned int band = 0 ; band < mean.GetSize() ; band++)
{
// Number of valid pixels in band
auto count = bandCount[band];
// Mean
mean[band] /= count;
// // Histogram
// m_Histogram[band][label] = it.second.GetHisto();
// Unbiased standard deviation (not sure unbiased is usefull here)
const double variance = (sqSum[band] - (sum[band] * mean[band])) / (count - 1);
std[band] = std::sqrt(variance);
}
m_MeanRadiometricValue[label] = mean;
m_StDevRadiometricValue[label] = std;
// Min & max
m_MinRadiometricValue[label] = it.second.GetMin();
m_MaxRadiometricValue[label] = it.second.GetMax();
}
}
template<class TInputVectorImage, class TLabelImage>
void
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::Reset()
{
m_AccumulatorMaps.clear();
m_MeanRadiometricValue.clear();
m_StDevRadiometricValue.clear();
m_MinRadiometricValue.clear();
m_MaxRadiometricValue.clear();
m_LabelPopulation.clear();
// m_Histogram.clear();
m_AccumulatorMaps.resize(this->GetNumberOfThreads());
}
template<class TInputVectorImage, class TLabelImage>
void
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::GenerateInputRequestedRegion()
{
// The Requested Regions of all the inputs are set to their Largest Possible Regions
this->itk::ProcessObject::GenerateInputRequestedRegion();
// Iteration over all the inputs of the current filter (this)
for( itk::InputDataObjectIterator it( this ); !it.IsAtEnd(); it++ )
{
// Check whether the input is an image of the appropriate dimension
// dynamic_cast of all the input images as itk::ImageBase objects
// in order to pass the if ( input ) test whatever the inputImageType (vectorImage or labelImage)
ImageBaseType * input = dynamic_cast< ImageBaseType *>( it.GetInput() );
if ( input )
{
// Use the function object RegionCopier to copy the output region
// to the input. The default region copier has default implementations
// to handle the cases where the input and output are the same
// dimension, the input a higher dimension than the output, and the
// input a lower dimension than the output.
InputImageRegionType inputRegion;
this->CallCopyOutputRegionToInputRegion( inputRegion, this->GetOutput()->GetRequestedRegion() );
input->SetRequestedRegion(inputRegion);
}
}
}
template<class TInputVectorImage, class TLabelImage>
void
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId )
{
/**
* Grab the input
*/
InputVectorImagePointer inputPtr = const_cast<TInputVectorImage *>(this->GetInput());
LabelImagePointer labelInputPtr = const_cast<TLabelImage *>(this->GetInputLabelImage());
itk::ImageRegionConstIterator<TInputVectorImage> inIt(inputPtr, outputRegionForThread);
itk::ImageRegionConstIterator<TLabelImage> labelIt(labelInputPtr, outputRegionForThread);
itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
auto &acc = m_AccumulatorMaps[threadId];
auto endAcc = acc.end();
// do the work
for (inIt.GoToBegin(), labelIt.GoToBegin();
!inIt.IsAtEnd() && !labelIt.IsAtEnd();
++inIt, ++labelIt)
{
const auto &value = inIt.Get();
auto label = labelIt.Get();
// Update the accumulator
auto itAcc = acc.find(label);
if (itAcc == endAcc)
{
acc.emplace(label, AccumulatorType(this->GetNoDataValue(), this->GetUseNoDataValue(), value));
}
else
{
itAcc->second.Update(value);
}
progress.CompletedPixel();
}
}
template<class TInputVectorImage, class TLabelImage>
void
PersistentStreamingStatisticsWithHistMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
}
} // end namespace otb
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment