/*========================================================================= Program: vv http://www.creatis.insa-lyon.fr/rio/vv Authors belong to: - University of LYON http://www.universite-lyon.fr/ - Léon Bérard cancer center http://www.centreleonberard.fr - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the copyright notices for more information. It is distributed under dual licence - BSD See included LICENSE.txt file - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html ===========================================================================**/ #ifndef _CLITKVECTORBSPLINEINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX #define _CLITKVECTORBSPLINEINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX /* ========================================================================= @file itkBSplineInterpolateImageFunctionWithLUT.txx @author jefvdmb@gmail.com Copyright (c) * CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details. * Léon Bérard cancer center, 28 rue Laënnec, 69373 Lyon cedex 08, France * http://www.creatis.insa-lyon.fr/rio 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. ========================================================================= */ namespace clitk { //==================================================================== template VectorBSplineInterpolateImageFunctionWithLUT:: VectorBSplineInterpolateImageFunctionWithLUT():Superclass() { // Set default values SetLUTSamplingFactor(20); SetSplineOrder(3); mWeightsAreUpToDate = false; } //==================================================================== //==================================================================== template void VectorBSplineInterpolateImageFunctionWithLUT:: SetLUTSamplingFactor(const int& s) { for(int i=0; i void VectorBSplineInterpolateImageFunctionWithLUT:: SetLUTSamplingFactors(const SizeType& s) { for(int i=0; i void VectorBSplineInterpolateImageFunctionWithLUT:: SetSplineOrder(const unsigned int& SplineOrder) { Superclass::SetSplineOrder(SplineOrder); // Compute support and half size static const int d = TImageType::ImageDimension; for(int l=0; l void VectorBSplineInterpolateImageFunctionWithLUT:: SetSplineOrders(const SizeType& SplineOrders) { mSplineOrders=SplineOrders; // Compute support and half size static const int d = TImageType::ImageDimension; for(int l=0; l void VectorBSplineInterpolateImageFunctionWithLUT:: SetInputImage(const TImageType * inputData) { // JV Call superclass (decomposition filter is executeed each time!) // JV Should call clitkVectorBSplineDecompositionFilterWithOBD to allow different order by dimension Superclass::SetInputImage(inputData); // Update the weightproperties if (!inputData) return; UpdateWeightsProperties(); } //==================================================================== template void VectorBSplineInterpolateImageFunctionWithLUT:: UpdateWeightsProperties() { // Compute Memory offset inside coefficients images (for looping over coefficients) static const unsigned int d = TImageType::ImageDimension; mInputMemoryOffset[0] = 1; for(unsigned int l=1; lm_Coefficients->GetLargestPossibleRegion().GetSize(l-1); } // Compute mSupportOffset according to input size mSupportOffset.resize(mSupportSize); mSupportIndex.resize(mSupportSize); for(unsigned int l=0; l(mSupportIndex[k], mInputMemoryOffset); // next coefficient index if (k != mSupportSize-1) { for(unsigned int l=0; l(mSupportIndex[k+1][l]) == mSupport[l]) { mSupportIndex[k+1][l] = 0; l++; } else stop = true; } } } // Compute BSpline weights if not up to date if (!mWeightsAreUpToDate) UpdatePrecomputedWeights(); } //==================================================================== //==================================================================== template void VectorBSplineInterpolateImageFunctionWithLUT:: UpdatePrecomputedWeights() { mWeightsCalculator.SetSplineOrders(mSplineOrders); mWeightsCalculator.SetSamplingFactors(mSamplingFactors); mWeightsCalculator.ComputeTensorProducts(); mWeightsAreUpToDate = true; } //==================================================================== //==================================================================== template typename VectorBSplineInterpolateImageFunctionWithLUT::IndexType VectorBSplineInterpolateImageFunctionWithLUT:: GetSampleIndexOfPixelPosition(const ContinuousIndexType & x, IndexType & EvaluateIndex) const { /* WARNING : sometimes, a floating number x could not really be represented in memory. In this case, the difference between x and floor(x) can be almost 1 (instead of 0). So we take into account such special case, otherwise it could lead to annoying results. */ // static const TCoefficientType tiny = 1.0e-7; IndexType index; for(int l=0; l(t2); // For even order : test if too close to 0.5 (but lower). In this // case : take the next coefficient if (!(mSplineOrders[l] & 1)) { if (t1<0.5) { if (mSamplingFactors[l] & 1) { if (index[l] == (int) mSamplingFactors[l]/2+1) EvaluateIndex[l] = EvaluateIndex[l]+1; } else if (index[l] == (int) mSamplingFactors[l]/2) EvaluateIndex[l] = EvaluateIndex[l]+1; } } // When to close to 1, take the next coefficient for odd order, but // only change index for odd if (index[l] == (int)mSamplingFactors[l]) { index[l] = 0; if (mSplineOrders[l] & 1) EvaluateIndex[l] = EvaluateIndex[l]+1; } } // The end return index; } //==================================================================== //==================================================================== template typename VectorBSplineInterpolateImageFunctionWithLUT::OutputType VectorBSplineInterpolateImageFunctionWithLUT:: EvaluateAtContinuousIndex(const ContinuousIndexType & x) const { // JV Compute BSpline weights if not up to date! Problem const: pass image as last // if (!mWeightsAreUpToDate) UpdatePrecomputedWeights(); // For shorter coding static const unsigned int d = TImageType::ImageDimension; // Compute the index of the first interpolation coefficient in the coefficient image IndexType evaluateIndex; long indx; for (unsigned int l=0; lm_SplineOrder / 2; evaluateIndex[l] = indx; } else { // Use this index calculation for even splineOrder if (mSplineOrders[l] == 0) evaluateIndex[l] = itk::Math::Round(x[l]); else { indx = (long)std::floor((x[l]+ 0.5)) - mSplineOrders[l] / 2; //this->m_SplineOrder / 2; evaluateIndex[l] = indx; } } } // Compute index of precomputed weights and get pointer to first weights const IndexType weightIndex = GetSampleIndexOfPixelPosition(x, evaluateIndex); const TCoefficientType * pweights = mWeightsCalculator.GetFirstTensorProduct(weightIndex); // Check boundaries bool boundaryCase = false; for (unsigned int l=0; l= this->m_Coefficients->GetLargestPossibleRegion().GetSize(l)) { boundaryCase = true; } } // Pointer to support offset const int * psupport; // Special case for boundary (to be changed ....) std::vector correctedSupportOffset; if (boundaryCase) { std::vector correctedSupportIndex;//(mSupportSize); correctedSupportIndex.resize(mSupportSize); correctedSupportOffset.resize(mSupportSize); for(unsigned int i=0; im_Coefficients->GetLargestPossibleRegion().GetSize(l); long d2 = 2 * b - 2; if (a < 0) { correctedSupportIndex[i][l] = -a - d2*(-a/d2) - evaluateIndex[l];//mSupportIndex[i][l]-a; } else { if (a>=b) { correctedSupportIndex[i][l] = d2 - a - evaluateIndex[l]; } else { correctedSupportIndex[i][l] = mSupportIndex[i][l]; //a - d2*(a/d2) - EvaluateIndex[l]; } /* if (a>=b) { correctedSupportIndex[i][l] = d2 - a - EvaluateIndex[l];//mSupportIndex[i][l] - (a-(b-1)); } else { correctedSupportIndex[i][l] = mSupportIndex[i][l]; } */ } } // DD(correctedSupportIndex[i]); correctedSupportOffset[i] = itk::Index2Offset(correctedSupportIndex[i], mInputMemoryOffset); } psupport = &correctedSupportOffset[0]; } else { psupport = &mSupportOffset[0]; } // Get pointer to first coefficient. Even if in some boundary cases, // EvaluateIndex is out of the coefficient image, //JV const CoefficientImagePixelType * pcoef = &(this->m_Coefficients->GetPixel(evaluateIndex)); // Main loop over BSpline support CoefficientImagePixelType interpolated = itk::NumericTraits::Zero;; for (unsigned int p=0; p void VectorBSplineInterpolateImageFunctionWithLUT:: EvaluateWeightsAtContinuousIndex(const ContinuousIndexType& x, const TCoefficientType ** pweights, IndexType & evaluateIndex)const { // JV Compute BSpline weights if not up to date! Problem const: pass image as last // if (!mWeightsAreUpToDate) UpdatePrecomputedWeights(); // For shorter coding static const unsigned int d = TImageType::ImageDimension; // Compute the index of the first interpolation coefficient in the coefficient image long indx; for (unsigned int l=0; lm_SplineOrder / 2; evaluateIndex[l] = indx; } else { // Use this index calculation for even splineOrder if (mSplineOrders[l] == 0) evaluateIndex[l] = itk::Math::Round(x[l]); else { indx = (long)std::floor((x[l]+ 0.5)) - mSplineOrders[l] / 2; //this->m_SplineOrder / 2; evaluateIndex[l] = indx; } } } // Compute index of precomputed weights and get pointer to first weights const IndexType weightIndex = GetSampleIndexOfPixelPosition(x, evaluateIndex); *pweights = mWeightsCalculator.GetFirstTensorProduct(weightIndex); } //==================================================================== } //end namespace #endif //_CLITKVECTORBSPLINEINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX