Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

SplineInterpolation.hxx

Go to the documentation of this file.
00001 /* ImLib3D
00002  * Copyright (c) 2001, ULP-IPB Strasbourg.
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or (at
00007  * your option) any later version.
00008  * 
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 // *************************** Value ****************************
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 //          return *Ccoeff.properties.background;
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     /* compute the interpolation indexes */
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     /* compute the interpolation weights */
00090     switch (splineDegree) 
00091     {
00092     case 2:
00093         /* x */
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         /* y */
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         /* z */
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         /* x */
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         /* y */
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         /* z */
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         /* x */
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         /* y */
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         /* z */
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         /* x */
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         /* y */
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         /* z */
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     /* apply the mirror boundary conditions */
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         {// use mirror boundary conditions
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         {// use "spread" mirror conditions
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     /* perform interpolation */
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             // beurk, mais sinon tres inefficace, faudrait creer un iterateur
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     /* compute the interpolation weights */
00372     switch (splineDegree) 
00373     {
00374         Scalar  w, w2, w4, t, t0, t1;
00375     case 2:
00376         /* x */
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         /* y */
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         /* z */
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         /* x */
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         /* y */
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         /* z */
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         /* x */
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         /* y */
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         /* z */
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         /* x */
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         /* y */
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         /* z */
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 // *************************** ValueFast ****************************
00514 // this fct is speed optimized
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 //      int Depth =Ccoeff.Depth ();
00522 
00523     Scalar  xWeight[6], yWeight[6], zWeight[6];
00524     Scalar  interpolated;
00525 //      long    xIndex[6], yIndex[6], zIndex[6];
00526     long x0,y0,z0;
00527 //      long    Width2 = 2 * Width - 2, Height2 = 2 * Height - 2, Depth2 = 2 * Depth - 2;
00528 
00529 #ifdef BENCH
00530     double T0=DTime();
00531 #endif
00532     /* compute the interpolation indexes */
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     /* perform interpolation */
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             // beurk, mais sinon tres inefficace, faudrait creer un iterateur
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 //                  sumx += xWeight[i] * p[x0+i];
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 // *************************** SamplesToCoefficients ****************************
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 //  if((Width<=1 || Height<=1 || Depth<=1) && boundary==BOUNDARY_MIRROR)
00657 //  {
00658 //      fprintf(stderr,"SplineInterpolator3D:: BOUNDARY_MIRROR needs image sizes in all directions to be >1\n");
00659 // //       ThrowError("SplineInterpolator3D:: BOUNDARY_MIRROR needs image sizes in all directions to be >1");
00660 //  }
00661 
00662     vector<Scalar>  poles;
00663     long    x, y,z;
00664 
00665 
00666     /* recover the poles from a lookup table */
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     /* convert the image samples into interpolation coefficients */
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         /* in-place separable process, along x */
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     /* in-place separable process, along y */
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     /* in-place separable process, along z */
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 } /* end SamplesToCoefficients */
00738 
00739 
00740 template<class Im3DValue>
00741 void
00742 SplineInterpolator3D<Im3DValue>::ConvertToInterpolationCoefficients(
00743     vector<Im3DValue> &c,
00744     vector<Scalar> &z,
00745     Scalar  Tolerance   /* admissible relative error */
00746     )
00747 
00748 { /* begin ConvertToInterpolationCoefficients */
00749     long    DataLength=c.size();
00750     long    NbPoles=z.size();
00751     Scalar  Lambda = 1;
00752     long    n, k;
00753 
00754     /* special case required by mirror boundaries */
00755     if (DataLength == 1L) 
00756     {
00757         return;
00758     }
00759     /* compute the overall gain */
00760     for (k = 0L; k < NbPoles; k++) 
00761     {
00762         Lambda = Lambda * (1 - z[k]) * (1 - 1 / z[k]);
00763     }
00764     /* apply the gain */
00765     for (n = 0L; n < DataLength; n++) 
00766     {
00767         c[n] *= Lambda;
00768     }
00769     /* loop over all poles */
00770     for (k = 0L; k < NbPoles; k++) 
00771     {
00772         Scalar zk=z[k];
00773         /* causal initialization */
00774         c[0] = InitialCausalCoefficient(c, z[k], Tolerance);
00775         /* causal recursion */
00776         for (n = 1L; n < DataLength; n++) 
00777         {
00778             c[n] += zk * c[n - 1L];
00779         }
00780         /* anticausal initialization */
00781         c[DataLength - 1L] = InitialAntiCausalCoefficient(c, z[k]);
00782         /* anticausal recursion */
00783         for (n = DataLength - 2L; 0 <= n; n--) 
00784         {
00785             c[n] = zk * (c[n + 1L] - c[n]);
00786         }
00787     }
00788 } /* end ConvertToInterpolationCoefficients */
00789 
00790 /*--------------------------------------------------------------------------*/
00791 template<class Im3DValue>
00792 Im3DValue
00793 SplineInterpolator3D<Im3DValue>::InitialCausalCoefficient(
00794     vector<Im3DValue>   &c,         /* coefficients */
00795     Scalar  z,          /* actual pole */
00796     Scalar  Tolerance   /* admissible relative error */
00797     )
00798 
00799 {
00800     Im3DValue zero;
00801     SetZero<Im3DValue>::Set(zero);
00802 
00803     if(boundary==BOUNDARY_ZERO){return zero;}
00804  /* begin InitialCausalCoefficient */
00805     long    DataLength=c.size();
00806     Im3DValue   Sum;
00807     Scalar zn, z2n, iz;
00808     long    n, Horizon;
00809 
00810     /* this initialization corresponds to mirror boundaries */
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         /* accelerated loop */
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         /* full loop */
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 } /* end InitialCausalCoefficient */
00845 
00846 /*--------------------------------------------------------------------------*/
00847 template<class Im3DValue>
00848 Im3DValue
00849 SplineInterpolator3D<Im3DValue>::InitialAntiCausalCoefficient
00850 (
00851     vector<Im3DValue> &c,
00852     Scalar  z           /* actual pole */
00853     )
00854 
00855 {
00856     Im3DValue zero;
00857     SetZero<Im3DValue>::Set(zero);
00858 
00859     if(boundary==BOUNDARY_ZERO){return zero;}
00860  /* begin InitialAntiCausalCoefficient */
00861     long    DataLength=c.size();
00862     /* this initialization corresponds to mirror boundaries */
00863     return((z / (z * z - 1)) * (z * c[DataLength - 2L] + c[DataLength - 1L]));
00864 } /* end InitialAntiCausalCoefficient */
00865 
00866 
00867 
00868 
00869 
00870 #endif // _SplineInterpolation_hxx

Generated on Fri Jun 17 13:36:07 2005 for ImLib3D by  doxygen 1.4.2