1 #ifndef _ITKINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX
2 #define _ITKINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX
3 /* =========================================================================
5 @file itkBSplineInterpolateImageFunctionWithLUT.txx
6 @author David Sarrut <david.sarrut@creatis.insa-lyon.fr>
9 * CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image).
10 All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12 * Léon Bérard cancer center, 28 rue Laënnec, 69373 Lyon cedex 08, France
13 * http://www.creatis.insa-lyon.fr/rio
15 This software is distributed WITHOUT ANY WARRANTY; without even the
16 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17 PURPOSE. See the above copyright notices for more information.
19 ========================================================================= */
22 //====================================================================
23 template <class TImageType, class TCoordRep, class TCoefficientType>
24 BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
25 BSplineInterpolateImageFunctionWithLUT():Superclass() {
27 //for(int i=0; i<TImageType::ImageDimension; i++) mOutputSpacing[i] = -1;
28 SetLUTSamplingFactor(20);
30 mWeightsAreUpToDate = false;
31 // Following need to be pointer beacause values are updated into
33 // mIntrinsecError = new double;
34 // mNumberOfError = new long;
35 // mIntrinsecErrorMax = new double;
36 // mInputIsCoef = false;
39 //====================================================================
41 //====================================================================
42 template <class TImageType, class TCoordRep, class TCoefficientType>
43 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
44 SetLUTSamplingFactor(const int& s) {
45 for(int i=0; i<TImageType::ImageDimension; i++) mSamplingFactors[i] = s;
46 mWeightsAreUpToDate = false;
49 //====================================================================
51 //====================================================================
52 template <class TImageType, class TCoordRep, class TCoefficientType>
53 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
54 SetLUTSamplingFactors(const SizeType& s) {
55 for(int i=0; i<TImageType::ImageDimension; i++) mSamplingFactors[i] = s[i];
56 mWeightsAreUpToDate = false;
59 //====================================================================
61 // //====================================================================
62 // template <class TImageType, class TCoordRep, class TCoefficientType>
63 // void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
64 // SetOutputSpacing(const SpacingType & s) {
65 // for(int i=0; i<TImageType::ImageDimension; i++)
66 // mOutputSpacing[i] = s[i];
67 // // mWeightsAreUpToDate = false;
69 //====================================================================
71 //====================================================================
72 template <class TImageType, class TCoordRep, class TCoefficientType>
73 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
74 SetSplineOrder(const unsigned int& SplineOrder) {
75 Superclass::SetSplineOrder(SplineOrder);
76 // Compute support and half size
77 static const int d = TImageType::ImageDimension;
78 for(int l=0; l<d; l++) {
79 mSplineOrders[l]= SplineOrder;
80 mSupport[l] = SplineOrder+1;
81 if (mSupport[l] % 2 == 0) { // support is even
82 mHalfSupport[l] = mSupport[l]/2-1;
84 else mHalfSupport[l] = mSupport[l]/2; // support is odd (like cubic spline)
87 for(int l=0; l<d; l++) {
88 mSupportSize *= mSupport[l];
90 mWeightsAreUpToDate = false;
92 //====================================================================
95 //====================================================================
96 template <class TImageType, class TCoordRep, class TCoefficientType>
97 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
98 SetSplineOrders(const SizeType& SplineOrders) {
99 mSplineOrders=SplineOrders;
101 // Compute support and half size
102 static const int d = TImageType::ImageDimension;
103 for(int l=0; l<d; l++) {
104 mSupport[l] = mSplineOrders[l]+1;
105 if (mSupport[l] % 2 == 0) { // support is even
106 mHalfSupport[l] = mSupport[l]/2-1;
108 else mHalfSupport[l] = mSupport[l]/2; // support is odd (like cubic spline)
111 for(int l=0; l<d; l++) {
112 mSupportSize *= mSupport[l];
114 mWeightsAreUpToDate = false;
116 //====================================================================
118 //====================================================================
119 template <class TImageType, class TCoordRep, class TCoefficientType>
120 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
121 SetInputImage(const TImageType * inputData) {
123 //==============================
124 // if (!mInputIsCoef)
126 Superclass::SetInputImage(inputData);
129 //==============================
130 // //JV Don't call superclass (decomposition filter is executeed each time!)
133 // this->m_Coefficients = inputData;
134 // if ( this->m_Coefficients.IsNotNull())
136 // this->m_DataLength = this->m_Coefficients->GetBufferedRegion().GetSize();
139 // //Call super-superclass in case more input arrives
140 // itk::ImageFunction<TImageType, ITK_TYPENAME itk::NumericTraits<typename TImageType::PixelType>::RealType, TCoefficientType>::SetInputImage(inputData);
142 if (!inputData) return;
143 UpdateWeightsProperties();
147 //====================================================================
148 template <class TImageType, class TCoordRep, class TCoefficientType>
149 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
150 UpdateWeightsProperties() {
152 // Compute Memory offset inside coefficients images (for looping over coefficients)
153 static const unsigned int d = TImageType::ImageDimension;
154 mInputMemoryOffset[0] = 1;
155 for(unsigned int l=1; l<d; l++) {
156 mInputMemoryOffset[l] =
157 mInputMemoryOffset[l-1]*this->m_Coefficients->GetLargestPossibleRegion().GetSize(l-1);
161 if (!mWeightsAreUpToDate)
163 // Compute mSupportOffset according to input size
164 mSupportOffset.resize(mSupportSize);
165 mSupportIndex.resize(mSupportSize);
166 for(unsigned int l=0; l<d; l++) mSupportIndex[0][l] = 0;
167 for(unsigned int k=0; k<mSupportSize; k++) {
169 mSupportOffset[k] = Index2Offset<TImageType::ImageDimension>(mSupportIndex[k], mInputMemoryOffset);
170 // next coefficient index
171 if (k != mSupportSize-1) {
172 for(unsigned int l=0; l<d; l++) mSupportIndex[k+1][l] = mSupportIndex[k][l];
176 mSupportIndex[k+1][l]++;
177 if (static_cast<unsigned int>(mSupportIndex[k+1][l]) == mSupport[l]) {
178 mSupportIndex[k+1][l] = 0;
187 // for(unsigned int l=0; l<d; l++) {
188 // if (mOutputSpacing[l] == -1) {
189 // std::cerr << "Please use SetOutputSpacing before using BLUT interpolator" << std::endl;
194 // Compute BSpline weights if not up to date
195 //if (!mWeightsAreUpToDate)
196 UpdatePrecomputedWeights();
199 // *mIntrinsecErrorMax = *mIntrinsecError = 0.0;
200 // *mNumberOfError = 0;
202 //====================================================================
204 //====================================================================
205 template <class TImageType, class TCoordRep, class TCoefficientType>
206 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
207 UpdatePrecomputedWeights() {
208 // mLUTTimer.Reset();
209 // mLUTTimer.Start();
210 mWeightsCalculator.SetSplineOrders(mSplineOrders);
211 mWeightsCalculator.SetSamplingFactors(mSamplingFactors);
212 mWeightsCalculator.ComputeTensorProducts();
213 mWeightsAreUpToDate = true;
215 // coef = new TCoefficientType[mSupportSize];
216 // mCorrectedSupportIndex.resize(mSupportSize);
217 // mCorrectedSupportOffset.resize(mSupportSize);
219 // mLUTTimer.Print("LUT \t");
221 //====================================================================
223 //====================================================================
224 template <class TImageType, class TCoordRep, class TCoefficientType>
225 typename BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::IndexType
226 BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
227 GetSampleIndexOfPixelPosition(const ContinuousIndexType & x, IndexType & EvaluateIndex) const {
230 WARNING : sometimes, a floating number x could not really be
231 represented in memory. In this case, the difference between x and
232 floor(x) can be almost 1 (instead of 0). So we take into account
233 such special case, otherwise it could lead to annoying results.
235 // static const TCoefficientType tiny = 1.0e-7;
238 for(int l=0; l<TImageType::ImageDimension; l++)
240 // bool mChange = false;
242 // Compute t1 = distance to floor
243 TCoefficientType t1 = x[l]- vcl_floor(x[l]);
245 // Compute index in precomputed weights table
246 TCoefficientType t2 = mSamplingFactors[l]*t1;
247 index[l] = (IndexValueType)lrint(t2);
249 // For even order : test if too close to 0.5 (but lower). In this
250 // case : take the next coefficient
251 if (!(mSplineOrders[l] & 1)) {
253 if (mSamplingFactors[l] & 1) {
254 if (index[l] == (int) mSamplingFactors[l]/2+1) EvaluateIndex[l] = EvaluateIndex[l]+1;
257 else if (index[l] == (int) mSamplingFactors[l]/2) EvaluateIndex[l] = EvaluateIndex[l]+1;
261 // Statistics (to be removed)
263 *mIntrinsecError += fabs(index[l]-t2);
265 if (fabs(index[l]-t2)> *mIntrinsecErrorMax) *mIntrinsecErrorMax = fabs(index[l]-t2);
268 // When to close to 1, take the next coefficient for odd order, but
269 // only change index for odd
270 if (index[l] == (int)mSamplingFactors[l]) {
272 if (mSplineOrders[l] & 1) EvaluateIndex[l] = EvaluateIndex[l]+1;
281 //====================================================================
283 //====================================================================
284 template <class TImageType, class TCoordRep, class TCoefficientType>
285 typename BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::OutputType
286 BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
287 EvaluateAtContinuousIndex(const ContinuousIndexType & x) const {
289 // For shorter coding
290 static const unsigned int d = TImageType::ImageDimension;
292 // Compute the index of the first interpolation coefficient in the coefficient image
293 IndexType evaluateIndex;
295 for (unsigned int l=0; l<d; l++) {
296 if (mSplineOrders[l] & 1) { // Use this index calculation for odd splineOrder (like cubic)
297 indx = (long)vcl_floor(x[l]) - mSplineOrders[l] / 2 ; //this->m_SplineOrder / 2;
298 evaluateIndex[l] = indx;
300 else { // Use this index calculation for even splineOrder
301 if (mSplineOrders[l] == 0) evaluateIndex[l] = (long)rint(x[l]);
303 indx = (long)vcl_floor((x[l]+ 0.5)) - mSplineOrders[l] / 2; //this->m_SplineOrder / 2;
304 evaluateIndex[l] = indx;
309 // Compute index of precomputed weights and get pointer to first weights
310 const IndexType weightIndex = GetSampleIndexOfPixelPosition(x, evaluateIndex);
311 const TCoefficientType * pweights = mWeightsCalculator.GetFirstTensorProduct(weightIndex);
314 bool boundaryCase = false;
315 for (unsigned int l=0; l<d; l++) {
316 if ((evaluateIndex[l] < 0) ||
317 (evaluateIndex[l]+mSupport[l]) >= this->m_Coefficients->GetLargestPossibleRegion().GetSize(l)) {
322 // Pointer to support offset
323 const int * psupport;
325 // Special case for boundary (to be changed ....)
326 std::vector<int> correctedSupportOffset;
329 //std::vector<TCoefficientType> coef(mSupportSize);
330 // DD(EvaluateIndex);
331 //std::vector<int> CorrectedSupportOffset;//(mSupportSize);
332 std::vector<IndexType> correctedSupportIndex;//(mSupportSize);
333 correctedSupportIndex.resize(mSupportSize);
334 correctedSupportOffset.resize(mSupportSize);
335 for(unsigned int i=0; i<mSupportSize; i++) {
336 // DD(mSupportIndex[i]);
337 for (unsigned int l=0; l<d; l++) {
338 long a = mSupportIndex[i][l] + evaluateIndex[l];
339 long b = this->m_Coefficients->GetLargestPossibleRegion().GetSize(l);
344 correctedSupportIndex[i][l] = -a - d2*(-a/d2) - evaluateIndex[l];//mSupportIndex[i][l]-a;
348 correctedSupportIndex[i][l] = d2 - a - evaluateIndex[l];
351 correctedSupportIndex[i][l] = mSupportIndex[i][l]; //a - d2*(a/d2) - EvaluateIndex[l];
355 correctedSupportIndex[i][l] = d2 - a - EvaluateIndex[l];//mSupportIndex[i][l] - (a-(b-1));
358 correctedSupportIndex[i][l] = mSupportIndex[i][l];
363 // DD(correctedSupportIndex[i]);
364 correctedSupportOffset[i] = itk::Index2Offset<TImageType::ImageDimension>(correctedSupportIndex[i], mInputMemoryOffset);
366 // for (unsigned int l=0; l<d; l++) {
367 // EvaluateIndex[l] = EvaluateIndex[l] + correctedSupportIndex[0][l];
369 // DD(EvaluateIndex);
370 psupport = &correctedSupportOffset[0];
373 psupport = &mSupportOffset[0];
376 // Get pointer to first coefficient. Even if in some boundary cases,
377 // EvaluateIndex is out of the coefficient image,
378 const TCoefficientType * pcoef = &(this->m_Coefficients->GetPixel(evaluateIndex));
380 // Main loop over BSpline support
381 TCoefficientType interpolated = 0.0;
382 for (unsigned int p=0; p<mSupportSize; p++) {
383 interpolated += pcoef[*psupport] * (*pweights);
388 // Return interpolated value
389 return(interpolated);
391 //====================================================================
394 #endif //_ITKINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX