1 #ifndef _CLITKVECTORBSPLINEINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX
2 #define _CLITKVECTORBSPLINEINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX
3 /* =========================================================================
5 @file itkBSplineInterpolateImageFunctionWithLUT.txx
6 @author jefvdmb@gmail.com
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 VectorBSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
25 VectorBSplineInterpolateImageFunctionWithLUT():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 VectorBSplineInterpolateImageFunctionWithLUT<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 VectorBSplineInterpolateImageFunctionWithLUT<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 VectorBSplineInterpolateImageFunctionWithLUT<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 VectorBSplineInterpolateImageFunctionWithLUT<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 VectorBSplineInterpolateImageFunctionWithLUT<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 VectorBSplineInterpolateImageFunctionWithLUT<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);
143 if (!inputData) return;
144 UpdateWeightsProperties();
148 //====================================================================
149 template <class TImageType, class TCoordRep, class TCoefficientType>
150 void VectorBSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
151 UpdateWeightsProperties() {
153 // Compute Memory offset inside coefficients images (for looping over coefficients)
154 static const unsigned int d = TImageType::ImageDimension;
155 mInputMemoryOffset[0] = 1;
156 for(unsigned int l=1; l<d; l++) {
157 mInputMemoryOffset[l] =
158 mInputMemoryOffset[l-1]*this->m_Coefficients->GetLargestPossibleRegion().GetSize(l-1);
162 if (!mWeightsAreUpToDate)
164 // Compute mSupportOffset according to input size
165 mSupportOffset.resize(mSupportSize);
166 mSupportIndex.resize(mSupportSize);
167 for(unsigned int l=0; l<d; l++) mSupportIndex[0][l] = 0;
168 for(unsigned int k=0; k<mSupportSize; k++) {
170 mSupportOffset[k] = itk::Index2Offset<TImageType::ImageDimension>(mSupportIndex[k], mInputMemoryOffset);
171 // next coefficient index
172 if (k != mSupportSize-1) {
173 for(unsigned int l=0; l<d; l++) mSupportIndex[k+1][l] = mSupportIndex[k][l];
177 mSupportIndex[k+1][l]++;
178 if (static_cast<unsigned int>(mSupportIndex[k+1][l]) == mSupport[l]) {
179 mSupportIndex[k+1][l] = 0;
188 // for(unsigned int l=0; l<d; l++) {
189 // if (mOutputSpacing[l] == -1) {
190 // std::cerr << "Please use SetOutputSpacing before using BLUT interpolator" << std::endl;
195 // Compute BSpline weights if not up to date
196 //if (!mWeightsAreUpToDate)
197 UpdatePrecomputedWeights();
200 // *mIntrinsecErrorMax = *mIntrinsecError = 0.0;
201 // *mNumberOfError = 0;
203 //====================================================================
205 //====================================================================
206 template <class TImageType, class TCoordRep, class TCoefficientType>
207 void VectorBSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
208 UpdatePrecomputedWeights() {
209 // mLUTTimer.Reset();
210 // mLUTTimer.Start();
211 mWeightsCalculator.SetSplineOrders(mSplineOrders);
212 mWeightsCalculator.SetSamplingFactors(mSamplingFactors);
213 mWeightsCalculator.ComputeTensorProducts();
214 mWeightsAreUpToDate = true;
216 // coef = new TCoefficientType[mSupportSize];
217 // mCorrectedSupportIndex.resize(mSupportSize);
218 // mCorrectedSupportOffset.resize(mSupportSize);
220 // mLUTTimer.Print("LUT \t");
222 //====================================================================
224 //====================================================================
225 template <class TImageType, class TCoordRep, class TCoefficientType>
226 typename VectorBSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::IndexType
227 VectorBSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
228 GetSampleIndexOfPixelPosition(const ContinuousIndexType & x, IndexType & EvaluateIndex) const {
231 WARNING : sometimes, a floating number x could not really be
232 represented in memory. In this case, the difference between x and
233 floor(x) can be almost 1 (instead of 0). So we take into account
234 such special case, otherwise it could lead to annoying results.
236 // static const TCoefficientType tiny = 1.0e-7;
239 for(int l=0; l<TImageType::ImageDimension; l++)
241 // bool mChange = false;
243 // Compute t1 = distance to floor
244 TCoefficientType t1 = x[l]- vcl_floor(x[l]);
246 // Compute index in precomputed weights table
247 TCoefficientType t2 = mSamplingFactors[l]*t1;
248 index[l] = (IndexValueType)lrint(t2);
250 // For even order : test if too close to 0.5 (but lower). In this
251 // case : take the next coefficient
252 if (!(mSplineOrders[l] & 1)) {
254 if (mSamplingFactors[l] & 1) {
255 if (index[l] == (int) mSamplingFactors[l]/2+1) EvaluateIndex[l] = EvaluateIndex[l]+1;
258 else if (index[l] == (int) mSamplingFactors[l]/2) EvaluateIndex[l] = EvaluateIndex[l]+1;
262 // Statistics (to be removed)
264 *mIntrinsecError += fabs(index[l]-t2);
266 if (fabs(index[l]-t2)> *mIntrinsecErrorMax) *mIntrinsecErrorMax = fabs(index[l]-t2);
269 // When to close to 1, take the next coefficient for odd order, but
270 // only change index for odd
271 if (index[l] == (int)mSamplingFactors[l]) {
273 if (mSplineOrders[l] & 1) EvaluateIndex[l] = EvaluateIndex[l]+1;
282 //====================================================================
284 //====================================================================
285 template <class TImageType, class TCoordRep, class TCoefficientType>
286 typename VectorBSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::OutputType
287 VectorBSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
288 EvaluateAtContinuousIndex(const ContinuousIndexType & x) const {
290 // For shorter coding
291 static const unsigned int d = TImageType::ImageDimension;
293 // Compute the index of the first interpolation coefficient in the coefficient image
294 IndexType evaluateIndex;
296 for (unsigned int l=0; l<d; l++) {
297 if (mSplineOrders[l] & 1) { // Use this index calculation for odd splineOrder (like cubic)
298 indx = (long)vcl_floor(x[l]) - mSplineOrders[l] / 2 ; //this->m_SplineOrder / 2;
299 evaluateIndex[l] = indx;
301 else { // Use this index calculation for even splineOrder
302 if (mSplineOrders[l] == 0) evaluateIndex[l] = (long)rint(x[l]);
304 indx = (long)vcl_floor((x[l]+ 0.5)) - mSplineOrders[l] / 2; //this->m_SplineOrder / 2;
305 evaluateIndex[l] = indx;
310 // Compute index of precomputed weights and get pointer to first weights
311 const IndexType weightIndex = GetSampleIndexOfPixelPosition(x, evaluateIndex);
312 const TCoefficientType * pweights = mWeightsCalculator.GetFirstTensorProduct(weightIndex);
315 bool boundaryCase = false;
316 for (unsigned int l=0; l<d; l++) {
317 if ((evaluateIndex[l] < 0) ||
318 (evaluateIndex[l]+mSupport[l]) >= this->m_Coefficients->GetLargestPossibleRegion().GetSize(l)) {
323 // Pointer to support offset
324 const int * psupport;
326 // Special case for boundary (to be changed ....)
327 std::vector<int> correctedSupportOffset;
330 //std::vector<TCoefficientType> coef(mSupportSize);
331 // DD(EvaluateIndex);
332 //std::vector<int> CorrectedSupportOffset;//(mSupportSize);
333 std::vector<IndexType> correctedSupportIndex;//(mSupportSize);
334 correctedSupportIndex.resize(mSupportSize);
335 correctedSupportOffset.resize(mSupportSize);
336 for(unsigned int i=0; i<mSupportSize; i++) {
337 // DD(mSupportIndex[i]);
338 for (unsigned int l=0; l<d; l++) {
339 long a = mSupportIndex[i][l] + evaluateIndex[l];
340 long b = this->m_Coefficients->GetLargestPossibleRegion().GetSize(l);
345 correctedSupportIndex[i][l] = -a - d2*(-a/d2) - evaluateIndex[l];//mSupportIndex[i][l]-a;
349 correctedSupportIndex[i][l] = d2 - a - evaluateIndex[l];
352 correctedSupportIndex[i][l] = mSupportIndex[i][l]; //a - d2*(a/d2) - EvaluateIndex[l];
356 correctedSupportIndex[i][l] = d2 - a - EvaluateIndex[l];//mSupportIndex[i][l] - (a-(b-1));
359 correctedSupportIndex[i][l] = mSupportIndex[i][l];
364 // DD(correctedSupportIndex[i]);
365 correctedSupportOffset[i] = itk::Index2Offset<TImageType::ImageDimension>(correctedSupportIndex[i], mInputMemoryOffset);
367 // for (unsigned int l=0; l<d; l++) {
368 // EvaluateIndex[l] = EvaluateIndex[l] + correctedSupportIndex[0][l];
370 // DD(EvaluateIndex);
371 psupport = &correctedSupportOffset[0];
374 psupport = &mSupportOffset[0];
377 // Get pointer to first coefficient. Even if in some boundary cases,
378 // EvaluateIndex is out of the coefficient image,
380 const CoefficientImagePixelType * pcoef = &(this->m_Coefficients->GetPixel(evaluateIndex));
382 // Main loop over BSpline support
383 CoefficientImagePixelType interpolated = 0.0;
384 for (unsigned int p=0; p<mSupportSize; p++) {
385 interpolated += pcoef[*psupport] * (*pweights);
390 // Return interpolated value
391 return(interpolated);
393 //====================================================================
396 //====================================================================
397 template <class TImageType, class TCoordRep, class TCoefficientType>
399 VectorBSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
400 EvaluateWeightsAtContinuousIndex(const ContinuousIndexType& x, const TCoefficientType ** pweights, IndexType & evaluateIndex)const {
402 // JV Compute BSpline weights if not up to date! Problem const: pass image as last
403 // if (!mWeightsAreUpToDate) UpdatePrecomputedWeights();
405 // For shorter coding
406 static const unsigned int d = TImageType::ImageDimension;
408 // Compute the index of the first interpolation coefficient in the coefficient image
409 //IndexType evaluateIndex;
411 for (unsigned int l=0; l<d; l++) {
412 if (mSplineOrders[l] & 1) { // Use this index calculation for odd splineOrder (like cubic)
413 indx = (long)vcl_floor(x[l]) - mSplineOrders[l] / 2 ; //this->m_SplineOrder / 2;
414 evaluateIndex[l] = indx;
416 else { // Use this index calculation for even splineOrder
417 if (mSplineOrders[l] == 0) evaluateIndex[l] = (long)rint(x[l]);
419 indx = (long)vcl_floor((x[l]+ 0.5)) - mSplineOrders[l] / 2; //this->m_SplineOrder / 2;
420 evaluateIndex[l] = indx;
425 // Compute index of precomputed weights and get pointer to first weights
426 const IndexType weightIndex = GetSampleIndexOfPixelPosition(x, evaluateIndex);
427 *pweights = mWeightsCalculator.GetFirstTensorProduct(weightIndex);
430 //====================================================================
437 #endif //_CLITKVECTORBSPLINEINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX