00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00020 #ifndef _SplineInterpolation_hxx
00021 #define _SplineInterpolation_hxx
00022
00023 #include<ImLib3D/Zero.hpp>
00024 #include<ImLib3D/Vect3D.hpp>
00025 #include<ImLib3D/TaskProgressManager.hpp>
00026 #include<float.h>
00027
00028
00030 template<class Im3DValue>
00031 Im3DValue
00032 SplineInterpolator3D<Im3DValue>::Value(const ImageType &ima,const float x,const float y,const float z)
00033 {
00034 if(&ima != srcImage)
00035 {
00036 ThrowError("SplineInterpolator3D::Value incoherence. Did you use \"Initialize\"");
00037 }
00038 const ImageType &Ccoeff=*coeffImage;
00039
00040 int Width =Ccoeff.Width ();
00041 int Height=Ccoeff.Height();
00042 int Depth =Ccoeff.Depth ();
00043
00044 int r=(splineDegree+1)/2;
00045 if(x>=r && y>=r && z>=r && x<=(Width-r-1) && y<=(Height-r-1) && z<=(Depth-r-1))
00046 {
00047 DBGvaluefastct++;
00048 return ValueFast(Ccoeff,x,y,z);
00049 }
00050 if(boundary==BOUNDARY_ZERO && !Ccoeff.IsInside(x,y,z))
00051 {
00052 return Zero<Im3DValue>();
00053 }
00054 if(boundary==BOUNDARY_BACKGROUND && !Ccoeff.IsInside(x,y,z))
00055 {
00056 ThrowError("SplineInterpolation BACKGROUND UNIMPLEMENTED");
00057
00058 }
00059 DBGvaluect++;
00060 Scalar xWeight[6], yWeight[6], zWeight[6];
00061 Scalar interpolated;
00062 Scalar w, w2, w4, t, t0, t1;
00063 long xIndex[6], yIndex[6], zIndex[6];
00064 long Width2 = 2L * Width - 2L, Height2 = 2L * Height - 2L, Depth2 = 2L * Depth - 2L;
00065
00066
00067 {
00068 long i, j, q, k;
00069 if (splineDegree & 1L)
00070 {
00071 i = (long)floor(x) - splineDegree / 2L;
00072 j = (long)floor(y) - splineDegree / 2L;
00073 q = (long)floor(z) - splineDegree / 2L;
00074 }
00075 else
00076 {
00077 i = (long)floor(x + 0.5) - splineDegree / 2L;
00078 j = (long)floor(y + 0.5) - splineDegree / 2L;
00079 q = (long)floor(z + 0.5) - splineDegree / 2L;
00080 }
00081 for (k = 0L; k <= splineDegree; k++)
00082 {
00083 xIndex[k] = i++;
00084 yIndex[k] = j++;
00085 zIndex[k] = q++;
00086 }
00087 }
00088
00089
00090 switch (splineDegree)
00091 {
00092 case 2:
00093
00094 w = x - (Scalar)xIndex[1];
00095 xWeight[1] = 3.0 / 4.0 - w * w;
00096 xWeight[2] = (1.0 / 2.0) * (w - xWeight[1] + 1.0);
00097 xWeight[0] = 1.0 - xWeight[1] - xWeight[2];
00098
00099 w = y - (Scalar)yIndex[1];
00100 yWeight[1] = 3.0 / 4.0 - w * w;
00101 yWeight[2] = (1.0 / 2.0) * (w - yWeight[1] + 1.0);
00102 yWeight[0] = 1.0 - yWeight[1] - yWeight[2];
00103
00104 w = z - (Scalar)zIndex[1];
00105 zWeight[1] = 3.0 / 4.0 - w * w;
00106 zWeight[2] = (1.0 / 2.0) * (w - zWeight[1] + 1.0);
00107 zWeight[0] = 1.0 - zWeight[1] - zWeight[2];
00108 break;
00109 case 3:
00110
00111 w = x - (Scalar)xIndex[1];
00112 xWeight[3] = (1.0 / 6.0) * w * w * w;
00113 xWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - xWeight[3];
00114 xWeight[2] = w + xWeight[0] - 2.0 * xWeight[3];
00115 xWeight[1] = 1.0 - xWeight[0] - xWeight[2] - xWeight[3];
00116
00117 w = y - (Scalar)yIndex[1];
00118 yWeight[3] = (1.0 / 6.0) * w * w * w;
00119 yWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - yWeight[3];
00120 yWeight[2] = w + yWeight[0] - 2.0 * yWeight[3];
00121 yWeight[1] = 1.0 - yWeight[0] - yWeight[2] - yWeight[3];
00122
00123 w = z - (Scalar)zIndex[1];
00124 zWeight[3] = (1.0 / 6.0) * w * w * w;
00125 zWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - zWeight[3];
00126 zWeight[2] = w + zWeight[0] - 2.0 * zWeight[3];
00127 zWeight[1] = 1.0 - zWeight[0] - zWeight[2] - zWeight[3];
00128 break;
00129 case 4:
00130
00131 w = x - (Scalar)xIndex[2];
00132 w2 = w * w;
00133 t = (1.0 / 6.0) * w2;
00134 xWeight[0] = 1.0 / 2.0 - w;
00135 xWeight[0] *= xWeight[0];
00136 xWeight[0] *= (1.0 / 24.0) * xWeight[0];
00137 t0 = w * (t - 11.0 / 24.0);
00138 t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t);
00139 xWeight[1] = t1 + t0;
00140 xWeight[3] = t1 - t0;
00141 xWeight[4] = xWeight[0] + t0 + (1.0 / 2.0) * w;
00142 xWeight[2] = 1.0 - xWeight[0] - xWeight[1] - xWeight[3] - xWeight[4];
00143
00144 w = y - (Scalar)yIndex[2];
00145 w2 = w * w;
00146 t = (1.0 / 6.0) * w2;
00147 yWeight[0] = 1.0 / 2.0 - w;
00148 yWeight[0] *= yWeight[0];
00149 yWeight[0] *= (1.0 / 24.0) * yWeight[0];
00150 t0 = w * (t - 11.0 / 24.0);
00151 t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t);
00152 yWeight[1] = t1 + t0;
00153 yWeight[3] = t1 - t0;
00154 yWeight[4] = yWeight[0] + t0 + (1.0 / 2.0) * w;
00155 yWeight[2] = 1.0 - yWeight[0] - yWeight[1] - yWeight[3] - yWeight[4];
00156
00157 w = z - (Scalar)zIndex[2];
00158 w2 = w * w;
00159 t = (1.0 / 6.0) * w2;
00160 zWeight[0] = 1.0 / 2.0 - w;
00161 zWeight[0] *= zWeight[0];
00162 zWeight[0] *= (1.0 / 24.0) * zWeight[0];
00163 t0 = w * (t - 11.0 / 24.0);
00164 t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t);
00165 zWeight[1] = t1 + t0;
00166 zWeight[3] = t1 - t0;
00167 zWeight[4] = zWeight[0] + t0 + (1.0 / 2.0) * w;
00168 zWeight[2] = 1.0 - zWeight[0] - zWeight[1] - zWeight[3] - zWeight[4];
00169 break;
00170 case 5:
00171
00172 w = x - (Scalar)xIndex[2];
00173 w2 = w * w;
00174 xWeight[5] = (1.0 / 120.0) * w * w2 * w2;
00175 w2 -= w;
00176 w4 = w2 * w2;
00177 w -= 1.0 / 2.0;
00178 t = w2 * (w2 - 3.0);
00179 xWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - xWeight[5];
00180 t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
00181 t1 = (-1.0 / 12.0) * w * (t + 4.0);
00182 xWeight[2] = t0 + t1;
00183 xWeight[3] = t0 - t1;
00184 t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
00185 t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
00186 xWeight[1] = t0 + t1;
00187 xWeight[4] = t0 - t1;
00188
00189 w = y - (Scalar)yIndex[2];
00190 w2 = w * w;
00191 yWeight[5] = (1.0 / 120.0) * w * w2 * w2;
00192 w2 -= w;
00193 w4 = w2 * w2;
00194 w -= 1.0 / 2.0;
00195 t = w2 * (w2 - 3.0);
00196 yWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - yWeight[5];
00197 t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
00198 t1 = (-1.0 / 12.0) * w * (t + 4.0);
00199 yWeight[2] = t0 + t1;
00200 yWeight[3] = t0 - t1;
00201 t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
00202 t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
00203 yWeight[1] = t0 + t1;
00204 yWeight[4] = t0 - t1;
00205
00206 w = z - (Scalar)zIndex[2];
00207 w2 = w * w;
00208 zWeight[5] = (1.0 / 120.0) * w * w2 * w2;
00209 w2 -= w;
00210 w4 = w2 * w2;
00211 w -= 1.0 / 2.0;
00212 t = w2 * (w2 - 3.0);
00213 zWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - zWeight[5];
00214 t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
00215 t1 = (-1.0 / 12.0) * w * (t + 4.0);
00216 zWeight[2] = t0 + t1;
00217 zWeight[3] = t0 - t1;
00218 t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
00219 t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
00220 zWeight[1] = t0 + t1;
00221 zWeight[4] = t0 - t1;
00222 break;
00223 default:
00224 ThrowError("SplineInterpolator3D::Value Invalid spline degree\n");
00225 }
00226
00227
00228 {
00229 int k;
00230 if (Width == 1L)
00231 {
00232 for (k = 0L; k <= splineDegree; k++)
00233 {
00234 xIndex[k] = 0L;
00235 }
00236 }
00237 if (Height == 1L)
00238 {
00239 for (k = 0L; k <= splineDegree; k++)
00240 {
00241 yIndex[k] = 0L;
00242 }
00243 }
00244 if (Depth == 1L)
00245 {
00246 for (k = 0L; k <= splineDegree; k++)
00247 {
00248 zIndex[k] = 0L;
00249 }
00250 }
00251 if(boundary==BOUNDARY_MIRROR || boundary==BOUNDARY_BACKGROUND)
00252 {
00253 for (k = 0L; k <= splineDegree; k++)
00254 {
00255 if(Width2!=0)
00256 {
00257 xIndex[k] = (xIndex[k] < 0L)
00258 ? (-xIndex[k] - Width2 * ((-xIndex[k]) / Width2))
00259 : ( xIndex[k] - Width2 * ( xIndex[k] / Width2));
00260 }
00261 else
00262 {
00263 xIndex[k] =0;
00264 }
00265 if (Width <= xIndex[k])
00266 {
00267 xIndex[k] = Width2 - xIndex[k];
00268 }
00269 if(Height2!=0)
00270 {
00271 yIndex[k] = (yIndex[k] < 0L)
00272 ? (-yIndex[k] - Height2 * ((-yIndex[k]) / Height2))
00273 : ( yIndex[k] - Height2 * ( yIndex[k] / Height2));
00274 }
00275 else
00276 {
00277 yIndex[k] =0;
00278 }
00279 if (Height <= yIndex[k])
00280 {
00281 yIndex[k] = Height2 - yIndex[k];
00282 }
00283 if(Depth2!=0)
00284 {
00285 zIndex[k] = (zIndex[k] < 0L)
00286 ? (-zIndex[k] - Depth2 * ((-zIndex[k]) / Depth2))
00287 : ( zIndex[k] - Depth2 * ( zIndex[k] / Depth2));
00288 }
00289 else
00290 {
00291 zIndex[k] = 0;
00292 }
00293 if (Depth <= zIndex[k])
00294 {
00295 zIndex[k] = Depth2 - zIndex[k];
00296 }
00297 }
00298 }
00299 else
00300 {
00301 for (k = 0L; k <= splineDegree; k++)
00302 {
00303 if(xIndex[k] < 0L ){xIndex[k]=0; }
00304 if(xIndex[k] >= Width ){xIndex[k]=Width - 1; }
00305 if(yIndex[k] < 0L ){yIndex[k]=0; }
00306 if(yIndex[k] >= Height){yIndex[k]=Height - 1;}
00307 if(zIndex[k] < 0L ){zIndex[k]=0; }
00308 if(zIndex[k] >= Depth ){zIndex[k]=Depth - 1;}
00309 }
00310
00311 }
00312 }
00313
00314 #ifdef NOTDEF
00315 if(
00316 xIndex[0]>Width /3 &&
00317 yIndex[0]>Height/3 &&
00318 zIndex[0]>Depth /3 &&
00319 xIndex[0]<Width *2/3 &&
00320 yIndex[0]<Height*2/3 &&
00321 zIndex[0]<Depth *2/3 )
00322 {
00323 mprintf("POINT: %f %f %f\n",x,y,z);
00324 for (long i = 0L; i <= splineDegree; i++)
00325 {
00326 mprintf("xWeight[%d]:%5.5f ",i,xWeight[i]);
00327 mprintf("yWeight[%d]:%5.5f ",i,yWeight[i]);
00328 mprintf("zWeight[%d]:%5.5f \n",i,zWeight[i]);
00329 }
00330 for (long i = 0L; i <= splineDegree; i++)
00331 {
00332 mprintf("xIndex[%d]:%3d ",i,xIndex[i]);
00333 mprintf("yIndex[%d]:%3d ",i,yIndex[i]);
00334 mprintf("zIndex[%d]:%3d \n",i,zIndex[i]);
00335 }
00336 }
00337 #endif //NOTDEF
00338
00339 interpolated = 0.0;
00340 Im3DValue zero;
00341 SetZero<Im3DValue>::Set(zero);
00342
00343 Im3DValue sumxyz=zero;
00344 for (long q = 0L; q <= splineDegree; q++)
00345 {
00346 long z=zIndex[q];
00347 Im3DValue sumxy=zero;
00348 for (long j = 0L; j <= splineDegree; j++)
00349 {
00350 Im3DValue sumx = zero;
00351
00352 const Im3DValue *p=Ccoeff.GetData()+yIndex[j]*Width+z*Width*Height;
00353 for (long i = 0L; i <= splineDegree; i++)
00354 {
00355 sumx += xWeight[i] * p[xIndex[i]];
00356 }
00357 sumxy += yWeight[j] * sumx;
00358 }
00359 sumxyz += zWeight[q] * sumxy;
00360 }
00361
00362 return(sumxyz);
00363 }
00364
00365 template<class Im3DValue>
00366 void
00367 SplineInterpolator3D<Im3DValue>::ComputeInterpolationWeights(Scalar *xWeight,Scalar *yWeight,Scalar *zWeight,
00368 float x,float y,float z,
00369 int x0,int y0,int z0)
00370 {
00371
00372 switch (splineDegree)
00373 {
00374 Scalar w, w2, w4, t, t0, t1;
00375 case 2:
00376
00377 w = x - (Scalar)(x0+1);
00378 xWeight[1] = 3.0 / 4.0 - w * w;
00379 xWeight[2] = (1.0 / 2.0) * (w - xWeight[1] + 1.0);
00380 xWeight[0] = 1.0 - xWeight[1] - xWeight[2];
00381
00382 w = y - (Scalar)(y0+1);
00383 yWeight[1] = 3.0 / 4.0 - w * w;
00384 yWeight[2] = (1.0 / 2.0) * (w - yWeight[1] + 1.0);
00385 yWeight[0] = 1.0 - yWeight[1] - yWeight[2];
00386
00387 w = z - (Scalar)(z0+1);
00388 zWeight[1] = 3.0 / 4.0 - w * w;
00389 zWeight[2] = (1.0 / 2.0) * (w - zWeight[1] + 1.0);
00390 zWeight[0] = 1.0 - zWeight[1] - zWeight[2];
00391 break;
00392 case 3:
00393
00394 w = x - (Scalar)(x0+1);
00395 xWeight[3] = (1.0 / 6.0) * w * w * w;
00396 xWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - xWeight[3];
00397 xWeight[2] = w + xWeight[0] - 2.0 * xWeight[3];
00398 xWeight[1] = 1.0 - xWeight[0] - xWeight[2] - xWeight[3];
00399
00400 w = y - (Scalar)(y0+1);
00401 yWeight[3] = (1.0 / 6.0) * w * w * w;
00402 yWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - yWeight[3];
00403 yWeight[2] = w + yWeight[0] - 2.0 * yWeight[3];
00404 yWeight[1] = 1.0 - yWeight[0] - yWeight[2] - yWeight[3];
00405
00406 w = z - (Scalar)(z0+1);
00407 zWeight[3] = (1.0 / 6.0) * w * w * w;
00408 zWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - zWeight[3];
00409 zWeight[2] = w + zWeight[0] - 2.0 * zWeight[3];
00410 zWeight[1] = 1.0 - zWeight[0] - zWeight[2] - zWeight[3];
00411 break;
00412 case 4:
00413
00414 w = x - (Scalar)(x0+2);
00415 w2 = w * w;
00416 t = (1.0 / 6.0) * w2;
00417 xWeight[0] = 1.0 / 2.0 - w;
00418 xWeight[0] *= xWeight[0];
00419 xWeight[0] *= (1.0 / 24.0) * xWeight[0];
00420 t0 = w * (t - 11.0 / 24.0);
00421 t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t);
00422 xWeight[1] = t1 + t0;
00423 xWeight[3] = t1 - t0;
00424 xWeight[4] = xWeight[0] + t0 + (1.0 / 2.0) * w;
00425 xWeight[2] = 1.0 - xWeight[0] - xWeight[1] - xWeight[3] - xWeight[4];
00426
00427 w = y - (Scalar)(y0+2);
00428 w2 = w * w;
00429 t = (1.0 / 6.0) * w2;
00430 yWeight[0] = 1.0 / 2.0 - w;
00431 yWeight[0] *= yWeight[0];
00432 yWeight[0] *= (1.0 / 24.0) * yWeight[0];
00433 t0 = w * (t - 11.0 / 24.0);
00434 t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t);
00435 yWeight[1] = t1 + t0;
00436 yWeight[3] = t1 - t0;
00437 yWeight[4] = yWeight[0] + t0 + (1.0 / 2.0) * w;
00438 yWeight[2] = 1.0 - yWeight[0] - yWeight[1] - yWeight[3] - yWeight[4];
00439
00440 w = z - (Scalar)(z0+2);
00441 w2 = w * w;
00442 t = (1.0 / 6.0) * w2;
00443 zWeight[0] = 1.0 / 2.0 - w;
00444 zWeight[0] *= zWeight[0];
00445 zWeight[0] *= (1.0 / 24.0) * zWeight[0];
00446 t0 = w * (t - 11.0 / 24.0);
00447 t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t);
00448 zWeight[1] = t1 + t0;
00449 zWeight[3] = t1 - t0;
00450 zWeight[4] = zWeight[0] + t0 + (1.0 / 2.0) * w;
00451 zWeight[2] = 1.0 - zWeight[0] - zWeight[1] - zWeight[3] - zWeight[4];
00452 break;
00453 case 5:
00454
00455 w = x - (Scalar)(x0+2);
00456 w2 = w * w;
00457 xWeight[5] = (1.0 / 120.0) * w * w2 * w2;
00458 w2 -= w;
00459 w4 = w2 * w2;
00460 w -= 1.0 / 2.0;
00461 t = w2 * (w2 - 3.0);
00462 xWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - xWeight[5];
00463 t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
00464 t1 = (-1.0 / 12.0) * w * (t + 4.0);
00465 xWeight[2] = t0 + t1;
00466 xWeight[3] = t0 - t1;
00467 t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
00468 t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
00469 xWeight[1] = t0 + t1;
00470 xWeight[4] = t0 - t1;
00471
00472 w = y - (Scalar)(y0+2);
00473 w2 = w * w;
00474 yWeight[5] = (1.0 / 120.0) * w * w2 * w2;
00475 w2 -= w;
00476 w4 = w2 * w2;
00477 w -= 1.0 / 2.0;
00478 t = w2 * (w2 - 3.0);
00479 yWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - yWeight[5];
00480 t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
00481 t1 = (-1.0 / 12.0) * w * (t + 4.0);
00482 yWeight[2] = t0 + t1;
00483 yWeight[3] = t0 - t1;
00484 t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
00485 t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
00486 yWeight[1] = t0 + t1;
00487 yWeight[4] = t0 - t1;
00488
00489 w = z - (Scalar)(z0+2);
00490 w2 = w * w;
00491 zWeight[5] = (1.0 / 120.0) * w * w2 * w2;
00492 w2 -= w;
00493 w4 = w2 * w2;
00494 w -= 1.0 / 2.0;
00495 t = w2 * (w2 - 3.0);
00496 zWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - zWeight[5];
00497 t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
00498 t1 = (-1.0 / 12.0) * w * (t + 4.0);
00499 zWeight[2] = t0 + t1;
00500 zWeight[3] = t0 - t1;
00501 t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
00502 t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
00503 zWeight[1] = t0 + t1;
00504 zWeight[4] = t0 - t1;
00505 break;
00506 default:
00507 ThrowError("Invalid spline degree\n");
00508 }
00509 }
00510
00511
00512
00514
00515 template<class Im3DValue>
00516 Im3DValue
00517 SplineInterpolator3D<Im3DValue>::ValueFast(const ImageType &Ccoeff,const float x,const float y,const float z)
00518 {
00519 int Width =Ccoeff.Width ();
00520 int Height=Ccoeff.Height();
00521
00522
00523 Scalar xWeight[6], yWeight[6], zWeight[6];
00524 Scalar interpolated;
00525
00526 long x0,y0,z0;
00527
00528
00529 #ifdef BENCH
00530 double T0=DTime();
00531 #endif
00532
00533 if (splineDegree & 1)
00534 {
00535 x0 = (long)floor(x) - splineDegree / 2;
00536 y0 = (long)floor(y) - splineDegree / 2;
00537 z0 = (long)floor(z) - splineDegree / 2;
00538 }
00539 else
00540 {
00541 x0 = (long)floor(x + 0.5) - splineDegree / 2;
00542 y0 = (long)floor(y + 0.5) - splineDegree / 2;
00543 z0 = (long)floor(z + 0.5) - splineDegree / 2;
00544 }
00545
00546 ComputeInterpolationWeights(xWeight,yWeight,zWeight,x,y,z,x0,y0,z0);
00547
00548
00549 interpolated = 0.0;
00550 Im3DValue zero;
00551 SetZero<Im3DValue>::Set(zero);
00552
00553 Im3DValue sumxyz=zero;
00554
00555 #ifdef BENCH
00556 static double T3=0;
00557 T3+=DTime(T0);
00558 #endif
00559 #ifdef NOTDEF
00560 Scalar ttt=0;
00561 for (long q = 0; q <= splineDegree; q++)
00562 {
00563 long z=z0+q;
00564 Im3DValue sumxy=zero;
00565 for (long j = 0; j <= splineDegree; j++)
00566 {
00567 Im3DValue sumx = zero;
00568
00569 Im3DValue *p=Ccoeff.GetData()+(y0+j)*Width+z*Width*Height;
00570 for (long i = 0; i <= splineDegree; i++)
00571 {
00572 ttt=p[x0+i];
00573 if(ttt) sumx += xWeight[i] * ttt;
00574
00575
00576 }
00577 sumxy += yWeight[j] * sumx;
00578 }
00579 sumxyz += zWeight[q] * sumxy;
00580 }
00581 #else //NOTDEF
00582 for (int q = 0; q <= splineDegree; q++)
00583 {
00584 Im3DValue sumxy=zero;
00585 const Im3DValue *p0=Ccoeff.GetData()+(z0+q)*Width*Height+y0*Width+x0;
00586 const Im3DValue *p1=p0;
00587 Im3DValue sumx;
00588 const Im3DValue *p;
00589 Scalar *weight;
00590 Scalar *yweight=yWeight;
00591 switch (splineDegree)
00592 {
00593
00594 #define unrolledy_0 sumx=0;p=p1;weight=xWeight;
00595 #define unrolledx sumx += (Im3DValue)((*weight++) * (*p++));
00596 #define unrolledy_1 p1+=Width;sumxy += (Im3DValue)((*yweight++) * sumx);
00597
00598 case 2:
00599 #define unrolledy unrolledy_0;unrolledx;unrolledx;unrolledx;unrolledy_1;
00600 unrolledy;unrolledy;unrolledy;
00601 #undef unrolledy
00602 break;
00603 case 3:
00604 #define unrolledy unrolledy_0;unrolledx;unrolledx;unrolledx;unrolledx;unrolledy_1;
00605 unrolledy;unrolledy;unrolledy;unrolledy;
00606 #undef unrolledy
00607 break;
00608 case 4:
00609 #define unrolledy unrolledy_0;unrolledx;unrolledx;unrolledx;unrolledx;unrolledx;unrolledy_1;
00610 unrolledy;unrolledy;unrolledy;unrolledy;unrolledy;
00611 #undef unrolledy
00612 break;
00613 case 5:
00614 #define unrolledy unrolledy_0;unrolledx;unrolledx;unrolledx;unrolledx;unrolledx;unrolledx;unrolledy_1;
00615 unrolledy;unrolledy;unrolledy;unrolledy;unrolledy;unrolledy;
00616 #undef unrolledy
00617 break;
00618
00619 #undef unrolledy_0
00620 #undef unrolledx
00621 #undef unrolledy_1
00622 }
00623 sumxyz += zWeight[q] * sumxy;
00624 }
00625 #endif //NOTDEF
00626 #ifdef BENCH
00627 static double T4=0;
00628 T4+=DTime(T0);
00629
00630 if(!(rand()%1000))
00631 {
00632 mprintf("0-1:%4.4f 1-2:%4.4f 2-3:%4.4f 3-4:%4.4f tot:%f\n",T1/T4,(T2-T1)/T4,(T3-T2)/T4,(T4-T3)/T4,T4);
00633 }
00634 #endif
00635
00636 return(sumxyz);
00637 }
00638
00639 #ifndef DBL_EPSILON
00640 #define DBL_EPSILON 2.2204460492503131E-16
00641 #endif // DBL_EPSILON
00642 #ifndef FLT_EPSILON
00643 #define FLT_EPSILON ((float)1.19209290E-07)
00644 #endif //FLT_EPSILON
00645
00646
00647
00649 template<class Im3DValue>
00650 void
00651 SplineInterpolator3D<Im3DValue>::SamplesToCoefficients(ImageType &ima)
00652 {
00653 int Width =ima.Width ();
00654 int Height=ima.Height();
00655 int Depth =ima.Depth ();
00656
00657
00658
00659
00660
00661
00662 vector<Scalar> poles;
00663 long x, y,z;
00664
00665
00666
00667 switch (splineDegree)
00668 {
00669 case 2:
00670 poles.push_back(sqrt(8.0) - 3.0);
00671 break;
00672 case 3:
00673 poles.push_back(sqrt(3.0) - 2.0);
00674 break;
00675 case 4:
00676 poles.push_back(sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0);
00677 poles.push_back(sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0);
00678 break;
00679 case 5:
00680 poles.push_back(sqrt(135.0 / 2.0 - sqrt(17745.0 / 4.0)) + sqrt(105.0 / 4.0)
00681 - 13.0 / 2.0);
00682 poles.push_back(sqrt(135.0 / 2.0 + sqrt(17745.0 / 4.0)) - sqrt(105.0 / 4.0)
00683 - 13.0 / 2.0);
00684 break;
00685 default:
00686 ThrowError("Invalid spline degree:%d",splineDegree);
00687 }
00688
00689
00690 const Scalar epsilon=(sizeof(Scalar)==sizeof(float) ? FLT_EPSILON : DBL_EPSILON);
00691 vector<Im3DValue> row1D;
00692 {
00693 TaskTracker<long int> tracker("SplineInterpolator3D:coefs-x",0,Depth,&z);
00694
00695 row1D.resize(Width);
00696 for (z = 0; z < Depth; z++)
00697 {
00698 for (y = 0; y < Height; y++)
00699 {
00700 for(x=0;x<Width;x++){row1D[x]=ima(x,y,z);}
00701 ConvertToInterpolationCoefficients(row1D, poles, epsilon);
00702 for(x=0;x<Width;x++){ima(x,y,z)=row1D[x];}
00703 }
00704 }
00705 }
00706
00707
00708 {
00709 TaskTracker<long int> tracker("SplineInterpolator3D:coefs-y",0,Depth,&z);
00710 row1D.resize(Height);
00711 for (z = 0; z < Depth; z++)
00712 {
00713 for (x = 0; x < Width; x++)
00714 {
00715 for(y=0;y<Height;y++){row1D[y]=ima(x,y,z);}
00716 ConvertToInterpolationCoefficients(row1D, poles, epsilon);
00717 for(y=0;y<Height;y++){ima(x,y,z)=row1D[y];}
00718 }
00719 }
00720 }
00721
00722 {
00723 TaskTracker<long int> tracker("SplineInterpolator3D:coefs-z",0,Width,&x);
00724 row1D.resize(Depth);
00725 for (x = 0L; x < Width; x++)
00726 {
00727 for (y = 0L; y < Height; y++)
00728 {
00729 for(z=0;z<Depth;z++){row1D[z]=ima(x,y,z);}
00730 ConvertToInterpolationCoefficients(row1D, poles, epsilon);
00731 for(z=0;z<Depth;z++){ima(x,y,z)=row1D[z];}
00732 }
00733 }
00734 }
00735
00736
00737 }
00738
00739
00740 template<class Im3DValue>
00741 void
00742 SplineInterpolator3D<Im3DValue>::ConvertToInterpolationCoefficients(
00743 vector<Im3DValue> &c,
00744 vector<Scalar> &z,
00745 Scalar Tolerance
00746 )
00747
00748 {
00749 long DataLength=c.size();
00750 long NbPoles=z.size();
00751 Scalar Lambda = 1;
00752 long n, k;
00753
00754
00755 if (DataLength == 1L)
00756 {
00757 return;
00758 }
00759
00760 for (k = 0L; k < NbPoles; k++)
00761 {
00762 Lambda = Lambda * (1 - z[k]) * (1 - 1 / z[k]);
00763 }
00764
00765 for (n = 0L; n < DataLength; n++)
00766 {
00767 c[n] *= Lambda;
00768 }
00769
00770 for (k = 0L; k < NbPoles; k++)
00771 {
00772 Scalar zk=z[k];
00773
00774 c[0] = InitialCausalCoefficient(c, z[k], Tolerance);
00775
00776 for (n = 1L; n < DataLength; n++)
00777 {
00778 c[n] += zk * c[n - 1L];
00779 }
00780
00781 c[DataLength - 1L] = InitialAntiCausalCoefficient(c, z[k]);
00782
00783 for (n = DataLength - 2L; 0 <= n; n--)
00784 {
00785 c[n] = zk * (c[n + 1L] - c[n]);
00786 }
00787 }
00788 }
00789
00790
00791 template<class Im3DValue>
00792 Im3DValue
00793 SplineInterpolator3D<Im3DValue>::InitialCausalCoefficient(
00794 vector<Im3DValue> &c,
00795 Scalar z,
00796 Scalar Tolerance
00797 )
00798
00799 {
00800 Im3DValue zero;
00801 SetZero<Im3DValue>::Set(zero);
00802
00803 if(boundary==BOUNDARY_ZERO){return zero;}
00804
00805 long DataLength=c.size();
00806 Im3DValue Sum;
00807 Scalar zn, z2n, iz;
00808 long n, Horizon;
00809
00810
00811 Horizon = DataLength;
00812 if (Tolerance > 0.0)
00813 {
00814 Horizon = (long)ceil(log(Tolerance) / log(fabs(z)));
00815 }
00816 if (Horizon < DataLength)
00817 {
00818
00819 zn = z;
00820 Sum = c[0];
00821 for (n = 1L; n < Horizon; n++)
00822 {
00823 Sum += zn * c[n];
00824 zn *= z;
00825 }
00826 return(Sum);
00827 }
00828 else
00829 {
00830
00831 zn = z;
00832 iz = 1.0 / z;
00833 z2n = pow(z, (Scalar)(DataLength - 1L));
00834 Sum = c[0] + z2n * c[DataLength - 1L];
00835 z2n *= z2n * iz;
00836 for (n = 1L; n <= DataLength - 2L; n++)
00837 {
00838 Sum += (zn + z2n) * c[n];
00839 zn *= z;
00840 z2n *= iz;
00841 }
00842 return (1 / (1 - zn * zn))*Sum;
00843 }
00844 }
00845
00846
00847 template<class Im3DValue>
00848 Im3DValue
00849 SplineInterpolator3D<Im3DValue>::InitialAntiCausalCoefficient
00850 (
00851 vector<Im3DValue> &c,
00852 Scalar z
00853 )
00854
00855 {
00856 Im3DValue zero;
00857 SetZero<Im3DValue>::Set(zero);
00858
00859 if(boundary==BOUNDARY_ZERO){return zero;}
00860
00861 long DataLength=c.size();
00862
00863 return((z / (z * z - 1)) * (z * c[DataLength - 2L] + c[DataLength - 1L]));
00864 }
00865
00866
00867
00868
00869
00870 #endif // _SplineInterpolation_hxx