/home/oan/prosjekt/gotools/segmentation/gpl_distro/lsseg_1.0_gpl/include/LevelSetFunction_implementation.h

Go to the documentation of this file.
00001 //===========================================================================
00002 // The Level-Set Segmentation Library (LSSEG)
00003 //
00004 //
00005 // Copyright (C) 2000-2005 SINTEF ICT, Applied Mathematics, Norway.
00006 //
00007 // This program is free software; you can redistribute it and/or          
00008 // modify it under the terms of the GNU General Public License            
00009 // as published by the Free Software Foundation version 2 of the License. 
00010 //
00011 // This program is distributed in the hope that it will be useful,        
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of         
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
00014 // GNU General Public License for more details.                           
00015 //
00016 // You should have received a copy of the GNU General Public License      
00017 // along with this program; if not, write to the Free Software            
00018 // Foundation, Inc.,                                                      
00019 // 59 Temple Place - Suite 330,                                           
00020 // Boston, MA  02111-1307, USA.                                           
00021 //
00022 // Contact information: e-mail: tor.dokken@sintef.no                      
00023 // SINTEF ICT, Department of Applied Mathematics,                         
00024 // P.O. Box 124 Blindern,                                                 
00025 // 0314 Oslo, Norway.                                                     
00026 // 
00027 //
00028 // Other licenses are also available for this software, notably licenses
00029 // for:
00030 // - Building commercial software.                                        
00031 // - Building software whose source code you wish to keep private.        
00032 //
00033 //===========================================================================
00034 //===========================================================================
00035 //                                                                           
00036 // File: LevelSetFunction_implementation.h                                   
00037 //                                                                           
00038 // Created: Fri Feb 17 16:36:53 2006                                         
00039 //                                                                           
00040 // Author: Odd A. Andersen <Odd.Andersen@sintef.no>
00041 //                                                                           
00042 // Revision: $Id: LevelSetFunction_implementation.h,v 1.7 2006/11/25 20:08:23 oan Exp $
00043 //                                                                           
00044 // Description:
00047 //                                                                           
00048 //===========================================================================
00049 
00050 #ifndef _LEVELSETFUNCTION_IMPLEMENTATION_H
00051 #define _LEVELSETFUNCTION_IMPLEMENTATION_H
00052 
00053 #include <cmath>
00054 
00055 namespace lsseg {
00056 
00057 //===========================================================================
00058 double LevelSetFunction::gradientNorm2D(int x, int y) const
00059 //===========================================================================
00060 {
00061     const int xp = --x >= 0 ? x : 0; ++x;
00062     const int xn = ++x < dimx() ? x : dimx() - 1; --x;
00063     const int yp = --y >= 0 ? y : 0; ++y;
00064     const int yn = ++y < dimy() ? y : dimy() - 1; --y;
00065     const double Icp = operator()(x, yp);
00066     const double Icn = operator()(x, yn);
00067     const double Ipc = operator()(xp, y);
00068     const double Inc = operator()(xn, y);
00069 
00070     const double x_diff = (xn - xp) == 2 ? 0.5 : 1; // inverse of distance
00071     const double y_diff = (yn - yp) == 2 ? 0.5 : 1; 
00072 
00073     const double dx = (Inc - Ipc) * x_diff;
00074     const double dy = (Icn - Icp) * y_diff;
00075     return sqrt((dx*dx) + (dy*dy));
00076 }
00077 
00078 //===========================================================================
00079 double LevelSetFunction::gradientNorm3D(int x, int y, int z) const
00080 //===========================================================================
00081 {
00082     const int xp = --x >= 0 ? x : 0; ++x;
00083     const int xn = ++x < dimx() ? x : dimx() - 1; --x;
00084     const int yp = --y >= 0 ? y : 0; ++y;
00085     const int yn = ++y < dimy() ? y : dimy() - 1; --y;
00086     const int zp = --z >= 0 ? z : 0; ++z;
00087     const int zn = ++z < dimz() ? z : dimz() - 1; --z;
00088     const double Icpc = operator()(x, yp,  z);
00089     const double Icnc = operator()(x, yn,  z);
00090     const double Ipcc = operator()(xp, y,  z);
00091     const double Incc = operator()(xn, y,  z);
00092     const double Iccp = operator()(x,  y, zp);
00093     const double Iccn = operator()(x,  y, zn);
00094     
00095     const double x_diff = (xn - xp) == 2 ? 0.5 : 1; // inverse of distance
00096     const double y_diff = (yn - yp) == 2 ? 0.5 : 1; 
00097     const double z_diff = (zn - zp) == 2 ? 0.5 : 1;
00098 
00099     const double dx = (Incc - Ipcc) * x_diff;
00100     const double dy = (Icnc - Icpc) * y_diff;
00101     const double dz = (Iccn - Iccp) * z_diff;
00102 
00103     return sqrt((dx*dx) + (dy*dy) + (dz*dz));
00104 }
00105 
00106 //===========================================================================
00107 double LevelSetFunction::curvature2D(int x, int y) const
00108 //===========================================================================
00109 {
00110     const double res = curvatureTimesGrad2D(x, y);
00111     return res / sqrt(cached_);
00112 }
00113 
00114 //===========================================================================
00115 double LevelSetFunction::curvature3D(int x, int y, int z) const
00116 //===========================================================================
00117 {
00118     const double res = curvatureTimesGrad3D(x, y, z); // will also set 'cached_' to square of grad
00119     return res / sqrt(cached_); 
00120 }
00121 
00122 
00123 //===========================================================================
00124 double LevelSetFunction::curvatureTimesGrad2D(int x, int y) const
00125 //===========================================================================
00126 {
00127     const double EPS=1.0e-5;
00128     const int xp = --x >= 0 ? x : 0; ++x;
00129     const int xn = ++x < dimx() ? x : dimx() - 1; --x;
00130     const int yp = --y >= 0 ? y : 0; ++y;
00131     const int yn = ++y < dimy() ? y : dimy() - 1; --y;
00132     const double Icp = operator()(x, yp);
00133     const double Icn = operator()(x, yn);
00134     const double Ipc = operator()(xp, y);
00135     const double Inc = operator()(xn, y);
00136     const double dx = (Inc - Ipc) * 0.5;
00137     const double dy = (Icn - Icp) * 0.5;
00138     const double norm2 = (dx*dx) + (dy*dy);
00139     cached_ = norm2 > EPS ? norm2 : EPS;
00140 
00141     if (norm2 < EPS) return 0; // cannot compute meaningful curvature with zero gradient
00142 
00143     const double Ipp = operator()(xp, yp);
00144     const double Inp = operator()(xn, yp);
00145     const double Icc = operator()(x,y);
00146     const double Ipn = operator()(xp, yn);
00147     const double Inn = operator()(xn, yn);
00148     const double dxx = Inc + Ipc - 2 * Icc;
00149     const double dyy = Icn + Icp - 2 * Icc;
00150     const double dxy = (dx * dy < 0) ? 
00151         0.5 * (2 * Icc + Ipp + Inn - Ipc - Inc - Icp - Icn) :
00152         0.5 * (Ipc + Inc + Icp + Icn - 2 * Icc - Ipn - Inp);
00153     return (dy * dy * dxx - 2 * dx * dy * dxy + dx * dx * dyy) / norm2;
00154 }
00155 
00156 //===========================================================================
00157 double LevelSetFunction::curvatureTimesGrad3D(int x, int y, int z) const
00158 //===========================================================================
00159 {
00160     const double EPS=1.0e-5;
00161     const int xp = --x >= 0 ? x : 0; ++x;
00162     const int xn = ++x < dimx() ? x : dimx() - 1; --x;
00163     const int yp = --y >= 0 ? y : 0; ++y;
00164     const int yn = ++y < dimy() ? y : dimy() - 1; --y;
00165     const int zp = --z >= 0 ? z : 0; ++z;
00166     const int zn = ++z < dimz() ? z : dimz() - 1; --z;
00167 
00168     const double Icpc = operator()(x, yp,  z);
00169     const double Icnc = operator()(x, yn,  z);
00170     const double Ipcc = operator()(xp, y,  z);
00171     const double Incc = operator()(xn, y,  z);
00172     const double Iccp = operator()(x,  y, zp);
00173     const double Iccn = operator()(x,  y, zn);
00174 
00175     const double x_diff = (xn - xp) == 2 ? 0.5 : 1; // inverse of distance
00176     const double y_diff = (yn - yp) == 2 ? 0.5 : 1; 
00177     const double z_diff = (zn - zp) == 2 ? 0.5 : 1;
00178 
00179     const double dx = (Incc - Ipcc) * x_diff;
00180     const double dy = (Icnc - Icpc) * y_diff;
00181     const double dz = (Iccn - Iccp) * z_diff;
00182     const double norm2 = (dx*dx) + (dy*dy) + (dz*dz);
00183     cached_ = norm2 > EPS ? norm2 : EPS;
00184 
00185     if(norm2 < EPS) return 0; // cannot compute meaningful curvature with zero gradient
00186 
00187     const double Ippc = operator()(xp, yp,  z);
00188     const double Ipcp = operator()(xp,  y, zp);
00189     const double Ipcn = operator()(xp,  y, zn);
00190     const double Ipnc = operator()(xp, yn,  z);
00191     const double Icpp = operator()( x, yp, zp);
00192     const double Icpn = operator()( x, yp, zn);
00193     const double Iccc = operator()( x,  y,  z);
00194     const double Icnp = operator()( x, yn, zp);
00195     const double Icnn = operator()( x, yn, zn);
00196     const double Inpc = operator()(xn, yp,  z);
00197     const double Incp = operator()(xn,  y, zp);
00198     const double Incn = operator()(xn,  y, zn);
00199     const double Innc = operator()(xn, yn,  z);
00200 
00201     const double dxx = Incc + Ipcc - 2 * Iccc;
00202     const double dyy = Icnc + Icpc - 2 * Iccc;
00203     const double dzz = Iccn + Iccp - 2 * Iccc;
00204     const double dxy = (dx * dy < 0) ? 
00205         0.5 * (2 * Iccc + Ippc + Innc - Ipcc - Incc - Icpc - Icnc) :
00206         0.5 * (Ipcc + Incc + Icpc + Icnc - 2 * Iccc - Ipnc - Inpc);
00207     const double dxz =  (dx * dz < 0) ? 
00208         0.5 * (2 * Iccc + Ipcp + Incn - Ipcc - Incc - Iccp - Iccn) :
00209         0.5 * (Ipcc + Incc + Iccp + Iccn - 2 * Iccc - Ipcn - Incp);
00210     const double dyz = (dy * dz < 0) ?
00211         0.5 * (2 * Iccc + Icpp + Icnn - Icpc - Icnc - Iccp - Iccn) :
00212         0.5 * (Icpc + Icnc + Iccp + Iccn - 2 * Iccc - Icpn - Icnp);
00213 
00214 
00215     return (dx * dx * (dyy + dzz) + 
00216             dy * dy * (dxx + dzz) +
00217             dz * dz * (dxx + dyy) - 
00218             2 * (dx * dy * dxy + 
00219                  dx * dz * dxz +
00220                  dy * dz * dyz)
00221             ) / norm2;
00222 }
00223 
00224 //===========================================================================
00225 void LevelSetFunction::curvature2D(Image<double>& target, Mask* mask) const
00226 //===========================================================================
00227 {
00228     assert(!mask || spatial_compatible(*mask));
00229     MESSAGE_IF(dimz() > 1, "Warning: applying 2D method on a grid with dim(z) > 1");
00230     const int X = dimx();
00231     const int Y = dimy();
00232     if (!size_compatible(target)) {
00233         target.resize(X, Y);
00234     }
00235     if (!mask) {
00236         for (int y = 0; y < Y; ++y) {
00237             for (int x = 0; x < X; ++x) {
00238                 target(x, y) = curvature2D(x, y);
00239             }
00240         }
00241     } else {
00242         char* mptr = mask->begin();
00243         for (int y = 0; y < Y; ++y) {
00244             for (int x = 0; x < X; ++x) {
00245                 if (*mptr++) {
00246                     target(x, y) = curvature2D(x, y);
00247                 }
00248             }
00249         }
00250     }
00251 }
00252 
00253 //===========================================================================
00254 void LevelSetFunction::curvature3D(Image<double>& target, Mask* mask) const
00255 //===========================================================================
00256 {
00257     assert(!mask || spatial_compatible(*mask));
00258     const int X = dimx();
00259     const int Y = dimy();
00260     const int Z = dimz();
00261     if (!size_compatible(target)) {
00262         target.resize(X, Y, Z);
00263     }
00264     if (!mask) {
00265         for (int z = 0; z < Z; ++z) {
00266             for (int y = 0; y < Y; ++y) {
00267                 for (int x = 0; x < X; ++x) {
00268                     target(x, y, z) = curvature3D(x, y, z);
00269                 }
00270             }
00271         }
00272     } else {
00273         char* mptr = mask->begin();
00274         for (int z = 0; z < Z; ++z) {
00275             for (int y = 0; y < Y; ++y) {
00276                 for (int x = 0; x < X; ++x) {
00277                     if (*mptr++) {
00278                         target(x, y, z) = curvature3D(x, y, z);
00279                     }
00280                 }
00281             }
00282         }
00283     }
00284 }
00285 
00286 //===========================================================================
00287 void LevelSetFunction::gradientNorm2D(Image<double>& target, Mask* mask) const
00288 //===========================================================================
00289 {
00290     assert(!mask || spatial_compatible(*mask));
00291     MESSAGE_IF(dimz() > 1, "Warning: applying 2D method on a grid with dim(z) > 1");
00292     const int X = dimx();
00293     const int Y = dimy();
00294     if (!size_compatible(target)) {
00295         target.resize(X, Y);
00296     }
00297     if (!mask) {
00298         for (int y = 0; y < Y; ++y) {
00299             for (int x = 0; x < X; ++x) {
00300                 target(x, y) = gradientNorm2D(x, y);
00301             }
00302         }
00303     } else {
00304         char* mptr = mask->begin();
00305         for (int y = 0; y < Y; ++y) {
00306             for (int x = 0; x < X; ++x) {
00307                 if (*mptr++) {
00308                     target(x, y) = gradientNorm2D(x, y);
00309                 }
00310             }
00311         }
00312 
00313     }
00314 }
00315 
00316 //===========================================================================
00317 void LevelSetFunction::gradientNorm3D(Image<double>& target, Mask* mask) const
00318 //===========================================================================
00319 {
00320     assert(!mask || spatial_compatible(*mask));
00321     const int X = dimx();
00322     const int Y = dimy();
00323     const int Z = dimz();
00324     if (!size_compatible(target)) {
00325         target.resize(X, Y, Z);
00326     }
00327     if (!mask) {
00328         for (int z = 0; z < Z; ++z) {
00329             for (int y = 0; y < Y; ++y) {
00330                 for (int x = 0; x < X; ++x) {
00331                     target(x, y, z) = gradientNorm3D(x, y, z);
00332                 }
00333             }
00334         }
00335     } else {
00336         char* mptr = mask->begin();
00337         for (int z = 0; z < Z; ++z) {
00338             for (int y = 0; y < Y; ++y) {
00339                 for (int x = 0; x < X; ++x) {
00340                     if (*mptr++) {
00341                         target(x, y, z) = gradientNorm3D(x, y, z);
00342                     }
00343                 }
00344             }
00345         }
00346     }
00347 }
00348 
00349 
00350 //===========================================================================
00351 void LevelSetFunction::curvatureTimesGrad2D(Image<double>& target, Mask* mask) const
00352 //===========================================================================
00353 {
00354     assert(!mask || spatial_compatible(*mask));
00355     MESSAGE_IF(dimz() > 1, "Warning: applying 2D method on a grid with dim(z) > 1");
00356     const int X = dimx();
00357     const int Y = dimy();
00358     if (!size_compatible(target)) {
00359         target.resize(X, Y);
00360     }
00361 
00362     if (!mask) {
00363         for (int y = 0; y < Y; ++y) {
00364             for (int x = 0; x < X; ++x) {
00365                 target(x, y) = curvatureTimesGrad2D(x, y);
00366             }
00367         }
00368     } else {
00369         char* mptr = mask->begin();
00370         for (int y = 0; y < Y; ++y) {
00371             for (int x = 0; x < X; ++x) {
00372                 if (*mptr++) {
00373                     target(x, y) = curvatureTimesGrad2D(x, y);
00374                 }
00375             }
00376         }
00377     }
00378 }
00379 
00380 //===========================================================================
00381 void LevelSetFunction::curvatureTimesGrad3D(Image<double>& target, Mask* mask) const
00382 //===========================================================================
00383 {
00384     assert(!mask || spatial_compatible(*mask));
00385     const int X = dimx();
00386     const int Y = dimy();
00387     const int Z = dimz(); 
00388     if (!size_compatible(target)) {
00389         target.resize(X, Y, Z);
00390     }
00391 
00392     if (!mask) {
00393         for (int z = 0; z < Z; ++z) {
00394             for (int y = 0; y < Y; ++y) {
00395                 for (int x = 0; x < X; ++x) {
00396                     target(x, y, z) = curvatureTimesGrad3D(x, y, z);
00397                 }
00398             }
00399         }
00400     } else {
00401         char* mptr = mask->begin();
00402         for (int z = 0; z < Z; ++z) {
00403             for (int y = 0; y < Y; ++y) {
00404                 for (int x = 0; x < X; ++x) {
00405                     if (*mptr++) {
00406                         target(x, y, z) = curvatureTimesGrad3D(x, y, z);
00407                     }
00408                 }
00409             }
00410         }
00411     }
00412 }
00413 
00414 
00415 }; // end namespace lsseg
00416 
00417 #endif // _LEVELSETFUNCTION_IMPLEMENTATION_H
00418 

Generated on Tue Nov 28 18:35:47 2006 for lsseg by  doxygen 1.4.7