diff --git a/Code/BasicFilters/otbBCOInterpolateImageFunction.h b/Code/BasicFilters/otbBCOInterpolateImageFunction.h new file mode 100644 index 0000000000000000000000000000000000000000..b717ea2cb297232777ff96dc2bf63383bd6ea0c8 --- /dev/null +++ b/Code/BasicFilters/otbBCOInterpolateImageFunction.h @@ -0,0 +1,157 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __otbBCOInterpolateImageFunction_h +#define __otbBCOInterpolateImageFunction_h + +#include "itkInterpolateImageFunction.h" +#include "vnl/vnl_vector.h" + +namespace otb +{ + +/** \class + * \brief + * + * + * + * + * + * + * + * + * \warning + * + * + * \sa + * + * \ingroup ImageFunctions ImageInterpolators + */ +template < + class TInputImage, + class TCoordRep = double> +class ITK_EXPORT BCOInterpolateImageFunction : + public itk::InterpolateImageFunction<TInputImage,TCoordRep> +{ +public: + /** Standard class typedefs. */ + typedef BCOInterpolateImageFunction Self; + typedef itk::InterpolateImageFunction<TInputImage,TCoordRep> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Run-time type information (and related methods). */ + itkTypeMacro(BCOInterpolateImageFunction, InterpolateImageFunction); + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** OutputType typedef support. */ + typedef typename Superclass::OutputType OutputType; + + /** InputImageType typedef support. */ + typedef typename Superclass::InputImageType InputImageType; + + /** InputPixelType typedef support. */ + typedef typename Superclass::InputPixelType InputPixelType; + + /** RealType typedef support. */ + //typedef typename Superclass::RealType RealType; + typedef typename itk::NumericTraits<typename TInputImage::PixelType>::RealType RealType; + + /** Dimension underlying input image. */ + itkStaticConstMacro(ImageDimension, unsigned int,Superclass::ImageDimension); + + /** Index typedef support. */ + typedef typename Superclass::IndexType IndexType; + typedef typename Superclass::IndexValueType IndexValueType; + + /** Point typedef support. */ + typedef typename Superclass::PointType PointType; + + /** ContinuousIndex typedef support. */ + typedef typename Superclass::ContinuousIndexType ContinuousIndexType; + + /** Coeficients container type.*/ + typedef vnl_vector<double> CoefContainerType; + + /** Interpolate the image at a point position + * + * Returns the interpolated image intensity at a + * specified point position. No bounds checking is done. + * The point is assume to lie within the image buffer. + * + * ImageFunction::IsInsideBuffer() can be used to check bounds before + * calling the method. */ + //virtual OutputType Evaluate( const PointType& point ) const;////////////////////////////////////////////////// + + /** Evaluate the function at a ContinuousIndex position + * + * Returns the linearly interpolated image intensity at a + * specified point position. No bounds checking is done. + * The point is assume to lie within the image buffer. + * + * ImageFunction::IsInsideBuffer() can be used to check bounds before + * calling the method. */ + virtual OutputType EvaluateAtContinuousIndex( const ContinuousIndexType & index ) const;///////////////////// + + /** Interpolate the image at an index position. + * + * Simply returns the image value at the + * specified index position. No bounds checking is done. + * The point is assume to lie within the image buffer. + * + * ImageFunction::IsInsideBuffer() can be used to check bounds before + * calling the method. */ + //virtual OutputType EvaluateAtIndex( const IndexType & index ) const;////////////////////////////////////////// + + /** Set/Get the window radius */ + virtual void SetRadius(unsigned int radius); + virtual unsigned int GetRadius() const; + + /** Set/Get the optimisation coefficient (Common values are -0.5, -0.75 or -1.0) */ + virtual void SetAlpha(double alpha); + virtual double GetAlpha() const; + + /** Compute the BCO coefficients. */ + void EvaluateCoef(); + +protected: + BCOInterpolateImageFunction(); + ~BCOInterpolateImageFunction(); + void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + BCOInterpolateImageFunction( const Self& ); //purposely not implemented + void operator=( const Self& ); //purposely not implemented + + /** Used radius for the BCO */ + double m_Radius; + /** Optimisation Coefficient */ + double m_Alpha; + /** Used BCO coefficiet */ + CoefContainerType m_BCOCoef; +}; + + +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbBCOInterpolateImageFunction.txx" +#endif + +#endif diff --git a/Code/BasicFilters/otbBCOInterpolateImageFunction.txx b/Code/BasicFilters/otbBCOInterpolateImageFunction.txx new file mode 100644 index 0000000000000000000000000000000000000000..929a50d7503fd3b4812af7a4f971dbdcadf4aa94 --- /dev/null +++ b/Code/BasicFilters/otbBCOInterpolateImageFunction.txx @@ -0,0 +1,225 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __otbProlateInterpolateImageFunction_txx +#define __otbProlateInterpolateImageFunction_txx + +#include "otbBCOInterpolateImageFunction.h" + +#include "itkNumericTraits.h" + +namespace otb +{ + +/** Constructor */ +template <class TInputImage, class TCoordRep> +BCOInterpolateImageFunction<TInputImage, TCoordRep> +::BCOInterpolateImageFunction() +{ + m_Radius = 1; + m_Alpha = -0.5; +} + +/** Destructor */ +template <class TInputImage, class TCoordRep> +BCOInterpolateImageFunction<TInputImage, TCoordRep> +::~BCOInterpolateImageFunction() +{ + +} + +template <class TInputImage, class TCoordRep> +void BCOInterpolateImageFunction<TInputImage, TCoordRep> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); +} + +template <class TInputImage, class TCoordRep> +typename BCOInterpolateImageFunction< TInputImage, TCoordRep > +::OutputType +BCOInterpolateImageFunction<TInputImage, TCoordRep> +::EvaluateAtContinuousIndex( const ContinuousIndexType & index ) const +{ + unsigned int dim; // index over dimension + unsigned int neighborNumber = (2*m_Radius+1) * (2*m_Radius+1); + + + /** + * Compute base index = closet index below point + * Compute distance from point to base index + */ + IndexType baseIndex; + double distance[ImageDimension]; + + for( dim = 0; dim < ImageDimension; dim++ ) + { + baseIndex[dim] = itk::Math::Floor< IndexValueType >( index[dim] ); + } + + /* + std::cout << "index : " << index << std::endl; + std::cout << "baseIndex : " << baseIndex << std::endl; + */ + + RealType value = 0; + + + IndexType neighIndex; + neighIndex.Fill(0); + + vnl_vector<RealType> lineRes(2*m_Radius+1, 0.); + + for( unsigned int counter = 0; counter < neighborNumber; counter++ ) + { + + unsigned int upper = counter; // each bit indicates upper/lower neighbour + double BCOCoefIndex; //link beetween counter and BCO Coeff. + + + // get neighbor index + for( dim = 0; dim < ImageDimension; dim++ ) + { + if ( upper & 1 ) + { + neighIndex[dim] = baseIndex[dim] + 1; +#ifdef ITK_USE_CENTERED_PIXEL_COORDINATES_CONSISTENTLY + // Take care of the case where the pixel is just + // in the outer upper boundary of the image grid. + if( neighIndex[dim] > this->m_EndIndex[dim] ) + { + neighIndex[dim] = this->m_EndIndex[dim]; + } +#endif + } + else + { + neighIndex[dim] = baseIndex[dim]; +#ifdef ITK_USE_CENTERED_PIXEL_COORDINATES_CONSISTENTLY + // Take care of the case where the pixel is just + // in the outer lower boundary of the image grid. + if( neighIndex[dim] < this->m_StartIndex[dim] ) + { + neighIndex[dim] = this->m_StartIndex[dim]; + } +#endif + } + + upper >>= 1; + } + // Proceed column + BCOCoefIndex = static_cast<int>(counter - floor(counter/(2*m_Radius+1))*(2*m_Radius+1)); + lineRes[BCOCoefIndex] = lineRes[BCOCoefIndex] + + static_cast<RealType>( this->GetInputImage()->GetPixel( neighIndex ) ) * m_BCOCoef(BCOCoefIndex) ; + } + + //Proceed line + for(unsigned int l=0; l<lineRes.size(); l++) + { + value = value + lineRes[l]*m_BCOCoef(l); + } + + std::cout << "Fin " << value / (2*m_Radius * 2*m_Radius) << std::endl; + return ( static_cast<OutputType>( value / (2*m_Radius * 2*m_Radius) ) ); +} + + + +template <class TInputImage, class TCoordRep> +void BCOInterpolateImageFunction<TInputImage, TCoordRep> +::SetRadius(unsigned int radius) +{ + if (radius == 0) + { + itkExceptionMacro(<< "Radius Must Be Strictly Superior to 0"); + } + else + { + m_Radius = radius; + } +} + +template <class TInputImage, class TCoordRep> +unsigned int BCOInterpolateImageFunction<TInputImage, TCoordRep> +::GetRadius() const +{ + return m_Radius; +} + +template <class TInputImage, class TCoordRep> +void BCOInterpolateImageFunction<TInputImage, TCoordRep> +::SetAlpha(double alpha) +{ + m_Alpha = alpha; +} + +template <class TInputImage, class TCoordRep> +double BCOInterpolateImageFunction<TInputImage, TCoordRep> +::GetAlpha() const +{ + return m_Alpha; +} + +template<class TInputImage, class TCoordRep> +void +BCOInterpolateImageFunction<TInputImage, TCoordRep> +::EvaluateCoef() +{ + // Init BCO coefficient container + unsigned int size = 2*m_Radius+1; + m_BCOCoef = CoefContainerType(size, 0.); + double val = 0.; + //double step = 1./static_cast<double>(m_Radius); + double step = 1./static_cast<double>(size); + + + // Compute BCO coefficients + for (unsigned int i = 0; i <= m_Radius; i++) + { + // Compute the distance according to alpha. + double d = val; + if( d <= 2. ) + { + if (d <= 1.) + { + m_BCOCoef[m_Radius+i] = (m_Alpha + 2.)*vcl_abs(vcl_pow(d, 3)) - (m_Alpha + 3.)*vcl_pow(d, 2) + 1; + } + else + { + m_BCOCoef[m_Radius+i] = m_Alpha*vcl_abs(vcl_pow(d, 3)) - 5*m_Alpha*vcl_pow(d, 2) + 8*m_Alpha*vcl_abs(d) - 4*m_Alpha; + } + } + else + { + m_BCOCoef[m_Radius+i] = 0; + } + + if(i>0) + { + // the filter is symtric + m_BCOCoef[m_Radius-i] = m_BCOCoef[m_Radius+i]; + } + val = val + step; + } + std::cout << m_BCOCoef << std::endl; + + } + + +} //namespace otb + +#endif diff --git a/Testing/Code/BasicFilters/CMakeLists.txt b/Testing/Code/BasicFilters/CMakeLists.txt index 568e3be66c5effc42df5d96109321ae2d16323f4..339410a01fc696436144b8f6867e0666e4315db0 100644 --- a/Testing/Code/BasicFilters/CMakeLists.txt +++ b/Testing/Code/BasicFilters/CMakeLists.txt @@ -673,7 +673,7 @@ ADD_TEST(bfTvProlateInterpolateImageFunction ${BASICFILTERS_TESTS6} ${TEMP}/bfProlateInterpolateImageFunctionCosOutput.tif ${TEMP}/bfProlateInterpolateImageFunctionITKCosOutput.tif ${TEMP}/bfProlateInterpolateImageFunctionProOutput.tif - 3 # radius + 50 # radius 0.5 0.5 127.33 44.9 259.67 21.43 @@ -733,6 +733,28 @@ ADD_TEST(bfTvWindowedSincInterpolateImageHammingFunction ${BASICFILTERS_TESTS6} -1 -1 ) +# ------- otb::BCOInterpolateImageFunction ------------------------------ + +ADD_TEST(bfTuBCOInterpolateImageFunctionNew ${BASICFILTERS_TESTS6} + otbBCOInterpolateImageFunctionNew) + +ADD_TEST(bfTvBCOInterpolateImageFunction ${BASICFILTERS_TESTS6} + otbBCOInterpolateImageFunction + ${INPUTDATA}/poupees.tif + ${TEMP}/bfBCOInterpolateImageFunctionOutput.txt + 50 # radius + -0.5 # optimised bicubic + 0.5 0.5 + 127.33 44.9 + 259.67 21.43 + 12.13 61.79 + 89.5 11 + 128 128 + 127.255 128.73 + -1 -1 + ) + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ otbBasicFiltersTests7 ~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1797,6 +1819,7 @@ otbWindowedSincInterpolateImageGaussianFunctionNew.cxx otbWindowedSincInterpolateImageGaussianFunction.cxx otbWindowedSincInterpolateImageHammingFunctionNew.cxx otbWindowedSincInterpolateImageHammingFunction.cxx +otbBCOInterpolateImageFunction.cxx ) # A enrichir diff --git a/Testing/Code/BasicFilters/otbBCOInterpolateImageFunction.cxx b/Testing/Code/BasicFilters/otbBCOInterpolateImageFunction.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a1ffa9cc88c202c4f476e1b55062827769caa010 --- /dev/null +++ b/Testing/Code/BasicFilters/otbBCOInterpolateImageFunction.cxx @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "itkExceptionObject.h" + +#include "otbBCOInterpolateImageFunction.h" +#include "otbVectorImage.h" +#include "otbImage.h" +#include "otbImageFileReader.h" +#include <fstream> + +int otbBCOInterpolateImageFunctionNew(int argc, char * argv[]) +{ + typedef otb::Image<double, 2> ImageType; + typedef otb::BCOInterpolateImageFunction<ImageType, double> InterpolatorType; + + // Instantiating object + InterpolatorType::Pointer filter = InterpolatorType::New(); + + return EXIT_SUCCESS; +} + +int otbBCOInterpolateImageFunction(int argc, char * argv[]) +{ + const char * infname = argv[1]; + const char * outfname = argv[2]; + const unsigned int radius = atoi(argv[3]); + const double alpha = atof(argv[4]); + + //typedef otb::VectorImage<double, 2> ImageType; + + typedef otb::Image<double, 2> ImageType; + typedef otb::BCOInterpolateImageFunction<ImageType, double> InterpolatorType; + typedef InterpolatorType::ContinuousIndexType ContinuousIndexType; + typedef otb::ImageFileReader<ImageType> ReaderType; + + int i = 5; + + std::vector<ContinuousIndexType> indicesList; + + while (i < argc && (i + 1) < argc) + { + ContinuousIndexType idx; + + idx[0] = atof(argv[i]); + idx[1] = atof(argv[i + 1]); + + indicesList.push_back(idx); + + i += 2; + } + + // Instantiating object + InterpolatorType::Pointer filter = InterpolatorType::New(); + + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(infname); + reader->Update();//TODO check if necessary + + std::cout << "Alpha Checking : " << std::endl << filter->GetAlpha() << std::endl; + filter->SetAlpha(-1.0); + std::cout << filter->GetAlpha() << std::endl; + filter->SetAlpha(alpha); + std::cout << filter->GetAlpha() << std::endl; + std::cout << "Radius Checking : " << std::endl << filter->GetRadius() << std::endl; + filter->SetRadius(radius); + std::cout << filter->GetRadius() << std::endl; + std::cout << "Coef Checking : " << std::endl; + filter->EvaluateCoef(); + std::cout << "Coef Generated ! " << std::endl; + + filter->SetInputImage(reader->GetOutput()); + + std::ofstream file; + file.open(outfname); + + for (std::vector<ContinuousIndexType>::iterator it = indicesList.begin(); it != indicesList.end(); ++it) + { + file << (*it) << " -> " << filter->EvaluateAtContinuousIndex((*it)) << std::endl; + } + + file.close(); + + + return EXIT_SUCCESS; +} diff --git a/Testing/Code/BasicFilters/otbBasicFiltersTests6.cxx b/Testing/Code/BasicFilters/otbBasicFiltersTests6.cxx index bd0cd5acc36215ac2925d8b6b7afab2d9370b2c4..3540b7dfd630bee59b4373e7cd25b0787fcfd79a 100644 --- a/Testing/Code/BasicFilters/otbBasicFiltersTests6.cxx +++ b/Testing/Code/BasicFilters/otbBasicFiltersTests6.cxx @@ -37,4 +37,6 @@ void RegisterTests() REGISTER_TEST(otbWindowedSincInterpolateImageGaussianFunction); REGISTER_TEST(otbWindowedSincInterpolateImageHammingFunctionNew); REGISTER_TEST(otbWindowedSincInterpolateImageHammingFunction); + REGISTER_TEST(otbBCOInterpolateImageFunctionNew); + REGISTER_TEST(otbBCOInterpolateImageFunction); }