/* * 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 otbBCOInterpolateImageFunction_hxx #define otbBCOInterpolateImageFunction_hxx #include "otbBCOInterpolateImageFunction.h" #include "itkNumericTraits.h" namespace otb { template void BCOInterpolateImageFunctionBase::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Radius: " << m_Radius << std::endl; os << indent << "Alpha: " << m_Alpha << std::endl; } template void BCOInterpolateImageFunctionBase::SetRadius(unsigned int radius) { if (radius < 2) { itkExceptionMacro(<< "Radius must be strictly greater than 1"); } else { m_Radius = radius; m_WinSize = 2 * m_Radius + 1; } } template unsigned int BCOInterpolateImageFunctionBase::GetRadius() const { return m_Radius; } template void BCOInterpolateImageFunctionBase::SetAlpha(double alpha) { m_Alpha = alpha; } template double BCOInterpolateImageFunctionBase::GetAlpha() const { return m_Alpha; } template typename BCOInterpolateImageFunctionBase::CoefContainerType BCOInterpolateImageFunctionBase::EvaluateCoef(const ContinuousIndexValueType& indexValue) const { // Init BCO coefficient container CoefContainerType BCOCoef(m_WinSize, 0.); double offset, dist, position, step; offset = indexValue - itk::Math::Floor(indexValue + 0.5); // Compute BCO coefficients step = 4. / static_cast(2 * m_Radius); position = -static_cast(m_Radius) * step; double sum = 0.0; for (unsigned int i = 0; i < m_WinSize; ++i) { // Compute the BCO coefficients according to alpha. dist = std::abs(position - offset * step); if (dist <= 2.) { if (dist <= 1.) { BCOCoef[i] = (m_Alpha + 2.) * std::abs(dist * dist * dist) - (m_Alpha + 3.) * dist * dist + 1; } else { BCOCoef[i] = m_Alpha * std::abs(dist * dist * dist) - 5 * m_Alpha * dist * dist + 8 * m_Alpha * std::abs(dist) - 4 * m_Alpha; } } else { BCOCoef[i] = 0; } sum += BCOCoef[i]; position += step; } for (unsigned int i = 0; i < m_WinSize; ++i) BCOCoef[i] = BCOCoef[i] / sum; return BCOCoef; } template void BCOInterpolateImageFunction::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); } template typename BCOInterpolateImageFunction::OutputType BCOInterpolateImageFunction::EvaluateAtContinuousIndex(const ContinuousIndexType& index) const { unsigned int dim; IndexType baseIndex; IndexType neighIndex; RealType value = itk::NumericTraits::Zero; CoefContainerType BCOCoefX = this->EvaluateCoef(index[0]); CoefContainerType BCOCoefY = this->EvaluateCoef(index[1]); // Compute base index = closet index for (dim = 0; dim < ImageDimension; dim++) { baseIndex[dim] = itk::Math::Floor(index[dim] + 0.5); } for (unsigned int i = 0; i < this->m_WinSize; ++i) { RealType lineRes = 0.; for (unsigned int j = 0; j < this->m_WinSize; ++j) { // get neighbor index neighIndex[0] = baseIndex[0] + i - this->m_Radius; neighIndex[1] = baseIndex[1] + j - this->m_Radius; if (neighIndex[0] > this->m_EndIndex[0]) { neighIndex[0] = this->m_EndIndex[0]; } if (neighIndex[0] < this->m_StartIndex[0]) { neighIndex[0] = this->m_StartIndex[0]; } if (neighIndex[1] > this->m_EndIndex[1]) { neighIndex[1] = this->m_EndIndex[1]; } if (neighIndex[1] < this->m_StartIndex[1]) { neighIndex[1] = this->m_StartIndex[1]; } lineRes += static_cast(this->GetInputImage()->GetPixel(neighIndex)) * BCOCoefY[j]; } value += lineRes * BCOCoefX[i]; } return (static_cast(value)); } template void BCOInterpolateImageFunction, TCoordRep>::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); } template typename BCOInterpolateImageFunction, TCoordRep>::OutputType BCOInterpolateImageFunction, TCoordRep>::EvaluateAtContinuousIndex(const ContinuousIndexType& index) const { typedef typename itk::NumericTraits::ScalarRealType ScalarRealType; unsigned int dim; unsigned int componentNumber = this->GetInputImage()->GetNumberOfComponentsPerPixel(); IndexType baseIndex; IndexType neighIndex; std::vector lineRes(componentNumber); OutputType output(componentNumber); output.Fill(itk::NumericTraits::Zero); CoefContainerType BCOCoefX = this->EvaluateCoef(index[0]); CoefContainerType BCOCoefY = this->EvaluateCoef(index[1]); // Compute base index = closet index for (dim = 0; dim < ImageDimension; dim++) { baseIndex[dim] = itk::Math::Floor(index[dim] + 0.5); } for (unsigned int i = 0; i < this->m_WinSize; ++i) { std::fill(lineRes.begin(), lineRes.end(), itk::NumericTraits::Zero); for (unsigned int j = 0; j < this->m_WinSize; ++j) { // get neighbor index neighIndex[0] = baseIndex[0] + i - this->m_Radius; neighIndex[1] = baseIndex[1] + j - this->m_Radius; if (neighIndex[0] > this->m_EndIndex[0]) { neighIndex[0] = this->m_EndIndex[0]; } if (neighIndex[0] < this->m_StartIndex[0]) { neighIndex[0] = this->m_StartIndex[0]; } if (neighIndex[1] > this->m_EndIndex[1]) { neighIndex[1] = this->m_EndIndex[1]; } if (neighIndex[1] < this->m_StartIndex[1]) { neighIndex[1] = this->m_StartIndex[1]; } const InputPixelType& pixel = this->GetInputImage()->GetPixel(neighIndex); for (unsigned int k = 0; k < componentNumber; ++k) { lineRes[k] += pixel.GetElement(k) * BCOCoefY[j]; } } for (unsigned int k = 0; k < componentNumber; ++k) { output[k] += lineRes[k] * BCOCoefX[i]; } } return (output); } } // namespace otb #endif