/home/oan/prosjekt/gotools/segmentation/gpl_distro/lsseg_1.0_gpl/src/level_set.C

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: level_set.C                                                         
00037 //                                                                           
00038 // Created: Tue Oct 25 14:02:40 2005                                         
00039 //                                                                           
00040 // Author: Odd A. Andersen <Odd.Andersen@sintef.no>
00041 //                                                                           
00042 // Revision: $Id: level_set.C,v 1.35 2006/11/25 20:08:28 oan Exp $
00043 //                                                                           
00044 // Description:
00047 //                                                                           
00048 //===========================================================================
00049 
00050 #include <functional>
00051 #include <stdexcept>
00052 #include <time.h>
00053 #include <vector>
00054 #include <boost/lambda/lambda.hpp>
00055 #include "Region.h"
00056 #include "errormacros.h"
00057 #include "Image.h"
00058 #include "LevelSetFunction.h"
00059 #include "level_set.h"
00060 #include "simple_tools.h"
00061 #include "cimg_dependent.h"
00062 //#include "GoTensorProductSpline.h"
00063 //#include "GLviewUtils.h"
00064 #include "Mask.h"
00065 #include "Filters.h"
00066 #include "DiscreteApproximations.h"
00067 
00068 using namespace boost::lambda;
00069 using namespace std;
00070 //using namespace Go;
00071 using namespace lsseg;
00072 
00073 namespace  // anonymous namespace 
00074 {
00075     void visualize_multisets_impl(vector<const LevelSetFunction*> phi_pts,
00076                                   Image<double>& target,
00077                                   const int** const rgb_color);
00078 
00079     inline void godunov_phi_2D(double a_term, 
00080                                double phi_xl, double phi_xr,
00081                                double phi_yl, double phi_yr,
00082                                double& phi_x,
00083                                double& phi_y);
00084 
00085     inline void godunov_phi_3D(double a_term, 
00086                                double phi_xl, double phi_xr,
00087                                double phi_yl, double phi_yr,
00088                                double phi_zl, double phi_zr,
00089                                double& phi_x,
00090                                double& phi_y,
00091                                double& phi_z);
00092 
00093 //===========================================================================
00094 // differential approximation schemes
00095 //===========================================================================
00096 
00097 inline bool defined(int x, int y, int z, int X, int Y, int Z, const Mask* mask) 
00098 {
00099     return (x >= 0 && x < X &&
00100             y >= 0 && y < Y &&
00101             z >= 0 && z < Z &&
00102             (!mask || (*mask)(x, y, z)));
00103 }
00104 
00105 double neumann_curvature_at(int x, 
00106                             int y, 
00107                             int z, 
00108                             const Image<double>& phi, 
00109                             const Mask* mask);
00110 
00111 double dirichlet_curvature_at(int x, 
00112                               int y,
00113                               int z, 
00114                               const Image<double>& phi,
00115                               const Mask* mask);
00116 
00117 void neumann_d1_leftright_2D(int x, 
00118                              int y, 
00119                              const Image<double>& phi, 
00120                              const Mask* mask,
00121                              double& dxl, 
00122                              double& dxr, 
00123                              double& dyl, 
00124                              double& dyr);
00125 
00126 void dirichlet_d1_leftright_2D(int x, 
00127                                int y, 
00128                                const Image<double>& phi, 
00129                                const Mask* mask,
00130                                double& dxl, 
00131                                double& dxr, 
00132                                double& dyl, 
00133                                double& dyr);
00134 
00135 void neumann_d1_leftright_3D(int x, 
00136                              int y, 
00137                              int z, 
00138                              const Image<double>& phi, 
00139                              const Mask* mask,
00140                              double& dxl, 
00141                              double& dxr, 
00142                              double& dyl, 
00143                              double& dyr, 
00144                              double& dzl, 
00145                              double& dzr);
00146 
00147 void dirichlet_d1_leftright_3D(int x, 
00148                                int y, 
00149                                int z, 
00150                                const Image<double>& phi, 
00151                                const Mask* mask,
00152                                double& dxl, 
00153                                double& dxr, 
00154                                double& dyl, 
00155                                double& dyr, 
00156                                double& dzl, 
00157                                double& dzr);
00158     
00159 }; // end anonymous namespace 
00160 
00161 namespace lsseg {
00162 
00163 
00164 //==============================================================================
00165 void normal_direction_flow_2D(const LevelSetFunction& phi, 
00166                               LevelSetFunction& advect,
00167                               BorderCondition bcond,
00168                               double& H1,
00169                               double& H2,
00170                               const Mask* const changes_allowed_mask,
00171                               const Mask* const defined_region_mask)
00172 //==============================================================================
00173 {
00174     assert(phi.dimz() == 1); // this should be the 2D case
00175     assert(advect.size_compatible(phi));
00176     assert(phi.numChannels() == 1);
00177     const int X = phi.dimx();
00178     const int Y = phi.dimy();
00179     H1 = H2 = 0;
00180 
00181     void (*der_estimate)(int, int, const Image<double>&, const Mask*,
00182                          double&, double&, double&, double&);
00183     if (bcond == NEUMANN) {
00184         der_estimate = neumann_d1_leftright_2D;
00185     } else {
00186         assert(bcond == DIRICHLET);
00187         der_estimate = dirichlet_d1_leftright_2D;
00188     }
00189 
00190     const Mask::value_type* m_it = changes_allowed_mask ? changes_allowed_mask->begin() : 0;
00191 
00192     for (int yc = 0; yc < Y; ++yc) {
00193         for (int xc = 0; xc < X; ++xc) {
00194             if (changes_allowed_mask && !(*m_it++)) {
00195                 // the changes_allowed_mask is defined and is false at this pixel, => no advection
00196                 advect(xc, yc) = 0;
00197                 continue;
00198             }
00199             const double a_term = advect(xc, yc);
00200             double phi_xl, phi_xr, phi_yl, phi_yr;
00201             
00202             der_estimate(xc, yc, phi, 
00203                          defined_region_mask, 
00204                          phi_xl, phi_xr,
00205                          phi_yl, phi_yr);
00206             
00207             double phi_x, phi_y;
00208             godunov_phi_2D(a_term, 
00209                            phi_xl, phi_xr, 
00210                            phi_yl, phi_yr, 
00211                            phi_x, 
00212                            phi_y);
00213             
00214             const double norm_phi2 = phi_x * phi_x + phi_y * phi_y;
00215             const double norm_phi = sqrt(norm_phi2);
00216             advect(xc, yc) = -a_term * norm_phi; 
00217             
00218             if (norm_phi > 0) {
00219                 const double norm_inv = double(1) / norm_phi;
00220                 const double fac = a_term * norm_inv;
00221                 double tmp = fabs(phi_x * fac);
00222                 H1 = H1 > tmp ? H1 : tmp;
00223                 tmp = fabs(phi_y * fac);
00224                 H2 = H2 > tmp ? H2 : tmp;
00225             }
00226         }
00227     }
00228 }
00229 
00230 //==============================================================================
00231 void normal_direction_flow_3D(const LevelSetFunction& phi, 
00232                               LevelSetFunction& advect,
00233                               BorderCondition bcond,
00234                               double& H1,
00235                               double& H2,
00236                               double& H3,
00237                               const Mask* const changes_allowed_mask,
00238                               const Mask* const defined_region_mask)
00239 //==============================================================================
00240 {
00241     assert(advect.size_compatible(phi));
00242     assert(phi.numChannels() == 1);
00243     const int X = phi.dimx();
00244     const int Y = phi.dimy();
00245     const int Z = phi.dimz();
00246     H1 = H2 = H3 = 0;
00247 
00248     void (*der_estimate)(int, int, int, const Image<double>&, const Mask*,
00249                          double&, double&, double&, double&, double&, double&);
00250     if (bcond == NEUMANN) {
00251         der_estimate = neumann_d1_leftright_3D;
00252     } else {
00253         assert(bcond == DIRICHLET);
00254         der_estimate = dirichlet_d1_leftright_3D;
00255     }
00256 
00257     const Mask::value_type* m_it = changes_allowed_mask ? changes_allowed_mask->begin() : 0;
00258 
00259     for (int zc = 0; zc < Z; ++zc) {
00260         for (int yc = 0; yc < Y; ++yc) {
00261             for (int xc = 0; xc < X; ++xc) {
00262                 if (changes_allowed_mask && !(*m_it++)) {
00263                     // the changes_allowed_mask is defined and is false at this pixel, => no advection
00264                     advect(xc, yc, zc) = 0;
00265                     continue;
00266                 }
00267                 const double a_term = advect(xc, yc, zc);
00268                 
00269                 double phi_xl, phi_xr, phi_yl, phi_yr, phi_zl, phi_zr;
00270                 
00271                 der_estimate(xc, yc, zc, phi, 
00272                              defined_region_mask, 
00273                              phi_xl, phi_xr,
00274                              phi_yl, phi_yr,
00275                              phi_zl, phi_zr);
00276                 double phi_x, phi_y, phi_z;
00277                 godunov_phi_3D(a_term, 
00278                                phi_xl, phi_xr, 
00279                                phi_yl, phi_yr, 
00280                                phi_zl, phi_zr,
00281                                phi_x, 
00282                                phi_y,
00283                                phi_z);
00284                 const double norm_phi2 = phi_x * phi_x + phi_y * phi_y + phi_z * phi_z;
00285                 const double norm_phi = sqrt(norm_phi2);
00286                 advect(xc, yc, zc) = -a_term * norm_phi;
00287                 
00288                 if (norm_phi > 0) {
00289                     const double norm_inv = double(1) / norm_phi;
00290                     const double fac = a_term * norm_inv;
00291                     double tmp = fabs(phi_x * fac);
00292                     
00293                     H1 = H1 > tmp ? H1 : tmp;
00294                     tmp = fabs(phi_y * fac);
00295                     H2 = H2 > tmp ? H2 : tmp;
00296                     tmp = fabs(phi_z * fac);
00297                     H3 = H3 > tmp ? H3 : tmp;
00298                 }
00299             }
00300         }
00301     }
00302 }
00303 
00304 //===========================================================================
00305 void visualize_multisets(const LevelSetFunction** const images,
00306                          int num_images,
00307                          Image<double>& target,
00308                          const int** const rgb_color) 
00309 //===========================================================================
00310 {
00311     vector<const LevelSetFunction* > phi_pointers(images, images + num_images);
00312 //     for (int i = 0; i < num_images; ++i) {
00313 //      phi_pointers[i] = const_cast<Image<double>* >(images + i);
00314 //     }
00315     visualize_multisets_impl(phi_pointers, target, rgb_color);
00316 }
00317 
00318 //===========================================================================
00319 int visualize_level_set(const LevelSetFunction& img, 
00320                          Image<double>& target, 
00321                          double threshold,
00322                          double outside_intensity,
00323                          double curve_intensity,
00324                          double interior_intensity,
00325                          const Mask* const mask,
00326                          double mask_intensity)
00327 //===========================================================================
00328 {
00329     int num_border_pixels = 0;
00330     ALWAYS_ERROR_IF(img.numChannels() != 1, "dim should be 1 here");
00331     assert(img.size_compatible(target));
00332     assert(!mask || img.size_compatible(*mask)); // check for size if not null pointer
00333     bool no_mask = (mask == 0);
00334     for (int z = 0; z < img.dimz(); ++z) {
00335         for (int y = 0; y < img.dimy(); ++y) {
00336             for (int x = 0; x < img.dimx(); ++x) {
00337                 if (no_mask || (*mask)(x, y, z) > 0) {
00338                     double Iccc = img(x, y, z);
00339                     double Icnc = img(x, (y == img.dimy() - 1) ? y : y+1, z);
00340                     double Incc = img((x == img.dimx() - 1) ? x : x+1, y, z);
00341                     double Iccn = img(x, y, (z == img.dimz() - 1) ? z : z+1);
00342                     double Icpc = img(x, (y==0) ? y : y-1, z);
00343                     double Ipcc = img((x==0) ? 0 : x-1, y, z);
00344                     double Iccp = img(x, y, (z==0) ? 0 : z-1);
00345 
00346                     Iccc -= threshold;
00347                     Icnc -= threshold;
00348                     Incc -= threshold;
00349                     Iccn -= threshold;
00350                     Icpc -= threshold;
00351                     Ipcc -= threshold;
00352                     Iccp -= threshold;
00353                     
00354                     if (Iccc * Incc < 0 || (Iccc == 0 && Incc != 0) ||
00355                         Iccc * Icnc < 0 || (Iccc == 0 && Icnc != 0) ||
00356                         Iccc * Iccn < 0 || (Iccc == 0 && Iccn != 0) ||
00357                         Iccc * Ipcc < 0 || (Iccc == 0 && Ipcc != 0) ||
00358                         Iccc * Icpc < 0 || (Iccc == 0 && Icpc != 0) ||
00359                         Iccc * Iccp < 0 || (Iccc == 0 && Iccp != 0)) {
00360                         target(x, y, z) = curve_intensity;
00361                         ++num_border_pixels;
00362                     } else {
00363                         target(x, y, z) = Iccc < 0 ? interior_intensity : outside_intensity;
00364                     }
00365                 } else {
00366                     target(x, y, z) = mask_intensity;
00367                 }
00368             }
00369         }
00370     }
00371     return num_border_pixels;
00372 }
00373 
00374 }; // end namespace lsseg
00375 
00376 namespace  // anonymous namespace 
00377 {
00378 
00379 //===========================================================================
00380 void neumann_d1_leftright_2D(int x, 
00381                              int y, 
00382                              const Image<double>& phi, 
00383                              const Mask* mask,
00384                              double& dxl, 
00385                              double& dxr, 
00386                              double& dyl, 
00387                              double& dyr)
00388 //===========================================================================
00389 {
00390     assert(phi.dimz() == 1);
00391     const int X = phi.dimx();
00392     const int Y = phi.dimy();
00393 
00394     // negative value means that the index has not been set
00395     int xp(-1), yp(-1), xn(-1), yn(-1);
00396 
00397     if (!mask) {
00398         if (x >   0) { xp = x-1; }
00399         if (x < X-1) { xn = x+1; }
00400         if (y >   0) { yp = y-1; }
00401         if (y < Y-1) { yn = y+1; }
00402     } else {
00403         if (x >   0 && (*mask)(x-1, y)) { xp = x-1; }
00404         if (x < X-1 && (*mask)(x+1, y)) { xn = x+1; }
00405         if (y >   0 && (*mask)(x, y-1)) { yp = y-1; }
00406         if (y < Y-1 && (*mask)(x, y+1)) { yn = y+1; }
00407     }
00408     const double Icc = phi(x, y);
00409     const double Ipc = (xp >= 0) ? phi(xp, y) : (xn >= 0) ? 2 * Icc - phi(xn, y) : Icc;
00410     const double Inc = (xn >= 0) ? phi(xn, y) : (xp >= 0) ? 2 * Icc - phi(xp, y) : Icc;
00411     const double Icp = (yp >= 0) ? phi(x, yp) : (yn >= 0) ? 2 * Icc - phi(x, yn) : Icc;
00412     const double Icn = (yn >= 0) ? phi(x, yn) : (yp >= 0) ? 2 * Icc - phi(x, yp) : Icc;
00413 
00414     dxl = Icc - Ipc;
00415     dxr = Inc - Icc;
00416     dyl = Icc - Icp;
00417     dyr = Icn - Icc;
00418 
00419 }
00420 
00421 //===========================================================================
00422 void dirichlet_d1_leftright_2D(int x, 
00423                                int y, 
00424                                const Image<double>& phi, 
00425                                const Mask* mask,
00426                                double& dxl, 
00427                                double& dxr, 
00428                                double& dyl, 
00429                                double& dyr)
00430 //===========================================================================
00431 {
00432     const int X = phi.dimx();
00433     const int Y = phi.dimy();
00434 
00435     // negative value means that the index has not been set
00436     int xp, yp, xn, yn;
00437     if (!mask) {
00438         xp = (x > 0) ? x-1 : x;
00439         yp = (y > 0) ? y-1 : x;
00440         xn = (x < X-1) ? x+1 : x;
00441         yn = (y < Y-1) ? y+1 : y;
00442     } else {
00443         xp = (x > 0 && (*mask)(x-1,   y)) ? x-1 : x;
00444         yp = (y > 0 && (*mask)(  x, y-1)) ? y-1 : y;
00445         xn = (x < X-1 && (*mask)(x+1,   y)) ? x+1 : x;
00446         yn = (y < Y-1 && (*mask)(  x, y+1)) ? y+1 : y;
00447     }
00448     
00449     double Icc = phi(x, y);
00450     double Ipc = phi(xp, y);
00451     double Inc = phi(xn, y);
00452     double Icp = phi(x, yp);
00453     double Icn = phi(x, yn);
00454 
00455     dxl = Icc - Ipc;
00456     dxr = Inc - Icc;
00457     dyl = Icc - Icp;
00458     dyr = Icn - Icc;
00459 }
00460 
00461 
00462 //===========================================================================
00463 void dirichlet_d1_leftright_3D(int x, 
00464                                int y, 
00465                                int z, 
00466                                const Image<double>& phi, 
00467                                const Mask* mask,
00468                                double& dxl, 
00469                                double& dxr, 
00470                                double& dyl, 
00471                                double& dyr, 
00472                                double& dzl, 
00473                                double& dzr)
00474 //===========================================================================
00475 {
00476     const int X = phi.dimx();
00477     const int Y = phi.dimy();
00478     const int Z = phi.dimz();
00479 
00480     // negative value means that the index has not been set
00481     int xp, yp, zp, xn, yn, zn;
00482     if (!mask) {
00483         xp = (x > 0) ? x-1 : x;
00484         yp = (y > 0) ? y-1 : x;
00485         zp = (z > 0) ? z-1 : x;
00486         xn = (x < X-1) ? x+1 : x;
00487         yn = (y < Y-1) ? y+1 : y;
00488         zn = (z < Z-1) ? z+1 : z;
00489     } else {
00490         xp = (x > 0 && (*mask)(x-1,   y,   z)) ? x-1 : x;
00491         yp = (y > 0 && (*mask)(  x, y-1,   z)) ? y-1 : y;
00492         zp = (z > 0 && (*mask)(  x,   y, z-1)) ? z-1 : z;
00493         xn = (x < X-1 && (*mask)(x+1,   y,   z)) ? x+1 : x;
00494         yn = (y < Y-1 && (*mask)(  x, y+1,   z)) ? y+1 : y;
00495         zn = (z < Z-1 && (*mask)(  x,   y, z+1)) ? z+1 : z;
00496     }
00497     
00498     double Iccc = phi(x, y, z);
00499     double Ipcc = phi(xp, y, z);
00500     double Incc = phi(xn, y, z);
00501     double Icpc = phi(x, yp, z);
00502     double Icnc = phi(x, yn, z);
00503     double Iccp = phi(x, y, zp);
00504     double Iccn = phi(x, y, zn);
00505 
00506     dxl = Iccc - Ipcc;
00507     dxr = Incc - Iccc;
00508     dyl = Iccc - Icpc;
00509     dyr = Icnc - Iccc;
00510     dzl = Iccc - Iccp;
00511     dzr = Iccn - Iccc;
00512 }
00513 
00514 
00515 //===========================================================================
00516 void neumann_d1_leftright_3D(int x, 
00517                              int y, 
00518                              int z, 
00519                              const Image<double>& phi, 
00520                              const Mask* mask,
00521                              double& dxl, 
00522                              double& dxr, 
00523                              double& dyl, 
00524                              double& dyr, 
00525                              double& dzl, 
00526                              double& dzr)
00527 //===========================================================================
00528 {
00529     const int X = phi.dimx();
00530     const int Y = phi.dimy();
00531     const int Z = phi.dimz();
00532 
00533     // negative value means that the index has not been set
00534     int xp(-1), yp(-1), zp(-1), xn(-1), yn(-1), zn(-1);
00535 
00536     if (!mask) {
00537         if (x >   0) { xp = x-1; }
00538         if (x < X-1) { xn = x+1; }
00539         if (y >   0) { yp = y-1; }
00540         if (y < Y-1) { yn = y+1; }
00541         if (z >   0) { zp = z-1; }
00542         if (z < Z-1) { zn = z+1; }
00543     } else {
00544         if (x >   0 && (*mask)(x-1, y, z)) { xp = x-1; }
00545         if (x < X-1 && (*mask)(x+1, y, z)) { xn = x+1; }
00546         if (y >   0 && (*mask)(x, y-1, z)) { yp = y-1; }
00547         if (y < Y-1 && (*mask)(x, y+1, z)) { yn = y+1; }
00548         if (z >   0 && (*mask)(x, y, z-1)) { zp = z-1; }
00549         if (z < Z-1 && (*mask)(x, y, z+1)) { zn = z+1; }
00550     }
00551     const double Iccc = phi(x, y, z);
00552     const double Ipcc = (xp >= 0) ? phi(xp, y, z) : (xn >= 0) ? 2 * Iccc - phi(xn, y, z) : Iccc;
00553     const double Incc = (xn >= 0) ? phi(xn, y, z) : (xp >= 0) ? 2 * Iccc - phi(xp, y, z) : Iccc;
00554     const double Icpc = (yp >= 0) ? phi(x, yp, z) : (yn >= 0) ? 2 * Iccc - phi(x, yn, z) : Iccc;
00555     const double Icnc = (yn >= 0) ? phi(x, yn, z) : (yp >= 0) ? 2 * Iccc - phi(x, yp, z) : Iccc;
00556     const double Iccp = (zp >= 0) ? phi(x, y, zp) : (zn >= 0) ? 2 * Iccc - phi(x, y, zn) : Iccc;
00557     const double Iccn = (zn >= 0) ? phi(x, y, zn) : (zp >= 0) ? 2 * Iccc - phi(x, y, zp) : Iccc;
00558 
00559 
00560     dxl = Iccc - Ipcc;
00561     dxr = Incc - Iccc;
00562     dyl = Iccc - Icpc;
00563     dyr = Icnc - Iccc;
00564     dzl = Iccc - Iccp;
00565     dzr = Iccn - Iccc;
00566 }
00567 
00568 //===========================================================================
00569 double dirichlet_curvature_at(int x, 
00570                               int y,
00571                               int z, 
00572                               const Image<double>& phi,
00573                               const Mask* mask)
00574 //===========================================================================
00575 {
00576     MESSAGE("dirichlet_curvature_at() unimplemented.");
00577     exit(0);
00578 }
00579 
00580 //===========================================================================
00581 double neumann_curvature_at(int x, 
00582                             int y, 
00583                             int z, 
00584                             const Image<double>& phi, 
00585                             const Mask* mask)
00586 //===========================================================================
00587 {
00588     const double EPS=1.0e-10;
00589     const int X = phi.dimx();
00590     const int Y = phi.dimy();
00591     const int Z = phi.dimz();
00592     
00593     // negative value means that the index has not been set
00594    int xp(-1), yp(-1), zp(-1), xn(-1), yn(-1), zn(-1);
00595 
00596     if (!mask) {
00597         if (x >   0) { xp = x-1; }
00598         if (x < X-1) { xn = x+1; }
00599         if (y >   0) { yp = y-1; }
00600         if (y < Y-1) { yn = y+1; }
00601         if (z >   0) { zp = z-1; }
00602         if (z < Z-1) { zn = z+1; }
00603     } else {
00604         if (x >   0 && (*mask)(x-1, y, z)) { xp = x-1; }
00605         if (x < X-1 && (*mask)(x+1, y, z)) { xn = x+1; }
00606         if (y >   0 && (*mask)(x, y-1, z)) { yp = y-1; }
00607         if (y < Y-1 && (*mask)(x, y+1, z)) { yn = y+1; }
00608         if (z >   0 && (*mask)(x, y, z-1)) { zp = z-1; }
00609         if (z < Z-1 && (*mask)(x, y, x+1)) { zn = z+1; }
00610     }
00611     double Iccc = phi(x, y, z);
00612     double Ipcc = (xp >= 0) ? phi(xp, y, z) : (xn >= 0) ? 2 * Iccc - phi(xn, y, z) : Iccc;
00613     double Incc = (xn >= 0) ? phi(xn, y, z) : (xp >= 0) ? 2 * Iccc - phi(xp, y, z) : Iccc;
00614     double Icpc = (yp >= 0) ? phi(x, yp, z) : (yn >= 0) ? 2 * Iccc - phi(x, yn, z) : Iccc;
00615     double Icnc = (yn >= 0) ? phi(x, yn, z) : (yp >= 0) ? 2 * Iccc - phi(x, yp, z) : Iccc;
00616     double Iccp = (zp >= 0) ? phi(x, y, zp) : (zn >= 0) ? 2 * Iccc - phi(x, y, zn) : Iccc;
00617     double Iccn = (zn >= 0) ? phi(x, y, zn) : (zp >= 0) ? 2 * Iccc - phi(x, y, zp) : Iccc;
00618 
00619     double dx = 0.5 * (Incc - Ipcc);
00620     double dy = 0.5 * (Icnc - Icpc);
00621     double dz = 0.5 * (Iccn - Iccp);
00622     
00623     double norm2 = (dx * dx + dy * dy + dz * dz);
00624     
00625     if (norm2 < EPS) return 0; // close to zero gradient norm - no significant curvature
00626 
00627     //double Ippp = defined(x-1,y-1,z-1,X,Y,Z,mask) ? phi(x-1,y-1,z-1) : Ipcc+Icpc+Iccp-2*Iccc;
00628     double Ippc = defined(x-1,y-1,z  ,X,Y,Z,mask) ? phi(x-1,y-1,z )  : Ipcc+Icpc     -  Iccc;
00629     //double Ippn = defined(x-1,y-1,z+1,X,Y,Z,mask) ? phi(x-1,y-1,z+1) : Ipcc+Icpc+Iccn-2*Iccc;
00630     double Ipcp = defined(x-1,y  ,z-1,X,Y,Z,mask) ? phi(x-1,y  ,z-1) : Ipcc+     Iccp-  Iccc;
00631     double Ipcn = defined(x-1,y  ,z+1,X,Y,Z,mask) ? phi(x-1,y  ,z+1) : Ipcc+     Iccn-  Iccc;
00632     //double Ipnp = defined(x-1,y+1,z-1,X,Y,Z,mask) ? phi(x-1,y+1,z-1) : Ipcc+Icnc+Iccp-2*Iccc;
00633     double Ipnc = defined(x-1,y+1,z  ,X,Y,Z,mask) ? phi(x-1,y+1,z  ) : Ipcc+Icnc     -  Iccc;
00634     //double Ipnn = defined(x-1,y+1,z+1,X,Y,Z,mask) ? phi(x-1,y+1,z+1) : Ipcc+Icnc+Iccn-2*Iccc;
00635     double Icpp = defined(x  ,y-1,z-1,X,Y,Z,mask) ? phi(x  ,y-1,z-1) :      Icpc+Iccp-  Iccc;
00636     double Icpn = defined(x  ,y-1,z+1,X,Y,Z,mask) ? phi(x  ,y-1,z+1) :      Icpc+Iccn-  Iccc;
00637     double Icnp = defined(x  ,y+1,z-1,X,Y,Z,mask) ? phi(x  ,y+1,z-1) :      Icnc+Iccp-  Iccc;
00638     double Icnn = defined(x  ,y+1,z+1,X,Y,Z,mask) ? phi(x  ,y+1,z+1) :      Icnc+Iccn-  Iccc;
00639     //double Inpp = defined(x+1,y-1,z-1,X,Y,Z,mask) ? phi(x+1,y-1,z-1) : Incc+Icpc+Iccp-2*Iccc;
00640     double Inpc = defined(x+1,y-1,z  ,X,Y,Z,mask) ? phi(x+1,y-1,z  ) : Incc+Icpc     -  Iccc;
00641     //double Inpn = defined(x+1,y-1,z+1,X,Y,Z,mask) ? phi(x+1,y-1,z+1) : Incc+Icpc+Iccn-2*Iccc;
00642     double Incp = defined(x+1,y  ,z-1,X,Y,Z,mask) ? phi(x+1,y  ,z-1) : Incc+     Iccp-  Iccc;
00643     double Incn = defined(x+1,y  ,z+1,X,Y,Z,mask) ? phi(x+1,y  ,z+1) : Incc+     Iccn-  Iccc;
00644     //double Innp = defined(x+1,y+1,z-1,X,Y,Z,mask) ? phi(x+1,y+1,z-1) : Incc+Icnc+Iccp-2*Iccc;
00645     double Innc = defined(x+1,y+1,z  ,X,Y,Z,mask) ? phi(x+1,y+1,z  ) : Incc+Icnc     -  Iccc;
00646     //double Innn = defined(x+1,y+1,z+1,X,Y,Z,mask) ? phi(x+1,y+1,z+1) : Incc+Icnc+Iccn-2*Iccc;
00647 
00648     double dxx = Incc + Ipcc - 2 * Iccc;
00649     double dyy = Icnc + Icpc - 2 * Iccc;
00650     double dzz = Iccn + Iccp - 2 * Iccc;
00651 
00652     double dxy = (dx * dy < 0) ? 
00653         0.5 * (2 * Iccc + Ippc + Innc - Ipcc - Incc - Icpc - Icnc) :
00654         0.5 * (Ipcc + Incc + Icpc + Icnc - 2 * Iccc - Ipnc - Inpc);
00655 
00656     double dxz =  (dx * dz < 0) ? 
00657         0.5 * (2 * Iccc + Ipcp + Incn - Ipcc - Incc - Iccp - Iccn) :
00658         0.5 * (Ipcc + Incc + Iccp + Iccn - 2 * Iccc - Ipcn - Incp);
00659 
00660     double dyz = (dy * dz < 0) ?
00661         0.5 * (2 * Iccc + Icpp + Icnn - Icpc - Icnc - Iccp - Iccn) :
00662         0.5 * (Icpc + Icnc + Iccp + Iccn - 2 * Iccc - Icpn - Icnp);
00663 
00664     double norm = sqrt(norm2);
00665     
00666     return (dx * dx * (dyy + dzz) + 
00667             dy * dy * (dxx + dzz) +
00668             dz * dz * (dxx + dyy) - 
00669             2 * (dx * dy * dxy + 
00670                  dx * dz * dxz +
00671                  dy * dz * dyz)
00672             ) / (norm * norm2);
00673 }
00674 
00675 //===========================================================================
00676 void visualize_multisets_impl(vector<const LevelSetFunction* > images,
00677                               Image<double>& target,
00678                               const int** const rgb_color)
00679 //===========================================================================
00680 {
00681     const int num_images = images.size();
00682     assert(num_images > 0);
00683     assert(images[0]->dimz() == 1); // currently only implemented in 2D
00684     const int X = images[0]->dimx();
00685     const int Y = images[0]->dimy();
00686     target.resize(X, Y, 1, 3); // 3 color channels
00687 
00688     int blend[3]; 
00689     int num_covering = 0;
00690     for (int y = 0; y < Y; ++y) {
00691         for (int x = 0; x < X; ++x) {
00692             blend[0] = blend[1] = blend[2] = 0;
00693             num_covering = 0;
00694             for (int i = 0; i < num_images; ++i) {
00695                 if ((*images[i])(x, y) <= 0) {
00696                     // this function is in the overlap
00697                     blend[0] += rgb_color[i][0];
00698                     blend[1] += rgb_color[i][1];
00699                     blend[2] += rgb_color[i][2];
00700                     ++num_covering;
00701                 }
00702             }
00703             if (num_covering > 0) {
00704                 target(x, y, 0, 0) = blend[0] / num_covering;
00705                 target(x, y, 0, 1) = blend[1] / num_covering;
00706                 target(x, y, 0, 2) = blend[2] / num_covering;
00707             } else {
00708                 target(x, y, 0, 0) = rgb_color[num_images][0];
00709                 target(x, y, 0, 1) = rgb_color[num_images][1];
00710                 target(x, y, 0, 2) = rgb_color[num_images][2];
00711             }
00712         }
00713     }
00714 }
00715 
00716 //===========================================================================
00717 void godunov_phi_2D(double a_term, 
00718                     double phi_xl, double phi_xr,
00719                     double phi_yl, double phi_yr,
00720                     double& phi_x,
00721                     double& phi_y)
00722 //===========================================================================
00723 {
00724     // using Godunov to choose correct phi_x and phi_y 
00725     if (a_term * phi_xr > 0) {
00726         phi_x = (a_term * phi_xl > 0) ? phi_xl : 0;
00727     } else { // a_term * phi_xr < 0
00728         if (a_term * phi_xl > 0) {
00729             phi_x = (fabs(phi_xl) > fabs(phi_xr)) ? phi_xl : phi_xr;
00730         } else {
00731             phi_x = phi_xr;
00732         }
00733     }
00734     if (a_term * phi_yr > 0) {
00735         phi_y = (a_term * phi_yl > 0) ? phi_yl : 0;
00736     } else { // a_term * phi_yr < 0
00737         if (a_term * phi_yl > 0) {
00738             phi_y = (fabs(phi_yl) > fabs(phi_yr)) ? phi_yl : phi_yr;
00739         } else {
00740             phi_y = phi_yr;
00741         }
00742     }
00743 }
00744 
00745 //===========================================================================
00746 void godunov_phi_3D(double a_term, 
00747                     double phi_xl, double phi_xr,
00748                     double phi_yl, double phi_yr,
00749                     double phi_zl, double phi_zr,
00750                     double& phi_x,
00751                     double& phi_y,
00752                     double& phi_z)
00753 //===========================================================================
00754 {
00755     // using Godunov to choose correct phi_x, phi_y and phi_z
00756     if (a_term * phi_xr > 0) {
00757         phi_x = (a_term * phi_xl > 0) ? phi_xl : 0;
00758     } else { // a_term * phi_xr < 0
00759         if (a_term * phi_xl > 0) {
00760             phi_x = (fabs(phi_xl) > fabs(phi_xr)) ? phi_xl : phi_xr;
00761         } else {
00762             phi_x = phi_xr;
00763         }
00764     }
00765     if (a_term * phi_yr > 0) {
00766         phi_y = (a_term * phi_yl > 0) ? phi_yl : 0;
00767     } else { // a_term * phi_yr < 0
00768         if (a_term * phi_yl > 0) {
00769             phi_y = (fabs(phi_yl) > fabs(phi_yr)) ? phi_yl : phi_yr;
00770         } else {
00771             phi_y = phi_yr;
00772         }
00773     }
00774     if (a_term * phi_zr > 0) {
00775         phi_z = (a_term * phi_zl > 0) ? phi_zl : 0;
00776     } else { // a_term * phi_zr < 0
00777         if (a_term * phi_zl > 0) {
00778             phi_z = (fabs(phi_zl) > fabs(phi_zr)) ? phi_zl : phi_zr;
00779         } else {
00780             phi_z = phi_zr;
00781         }
00782     }
00783 }
00784 
00785 }; // end anonymous namespace 
00786 

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