1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://www.centreleonberard.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18 #ifndef _ITKINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX
19 #define _ITKINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX
24 //====================================================================
25 template <class TImageType, class TCoordRep, class TCoefficientType>
26 BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
27 BSplineInterpolateImageFunctionWithLUT():Superclass() {
30 SetLUTSamplingFactor(20);
32 mWeightsAreUpToDate = false;
35 //====================================================================
37 //====================================================================
38 template <class TImageType, class TCoordRep, class TCoefficientType>
39 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
40 SetLUTSamplingFactor(const int& s) {
41 for(int i=0; i<TImageType::ImageDimension; i++) mSamplingFactors[i] = s;
42 mWeightsAreUpToDate = false;
45 //====================================================================
47 //====================================================================
48 template <class TImageType, class TCoordRep, class TCoefficientType>
49 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
50 SetLUTSamplingFactors(const SizeType& s) {
51 for(int i=0; i<TImageType::ImageDimension; i++) mSamplingFactors[i] = s[i];
52 mWeightsAreUpToDate = false;
55 //====================================================================
57 //====================================================================
58 template <class TImageType, class TCoordRep, class TCoefficientType>
59 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
60 SetSplineOrder(const unsigned int& SplineOrder) {
61 Superclass::SetSplineOrder(SplineOrder);
62 // Compute support and half size
63 static const int d = TImageType::ImageDimension;
64 for(int l=0; l<d; l++) {
65 mSplineOrders[l]= SplineOrder;
66 mSupport[l] = SplineOrder+1;
67 if (mSupport[l] % 2 == 0) { // support is even
68 mHalfSupport[l] = mSupport[l]/2-1;
70 else mHalfSupport[l] = mSupport[l]/2; // support is odd (like cubic spline)
73 for(int l=0; l<d; l++) {
74 mSupportSize *= mSupport[l];
76 mWeightsAreUpToDate = false;
78 //====================================================================
81 //====================================================================
82 template <class TImageType, class TCoordRep, class TCoefficientType>
83 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
84 SetSplineOrders(const SizeType& SplineOrders) {
85 mSplineOrders=SplineOrders;
87 // Compute support and half size
88 static const int d = TImageType::ImageDimension;
89 for(int l=0; l<d; l++) {
90 mSupport[l] = mSplineOrders[l]+1;
91 if (mSupport[l] % 2 == 0) { // support is even
92 mHalfSupport[l] = mSupport[l]/2-1;
94 else mHalfSupport[l] = mSupport[l]/2; // support is odd (like cubic spline)
97 for(int l=0; l<d; l++) {
98 mSupportSize *= mSupport[l];
100 mWeightsAreUpToDate = false;
102 //====================================================================
104 //====================================================================
105 template <class TImageType, class TCoordRep, class TCoefficientType>
106 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
107 SetInputImage(const TImageType * inputData) {
109 // JV Call superclass (decomposition filter is executeed each time!)
110 // JV Should call itkBSplineDecompositionFilterWithOBD to allow different order by dimension
111 Superclass::SetInputImage(inputData);
113 // Update the weightproperties
114 if (!inputData) return;
115 UpdateWeightsProperties();
118 //====================================================================
119 template <class TImageType, class TCoordRep, class TCoefficientType>
120 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
121 UpdateWeightsProperties() {
123 // Compute Memory offset inside coefficients images (for looping over coefficients)
124 static const unsigned int d = TImageType::ImageDimension;
125 mInputMemoryOffset[0] = 1;
126 for(unsigned int l=1; l<d; l++) {
127 mInputMemoryOffset[l] =
128 mInputMemoryOffset[l-1]*this->m_Coefficients->GetLargestPossibleRegion().GetSize(l-1);
131 // Compute mSupportOffset according to input size
132 mSupportOffset.resize(mSupportSize);
133 mSupportIndex.resize(mSupportSize);
134 for(unsigned int l=0; l<d; l++) mSupportIndex[0][l] = 0;
135 for(unsigned int k=0; k<mSupportSize; k++) {
137 mSupportOffset[k] = Index2Offset<TImageType::ImageDimension>(mSupportIndex[k], mInputMemoryOffset);
138 // next coefficient index
139 if (k != mSupportSize-1) {
140 for(unsigned int l=0; l<d; l++) mSupportIndex[k+1][l] = mSupportIndex[k][l];
144 mSupportIndex[k+1][l]++;
145 if (static_cast<unsigned int>(mSupportIndex[k+1][l]) == mSupport[l]) {
146 mSupportIndex[k+1][l] = 0;
154 // Compute BSpline weights if not up to date
155 if (!mWeightsAreUpToDate)
156 UpdatePrecomputedWeights();
158 //====================================================================
160 //====================================================================
161 template <class TImageType, class TCoordRep, class TCoefficientType>
162 void BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
163 UpdatePrecomputedWeights() {
165 mWeightsCalculator.SetSplineOrders(mSplineOrders);
166 mWeightsCalculator.SetSamplingFactors(mSamplingFactors);
167 mWeightsCalculator.ComputeTensorProducts();
168 mWeightsAreUpToDate = true;
170 //====================================================================
172 //====================================================================
173 template <class TImageType, class TCoordRep, class TCoefficientType>
174 typename BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::IndexType
175 BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
176 GetSampleIndexOfPixelPosition(const ContinuousIndexType & x, IndexType & EvaluateIndex) const {
179 WARNING : sometimes, a floating number x could not really be
180 represented in memory. In this case, the difference between x and
181 floor(x) can be almost 1 (instead of 0). So we take into account
182 such special case, otherwise it could lead to annoying results.
184 // static const TCoefficientType tiny = 1.0e-7;
187 for(int l=0; l<TImageType::ImageDimension; l++)
189 // Compute t1 = distance to floor
190 TCoefficientType t1 = x[l]- vcl_floor(x[l]);
192 // Compute index in precomputed weights table
193 TCoefficientType t2 = mSamplingFactors[l]*t1;
194 index[l] = (IndexValueType)Math::Round<TCoefficientType>(t2);
196 // For even order : test if too close to 0.5 (but lower). In this
197 // case : take the next coefficient
198 if (!(mSplineOrders[l] & 1)) {
200 if (mSamplingFactors[l] & 1) {
201 if (index[l] == (int) mSamplingFactors[l]/2+1) EvaluateIndex[l] = EvaluateIndex[l]+1;
204 else if (index[l] == (int) mSamplingFactors[l]/2) EvaluateIndex[l] = EvaluateIndex[l]+1;
208 // When to close to 1, take the next coefficient for odd order, but
209 // only change index for odd
210 if (index[l] == (int)mSamplingFactors[l]) {
212 if (mSplineOrders[l] & 1) EvaluateIndex[l] = EvaluateIndex[l]+1;
221 //====================================================================
223 //====================================================================
224 template <class TImageType, class TCoordRep, class TCoefficientType>
225 typename BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::OutputType
226 BSplineInterpolateImageFunctionWithLUT<TImageType,TCoordRep,TCoefficientType>::
227 EvaluateAtContinuousIndex(const ContinuousIndexType & x) const {
229 // JV Compute BSpline weights if not up to date! Problem const: pass image as last
230 // if (!mWeightsAreUpToDate) UpdatePrecomputedWeights();
232 // For shorter coding
233 static const unsigned int d = TImageType::ImageDimension;
235 // Compute the index of the first interpolation coefficient in the coefficient image
236 IndexType evaluateIndex;
238 for (unsigned int l=0; l<d; l++) {
239 if (mSplineOrders[l] & 1) { // Use this index calculation for odd splineOrder (like cubic)
240 indx = (long)vcl_floor(x[l]) - mSplineOrders[l] / 2 ; //this->m_SplineOrder / 2;
241 evaluateIndex[l] = indx;
243 else { // Use this index calculation for even splineOrder
244 if (mSplineOrders[l] == 0) evaluateIndex[l] = Math::Round<typename ContinuousIndexType::ValueType>(x[l]);
246 indx = (long)vcl_floor((x[l]+ 0.5)) - mSplineOrders[l] / 2; //this->m_SplineOrder / 2;
247 evaluateIndex[l] = indx;
252 // Compute index of precomputed weights and get pointer to first weights
253 const IndexType weightIndex = GetSampleIndexOfPixelPosition(x, evaluateIndex);
254 const TCoefficientType * pweights = mWeightsCalculator.GetFirstTensorProduct(weightIndex);
257 bool boundaryCase = false;
258 for (unsigned int l=0; l<d; l++) {
259 if ((evaluateIndex[l] < 0) ||
260 (evaluateIndex[l]+mSupport[l]) >= this->m_Coefficients->GetLargestPossibleRegion().GetSize(l)) {
265 // Pointer to support offset
266 const int * psupport;
268 // Special case for boundary (to be changed ....)
269 std::vector<int> correctedSupportOffset;
272 std::vector<IndexType> correctedSupportIndex;//(mSupportSize);
273 correctedSupportIndex.resize(mSupportSize);
274 correctedSupportOffset.resize(mSupportSize);
275 for(unsigned int i=0; i<mSupportSize; i++) {
276 for (unsigned int l=0; l<d; l++) {
277 long a = mSupportIndex[i][l] + evaluateIndex[l];
278 long b = this->m_Coefficients->GetLargestPossibleRegion().GetSize(l);
281 correctedSupportIndex[i][l] = -a - d2*(-a/d2) - evaluateIndex[l];//mSupportIndex[i][l]-a;
285 correctedSupportIndex[i][l] = d2 - a - evaluateIndex[l];
288 correctedSupportIndex[i][l] = mSupportIndex[i][l]; //a - d2*(a/d2) - EvaluateIndex[l];
292 correctedSupportIndex[i][l] = d2 - a - EvaluateIndex[l];//mSupportIndex[i][l] - (a-(b-1));
295 correctedSupportIndex[i][l] = mSupportIndex[i][l];
300 correctedSupportOffset[i] = itk::Index2Offset<TImageType::ImageDimension>(correctedSupportIndex[i], mInputMemoryOffset);
302 psupport = &correctedSupportOffset[0];
305 psupport = &mSupportOffset[0];
308 // Get pointer to first coefficient. Even if in some boundary cases,
309 // EvaluateIndex is out of the coefficient image,
310 const TCoefficientType * pcoef = &(this->m_Coefficients->GetPixel(evaluateIndex));
312 // Main loop over BSpline support
313 TCoefficientType interpolated = itk::NumericTraits<TCoefficientType>::Zero;
314 for (unsigned int p=0; p<mSupportSize; p++) {
315 interpolated += pcoef[*psupport] * (*pweights);
320 // Return interpolated value
321 return(interpolated);
323 //====================================================================
326 #endif //_ITKINTERPOLATEIMAGEFUNCTIONWITHLUT_TXX