Skip to content
Snippets Groups Projects
Commit 68e2e745 authored by Antoine Regimbeau's avatar Antoine Regimbeau
Browse files

REFAC: change clampfilter to use a functor and be more generic

parent f1e15408
No related branches found
No related tags found
No related merge requests found
......@@ -21,7 +21,8 @@
#ifndef otbClampImageFilter_h
#define otbClampImageFilter_h
#include "itkImageToImageFilter.h"
#include "otbConvertTypeFunctor.h"
#include "itkUnaryFunctorImageFilter.h"
namespace otb
{
......@@ -45,61 +46,68 @@ namespace otb
* \ingroup OTBImageManipulation
*/
template <class TInputImage, class TOutputImage=TInputImage>
class ITK_EXPORT ClampImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>
class ITK_EXPORT ClampImageFilter
: public itk::UnaryFunctorImageFilter< TInputImage , TOutputImage ,
Functor::ConvertTypeFunctor <typename TInputImage::PixelType ,
typename TOutputImage::PixelType> >
{
public:
/** Standard class typedefs. */
typedef ClampImageFilter Self;
typedef itk::ImageToImageFilter<TInputImage, TOutputImage> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
typedef ClampImageFilter Self;
typedef itk::UnaryFunctorImageFilter< TInputImage , TOutputImage ,
Functor::ConvertTypeFunctor <typename TInputImage::PixelType ,
typename TOutputImage::PixelType> > Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
itkNewMacro( Self );
/** Run-time type information (and related methods). */
itkTypeMacro(ClampImageFilter, itk::ImageToImageFilter);
itkTypeMacro( ClampImageFilter , itk::UnaryFunctorImageFilter );
/** Some additional typedefs. */
typedef TInputImage InputImageType;
typedef typename InputImageType::ConstPointer InputImagePointer;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename InputImageType::PixelType InputImagePixelType;
/** Some additional typedefs. */
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::Pointer OutputImagePointer;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename OutputImageType::PixelType OutputImagePixelType;
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename OutputImageType::PixelType OutputImagePixelType;
typedef typename OutputImageType::InternalPixelType OutputInternalPixelType;
typedef typename itk::NumericTraits< OutputInternalPixelType >::ValueType OutputPixelValueType;
/** The values greater than or equal to the value are set to OutsideValue. */
void ClampAbove(const OutputImagePixelType &thresh);
void ClampAbove(const OutputPixelValueType &thresh);
/** The values less than or equal to the value are set to OutsideValue. */
void ClampBelow(const OutputImagePixelType &thresh);
void ClampBelow(const OutputPixelValueType &thresh);
/** The values outside the range are set to OutsideValue. */
void ClampOutside(const OutputImagePixelType &lower, const OutputImagePixelType &upper);
void ClampOutside(const OutputPixelValueType &lower, const OutputPixelValueType &upper);
/** Set/Get methods to set the lower threshold */
void SetLower(OutputImagePixelType val)
void SetLower(OutputPixelValueType val)
{
m_Lower = val;
m_DLower = static_cast<double>(val);
this->GetFunctor().SetLowest( m_Lower );
this->Modified();
}
itkGetConstMacro(Lower, OutputImagePixelType);
itkGetConstMacro(Lower, OutputPixelValueType);
/** Set/Get methods to set the upper threshold */
void SetUpper(OutputImagePixelType val)
void SetUpper(OutputPixelValueType val)
{
m_Upper = val;
m_DUpper = static_cast<double>(val);
this->GetFunctor().SetHighest( m_Upper );
this->Modified();
}
itkGetConstMacro(Upper, OutputImagePixelType);
itkGetConstMacro(Upper, OutputPixelValueType);
protected:
......@@ -117,14 +125,23 @@ protected:
*
* \sa ImageToImageFilter::ThreadedGenerateData(),
* ImageToImageFilter::GenerateData() */
void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
itk::ThreadIdType threadId ) ITK_OVERRIDE;
// void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
// itk::ThreadIdType threadId ) ITK_OVERRIDE;
void GenerateOutputInformation(void) ITK_OVERRIDE
{
Superclass::GenerateOutputInformation();
this->GetOutput()->SetNumberOfComponentsPerPixel( this->GetInput()->GetNumberOfComponentsPerPixel() );
// typename InputImageType::IndexType index;
// index.Fill(0);
// InputImagePixelType px = ->GetPixel( index );
unsigned int sizeIn = this->GetInput()->GetNumberOfComponentsPerPixel();
// sizeIn *= itk::NumericTraits < typename itk::NumericTraits< InputImagePixelType >::ValueType >
// :: GetLength();
this->GetOutput()->SetNumberOfComponentsPerPixel(
this->GetFunctor().GetOutputSize ( sizeIn ) );
}
private:
......@@ -134,8 +151,8 @@ private:
double m_DLower;
double m_DUpper;
OutputImagePixelType m_Lower;
OutputImagePixelType m_Upper;
OutputPixelValueType m_Lower;
OutputPixelValueType m_Upper;
};
......
......@@ -25,6 +25,7 @@
#include "otbClampImageFilter.h"
#include "itkImageRegionIterator.h"
#include "itkNumericTraits.h"
#include <limits>
#include "itkObjectFactory.h"
#include "itkProgressReporter.h"
......@@ -38,8 +39,8 @@ template <class TInputImage, class TOutputImage>
ClampImageFilter<TInputImage, TOutputImage>
::ClampImageFilter()
{
m_Lower = itk::NumericTraits<OutputImagePixelType>::NonpositiveMin();
m_Upper = itk::NumericTraits<OutputImagePixelType>::max();
m_Lower = std::numeric_limits < OutputPixelValueType >::lowest();
m_Upper = std::numeric_limits < OutputPixelValueType >::max();
m_DLower = static_cast<double>(m_Lower);
m_DUpper = static_cast<double>(m_Upper);
......@@ -70,14 +71,16 @@ ClampImageFilter<TInputImage, TOutputImage>
template <class TInputImage, class TOutputImage>
void
ClampImageFilter<TInputImage, TOutputImage>
::ClampAbove(const OutputImagePixelType &thresh)
::ClampAbove(const OutputPixelValueType &thresh)
{
if (m_Upper != thresh
|| m_Lower > itk::NumericTraits<OutputImagePixelType>::NonpositiveMin())
|| m_Lower > std::numeric_limits < OutputPixelValueType >::lowest())
{
m_Lower = itk::NumericTraits<OutputImagePixelType>::NonpositiveMin();
m_Lower = std::numeric_limits < OutputPixelValueType >::lowest();
m_Upper = thresh;
m_DUpper = static_cast<double>(m_Upper);
this->GetFunctor().SetLowest( m_Lower );
this->GetFunctor().SetHighest( m_Upper );
this->Modified();
}
}
......@@ -88,13 +91,15 @@ ClampImageFilter<TInputImage, TOutputImage>
template <class TInputImage, class TOutputImage>
void
ClampImageFilter<TInputImage, TOutputImage>
::ClampBelow(const OutputImagePixelType &thresh)
::ClampBelow(const OutputPixelValueType &thresh)
{
if (m_Lower != thresh || m_Upper < itk::NumericTraits<OutputImagePixelType>::max())
if (m_Lower != thresh || m_Upper < std::numeric_limits < OutputPixelValueType >::max())
{
m_Upper = std::numeric_limits < OutputPixelValueType >::max();
m_Lower = thresh;
m_DLower = m_Lower;
m_Upper = itk::NumericTraits<InputImagePixelType>::max();
this->GetFunctor().SetLowest( m_Lower );
this->GetFunctor().SetHighest( m_Upper );
this->Modified();
}
}
......@@ -106,7 +111,7 @@ ClampImageFilter<TInputImage, TOutputImage>
template <class TInputImage, class TOutputImage>
void
ClampImageFilter<TInputImage, TOutputImage>
::ClampOutside(const OutputImagePixelType &lower, const OutputImagePixelType &upper)
::ClampOutside(const OutputPixelValueType &lower, const OutputPixelValueType &upper)
{
if (lower > upper)
{
......@@ -120,6 +125,8 @@ ClampImageFilter<TInputImage, TOutputImage>
m_Upper = upper;
m_DLower = m_Lower;
m_DUpper = m_Upper;
this->GetFunctor().SetLowest( m_Lower );
this->GetFunctor().SetHighest( m_Upper );
this->Modified();
}
}
......@@ -128,62 +135,62 @@ ClampImageFilter<TInputImage, TOutputImage>
/**
*
*/
template <class TInputImage, class TOutputImage>
void
ClampImageFilter<TInputImage, TOutputImage>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
itk::ThreadIdType threadId)
{
itkDebugMacro(<<"Actually executing");
// Get the input and output pointers
InputImagePointer inputPtr = this->GetInput();
OutputImagePointer outputPtr = this->GetOutput(0);
// Define/declare an iterator that will walk the output region for this
// thread.
typedef itk::ImageRegionConstIterator<TInputImage> InputIterator;
typedef itk::ImageRegionIterator<TOutputImage> OutputIterator;
InputIterator inIt(inputPtr, outputRegionForThread);
OutputIterator outIt(outputPtr, outputRegionForThread);
// support progress methods/callbacks
itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
// walk the regions, threshold each pixel
while( !outIt.IsAtEnd() && !inIt.IsAtEnd() )
{
// Cast the value of the pixel to double in order to compare
// with the double version of the upper and the lower bounds of
// output image
const double value = static_cast<double>(inIt.Get());
OutputImagePixelType outPix = m_Lower;
if ( m_DLower <= value && value <= m_DUpper)
{
// pixel passes to output unchanged
outPix = static_cast<OutputImagePixelType>(value);
}
/* Already outPix is initialized with m_Lower even for preventing Warning.
*
else if ( value < m_DLower )
{
outPix = m_Lower;
}
*/
else if ( value > m_DUpper)
{
outPix = m_Upper;
}
outIt.Set( outPix );
++inIt;
++outIt;
progress.CompletedPixel();
}
}
// template <class TInputImage, class TOutputImage>
// void
// ClampImageFilter<TInputImage, TOutputImage>
// ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
// itk::ThreadIdType threadId)
// {
// itkDebugMacro(<<"Actually executing");
// // Get the input and output pointers
// typename InputImageType::ConstPointer inputPtr = this->GetInput();
// typename OutputImageType::Pointer outputPtr = this->GetOutput(0);
// // Define/declare an iterator that will walk the output region for this
// // thread.
// typedef itk::ImageRegionConstIterator<TInputImage> InputIterator;
// typedef itk::ImageRegionIterator<TOutputImage> OutputIterator;
// InputIterator inIt(inputPtr, outputRegionForThread);
// OutputIterator outIt(outputPtr, outputRegionForThread);
// // support progress methods/callbacks
// itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
// // walk the regions, threshold each pixel
// while( !outIt.IsAtEnd() && !inIt.IsAtEnd() )
// {
// // Cast the value of the pixel to double in order to compare
// // with the double version of the upper and the lower bounds of
// // output image
// const double value = static_cast<double>(inIt.Get());
// OutputImagePixelType outPix = m_Lower;
// if ( m_DLower <= value && value <= m_DUpper)
// {
// // pixel passes to output unchanged
// outPix = static_cast<OutputImagePixelType>(value);
// }
// /* Already outPix is initialized with m_Lower even for preventing Warning.
// *
// else if ( value < m_DLower )
// {
// outPix = m_Lower;
// }
// */
// else if ( value > m_DUpper)
// {
// outPix = m_Upper;
// }
// outIt.Set( outPix );
// ++inIt;
// ++outIt;
// progress.CompletedPixel();
// }
// }
} // end namespace itk
......
/*
* 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 otbConvertTypeFunctor_h
#define otbConvertTypeFunctor_h
#include <limits>
#include <type_traits>
#include <boost/type_traits/is_complex.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include "itkVariableLengthVector.h"
#include "itkNumericTraits.h"
#include "otbDefaultConvertNewImpl.h"
namespace otb
{
namespace Functor
{
template < class TInputPixelType , class TOutputPixelType >
class ConvertTypeFunctor
{
public:
typedef TInputPixelType InputPixelType;
typedef TOutputPixelType OutputPixelType;
typedef ConvertTypeFunctor Self;
typedef typename itk::NumericTraits < InputPixelType > :: ValueType InputInternalPixelType;
typedef typename itk::NumericTraits < OutputPixelType > :: ValueType OutputInternalPixelType;
typedef typename itk::NumericTraits < InputInternalPixelType > :: ValueType InputPixelValueType;
typedef typename itk::NumericTraits < OutputInternalPixelType > :: ValueType OutputPixelValueType;
// template < class InternalPixelType >
unsigned int GetOutputSize( unsigned int sizeIn )
{
m_CompIn = sizeIn ;
if ( m_cInPix || m_cInInternalPix )
m_Scal = 2 * m_CompIn;
else
m_Scal = m_CompIn;
if ( m_cOutPix || m_cOutInternalPix )
{
m_CompOut = sizeIn / 2 ; // ( sizeIn + 1 )/ 2
return m_CompOut ;
}
else
{
m_CompOut = sizeIn ;
return m_CompOut ;
}
}
void SetLowest( OutputPixelValueType & lowest )
{
m_LowestB = lowest;
m_LowestBD = static_cast < double > ( m_LowestB );
}
void SetHighest( OutputPixelValueType & highest )
{
m_HighestB = highest;
m_HighestBD = static_cast < double > ( m_HighestB );
}
ConvertTypeFunctor()
{
m_LowestB = std::numeric_limits < OutputPixelValueType >::lowest();
m_HighestB = std::numeric_limits < OutputPixelValueType >::max();
m_LowestBD = static_cast < double > ( m_LowestB );
m_HighestBD = static_cast < double > ( m_HighestB );
m_cInPix = boost::is_complex < InputPixelType > :: value ;
m_cOutPix = boost::is_complex < OutputPixelType > :: value ;
m_cInInternalPix = boost::is_complex < InputInternalPixelType > :: value ;
m_cOutInternalPix = boost::is_complex < OutputInternalPixelType > :: value ;
m_MultiCompIn = ! ( boost::is_complex < InputPixelType > :: value )
|| ! ( boost::is_scalar < InputPixelType > :: value) ;
m_MultiCompOut = ! ( boost::is_complex < OutputPixelType > :: value )
|| ! ( boost::is_scalar < OutputPixelType > :: value);
}
OutputPixelType operator() ( InputPixelType const & in ) const
{
std::vector < double > vPixel;
for ( unsigned int i = 0 ; i < m_CompIn ; i ++)
FillIn < InputPixelType > ( i , in , vPixel );
Clamp( vPixel );
OutputPixelType out;
int hack = 1;
if ( m_cOutPix && !m_MultiCompOut )
hack += 1; // needed in case we have OutputPixelType == complex<t> as SetLength() will ask a length of 2!
itk::NumericTraits < OutputPixelType > :: SetLength( out , hack * m_CompOut );
for ( unsigned int i = 0 ; i < m_CompOut ; i ++)
FillOut < OutputPixelType > ( i , out , vPixel );
return out;
}
~ConvertTypeFunctor() {};
protected:
template <class PixelType ,
std::enable_if_t < std::is_arithmetic < PixelType > ::value , int > = 2 >
void FillIn( unsigned int i , InputPixelType const & pix , std::vector < double > & vPix ) const
{
vPix.push_back( DefaultConvertPixelTraitsTest < InputPixelType > ::
GetNthComponent( i , pix ) );
}
template <class PixelType ,
std::enable_if_t < boost::is_complex < PixelType > :: value , int > = 1 >
void FillIn( unsigned int i , InputPixelType const & pix , std::vector < double > & vPix ) const
{
PixelType comp = DefaultConvertPixelTraitsTest < InputPixelType > ::
GetNthComponent( i , pix );
vPix.push_back( static_cast < double > ( real( comp ) ) );
vPix.push_back( static_cast < double > ( imag( comp ) ) );
}
template <class PixelType ,
std::enable_if_t < !( boost::is_complex < PixelType > :: value || std::is_arithmetic < PixelType > ::value ) , int > = 0 >
void FillIn( unsigned int i , InputPixelType const & pix , std::vector < double > & vPix ) const
{
FillIn < InputInternalPixelType > ( i , pix , vPix );
}
void Clamp( std::vector < double > & vPixel ) const
{
assert( m_Scal == vPixel.size() );
for ( double & comp : vPixel )
{
if ( comp >= m_HighestBD )
comp = m_HighestBD;
else if ( comp <= m_LowestBD )
comp = m_LowestBD;
}
}
template <class PixelType ,
std::enable_if_t < std::is_arithmetic < PixelType > ::value , int > = 2 >
void FillOut( unsigned int i , OutputPixelType & pix , std::vector < double > & vPix ) const
{
DefaultConvertPixelTraitsTest < OutputPixelType > ::
SetNthComponent( i , pix , vPix[i] );
}
template <class PixelType ,
std::enable_if_t < boost::is_complex < PixelType > :: value , int > = 1 >
void FillOut( unsigned int i , OutputPixelType & pix , std::vector < double > & vPix ) const
{
DefaultConvertPixelTraitsTest < OutputPixelType > ::
SetNthComponent( i , pix ,
PixelType ( vPix[ 2 * i] , vPix[ 2 * i + 1] ) );
}
template <class PixelType ,
std::enable_if_t < !( boost::is_complex < PixelType > :: value || std::is_arithmetic < PixelType > ::value ) , int > = 0 >
void FillOut( unsigned int i , OutputPixelType & pix , std::vector < double > & vPix ) const
{
FillOut < OutputInternalPixelType > ( i , pix , vPix );
}
private:
ConvertTypeFunctor(const Self &) = delete;
void operator =(const Self&) = delete;
double m_LowestBD , m_HighestBD ;
OutputPixelValueType m_LowestB , m_HighestB ;
unsigned int m_CompIn , m_CompOut , m_Scal ;
bool m_cInPix , m_cInInternalPix , m_cOutPix , m_cOutInternalPix ,
m_MultiCompIn , m_MultiCompOut ;
};
} //end namespace Functor
} //end namespace otb
#endif
/*=========================================================================
*
* Copyright Insight Software Consortium
*
* 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.txt
*
* 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 otbDefaultConvertNewImp_h
#define otbDefaultConvertNewImp_h
#include "itkDefaultConvertPixelTraits.h"
namespace otb
{
template < typename PixelType>
class DefaultConvertPixelTraitsTest : public itk::DefaultConvertPixelTraits < PixelType >
{
};
template < typename T >
class DefaultConvertPixelTraitsTest < std::complex < T > > : public itk::DefaultConvertPixelTraits < std::complex < T > >
{
public:
typedef itk::DefaultConvertPixelTraits < std::complex < T > > SuperClass;
static typename SuperClass::TargetType GetNthComponent ( int , const typename SuperClass::TargetType & pixel )
{
return pixel;
}
};
} // end namespace
#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