/home/oan/prosjekt/gotools/segmentation/gpl_distro/lsseg_1.0_gpl/src/LIC.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: LIC.C                                                               
00037 //                                                                           
00038 // Created: Mon Apr 24 18:09:44 2006                                         
00039 //                                                                           
00040 // Author: Odd A. Andersen <Odd.Andersen@sintef.no>
00041 //                                                                           
00042 // Revision: $Id: LIC.C,v 1.11 2006/11/25 20:08:26 oan Exp $
00043 //                                                                           
00044 // Description:
00047 //                                                                           
00048 //===========================================================================
00049 
00050 #include <iostream> // debug
00051 #include <cmath>
00052 #include <limits>
00053 #include "errormacros.h"
00054 #include "LIC.h"
00055 
00056 #include "simplethreads.h" // test this
00057 
00058 const int NUM_PROC=4; // how many threads should run at the same time (>= nb. of processors)
00059 
00060 using namespace lsseg;
00061 using namespace std;
00062 //using namespace Go;
00063 
00064 namespace { // anonymous namespace
00065 
00066 const double TAN_LIM_ANGLE = tan(0.05); // tan-function of 3 degrees, approx.
00067 const double SIN2_LIM_ANGLE = sin(0.05) * sin(0.05); // sin2 function of 3 degrees, approx.
00068 const double ROUNDOFF_TERM = 1.0e-5; // added to stepsize to ensure entry into neighbour cell
00069 const double INFINITE = std::numeric_limits<double>::max();
00070 
00071  double steplength(const double posx, 
00072                          const double posy, 
00073                          const double vecx,
00074                          const double vecy);
00075 
00076 
00077 inline double steplength(const double posx,
00078                          const double posy,
00079                          const double posz,
00080                          const double vecx,
00081                          const double vecy,
00082                          const double vecz);
00083 
00084 struct LIC_idata {
00085     int start; // refers to y or z coord, depending on 2D or 3D
00086     int end;   // idem
00087     const Image<double>* src;
00088     const Image<double>* vec;
00089     double* target_ptr;
00090     double (*kernel_func)(double);
00091     double L;
00092 };
00093 
00094 struct LIC_FS_idata {
00095     int start; // refers to y or z coord, depending on 2D or 3D 
00096     int end; // idem
00097     const Image<double>* src;
00098     const Image<double>* vec;
00099     double* target_ptr;
00100     double (*kernel_func)(double);
00101     double L;
00102     double dl;
00103 };
00104 
00105 void LIC_2D_subpart(const int job,
00106                     const int thread,
00107                     void * const idata,
00108                     void * const odata);
00109 
00110 void LIC_3D_subpart(const int job,
00111                     const int thread,
00112                     void * const idata,
00113                     void * const odata);
00114 
00115 void LIC_2D_FS_subpart(const int job,
00116                        const int thread,
00117                        void * const idata,
00118                        void * const odata);
00119 void LIC_3D_FS_subpart(const int job,
00120                        const int thread,
00121                        void * const idata,
00122                        void * const odata);
00123 
00124 }; // end anonymous namespace
00125 
00126 namespace lsseg {
00127 
00128 void LIC_2D_FS(const Image<double>& src,
00129                const Image<double>& vec,
00130                Image<double>& target,
00131                double (*kernel_func)(double),
00132                const double dl, // steplength
00133                const double L) // total length along which to integrate
00134 {
00135     ALWAYS_ERROR_IF(!src.spatial_compatible(vec), 
00136                     "source image and vector field size mismatch");
00137     ALWAYS_ERROR_IF(vec.numChannels() != 3, "given vector field was not 2D + magnitude");
00138     ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00139 
00140     // preparing indata for the threads
00141     const int Y = src.dimy();
00142     const int USED_PROC = Y < NUM_PROC ? Y : NUM_PROC;
00143     vector<LIC_FS_idata> job_idata(USED_PROC); 
00144     for (int i = 0; i < USED_PROC; ++i) {
00145         int y1 = (i * Y) / USED_PROC;
00146         int y2 = ((i+1) * Y) / USED_PROC;
00147         job_idata[i].start = y1;
00148         job_idata[i].end = y2;
00149 
00150         job_idata[i].target_ptr = &(target(0, y1, 0, 0));
00151         job_idata[i].src = &src;
00152         job_idata[i].vec = &vec;
00153         job_idata[i].kernel_func = kernel_func;
00154         job_idata[i].L = L;
00155         job_idata[i].dl = dl;
00156     }
00157     // carry out the work
00158     do_threaded_jobs(LIC_2D_FS_subpart, &job_idata[0], USED_PROC, USED_PROC, false, NULL);  
00159 }
00160 
00161 void LIC_3D_FS(const Image<double>& src,
00162                const Image<double>& vec,
00163                Image<double>& target,
00164                double (*kernel_func)(double),
00165                const double dl, // steplength
00166                const double L) // total length along which to integrate
00167 {
00168     ALWAYS_ERROR_IF(!src.spatial_compatible(vec), 
00169                     "source image and vector field size mismatch");
00170     ALWAYS_ERROR_IF(vec.numChannels() != 4, "given vector field was not 3D + magnitude");
00171     ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00172 
00173     // preparing indata for the threads
00174     const int Z = src.dimz();
00175     const int USED_PROC = Z < NUM_PROC ? Z : NUM_PROC;
00176     vector<LIC_FS_idata> job_idata(USED_PROC);
00177     for (int i = 0; i < USED_PROC; ++i) {
00178         int z1 = (i * Z) / USED_PROC;;
00179         int z2 = ((i+1) * Z) / USED_PROC;
00180         job_idata[i].start = z1;
00181         job_idata[i].end = z2;
00182 
00183         job_idata[i].target_ptr = &(target(0, 0, z1, 0));
00184         job_idata[i].src = &src;
00185         job_idata[i].vec = &vec;
00186         job_idata[i].kernel_func = kernel_func;
00187         job_idata[i].L = L;
00188         job_idata[i].dl = dl;
00189     }
00190     // carry out the work
00191     do_threaded_jobs(LIC_3D_FS_subpart, &job_idata[0], USED_PROC, USED_PROC, false, NULL);
00192 }
00193 
00194 
00195 
00196 
00197 void LIC_3D(const Image<double>& src,
00198             const Image<double>& vec,
00199             Image<double>& target,
00200             double (*kernel_func)(double),
00201             const double L)
00202 {
00203     ALWAYS_ERROR_IF(!src.spatial_compatible(vec), 
00204                     "source image and vector field size mismatch");
00205     ALWAYS_ERROR_IF(vec.numChannels() != 3, "given vector field was not 3D");
00206     ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00207 
00208     // preparing indata for the threads
00209     const int Z = src.dimz();
00210     const int USED_PROC = Z < NUM_PROC ? Z : NUM_PROC;
00211     vector<LIC_idata> job_idata(USED_PROC);
00212     for (int i = 0; i < USED_PROC; ++i) {
00213         int z1 = (i * Z) / USED_PROC;;
00214         int z2 = ((i+1) * Z) / USED_PROC;
00215         job_idata[i].start = z1;
00216         job_idata[i].end = z2;
00217 
00218         job_idata[i].target_ptr = &(target(0, 0, z1, 0));
00219         job_idata[i].src = &src;
00220         job_idata[i].vec = &vec;
00221         job_idata[i].kernel_func = kernel_func;
00222         job_idata[i].L = L;
00223     }
00224     // carry out the work
00225     do_threaded_jobs(LIC_3D_subpart, &job_idata[0], USED_PROC, USED_PROC, false, NULL);
00226 }
00227 
00228 
00229 void LIC_2D(const Image<double>& src,
00230             const Image<double>& vec,
00231             Image<double>& target,
00232             double (*kernel_func)(double),
00233             const double L)
00234 {
00235     ALWAYS_ERROR_IF(!src.spatial_compatible(vec), 
00236                     "source image and vector field size mismatch");
00237     ALWAYS_ERROR_IF(vec.numChannels() != 2, "given vector field was not 2D");
00238     ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00239 
00240     // preparing indata for the threads
00241     const int Y = src.dimy();
00242     const int USED_PROC = Y < NUM_PROC ? Y : NUM_PROC;
00243     vector<LIC_idata> job_idata(USED_PROC); 
00244     for (int i = 0; i < USED_PROC; ++i) {
00245         int y1 = (i * Y) / USED_PROC;
00246         int y2 = ((i+1) * Y) / USED_PROC;
00247         job_idata[i].start = y1;
00248         job_idata[i].end = y2;
00249 
00250         job_idata[i].target_ptr = &(target(0, y1, 0, 0));
00251         job_idata[i].src = &src;
00252         job_idata[i].vec = &vec;
00253         job_idata[i].kernel_func = kernel_func;
00254         job_idata[i].L = L;
00255     }
00256     // carry out the work
00257     do_threaded_jobs(LIC_2D_subpart, &job_idata[0], USED_PROC, USED_PROC, false, NULL);  
00258 }
00259 
00260 
00261 // void LIC_2D(const Image<double>& src,
00262 //          const Image<double>& vec,
00263 //          Image<double>& target,
00264 //          double (*kernel_func)(double),
00265 //          const double L)
00266 // {
00267 //     ALWAYS_ERROR_IF(!src.spatial_compatible(vec), 
00268 //                  "source image and vector field size mismatch");
00269 //     ALWAYS_ERROR_IF(vec.numChannels() != 2, "given vector field was not 2D");
00270 //     ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00271 //     //target.resize(src);
00272 //     //target = 0;
00273 //     const int X = src.dimx();
00274 //     const int Y = src.dimy();
00275 //     const int C = src.numChannels();
00276 //     std::vector<double> px_val(C);
00277 //     double posx, posy; // position of current point on the traced line
00278 //     for (int y = 0; y < Y; ++y) {
00279 //      for (int x = 0; x < X; ++x) {
00280 //          fill(px_val.begin(), px_val.end(), 0);
00281 //          double accum = 0;
00282 //          int sign = 1;
00283 //          for (int pass = 0; pass != 2; ++pass) { // first forwards, then backwards
00284                 
00285 //              double posx = x + 0.5; // position of current point on the traced line
00286 //              double posy = y + 0.5; //                  - " -
00287 //              double l = 0;
00288 //              bool end_reached = false;
00289 //              int prev_x = int(posx);
00290 //              int prev_y = int(posy);
00291 //              do {
00292 //                  const int iposx = int(posx); // integer position
00293 //                  const int iposy = int(posy); // integer position
00294 //                  const double w_x = sign * vec(iposx, iposy, 0, 0); // roundoff to integer
00295 //                  const double w_y = sign * vec(iposx, iposy, 0, 1); // roundoff to integer
00296 //                  double dl = steplength(posx, posy, w_x, w_y); 
00297 //                  if (dl < 0) break; // degeneracy detected
00298 //                  l += dl; // l measures parametric length traversed
00299 //                  if (l > L) {
00300 //                      dl = (l - L);
00301 //                      l = L;
00302 //                      // this will be the last cycle of updates.
00303 //                      end_reached = true;
00304 //                  }
00305                     
00306 //                  // contribution to integral
00307 //                  // integrate over param.
00308 //                  const double h = kernel_func(l) * dl;
00309 //                  for (int c = 0; c < C; ++c) {
00310 //                      px_val[c] += h * src(iposx, iposy, 0, c); 
00311 //                  }
00312 //                  accum += h;
00313                     
00314 //                  // updating position
00315 //                  posx += dl * w_x;
00316 //                  posy += dl * w_y;
00317 //                  if (posx < 0 || posx > X) break; // outside image domain
00318 //                  if (posy < 0 || posy > Y) break; // outside image domain
00319 //                  if (int(posx) == prev_x && int(posy) == prev_y) break; // degen. point in field
00320 //                  prev_x = iposx; // NB: iposx and iposy have not yet been updated
00321 //                  prev_y = iposy; // from last iteration, so we here get the previous value
00322 //              } while (!end_reached);
00323 //              sign *= -1;
00324 //          }
00325 //          if (accum > 0) {
00326 //              for (int c = 0; c < C; ++c) 
00327 //                  target(x, y, 0, c) += px_val[c] / accum;
00328 //          } else {
00329 //              for (int c = 0; c < C; ++c) 
00330 //                  target(x, y, 0, c) += src(x, y, 0, c);
00331 //          }
00332 //      }
00333 //     }
00334 // }
00335 
00336 // void LIC_3D(const Image<double>& src,
00337 //          const Image<double>& vec,
00338 //          Image<double>& target,
00339 //          double (*kernel_func)(double),
00340 //          const double L)
00341 // {
00342 //     ALWAYS_ERROR_IF(!src.spatial_compatible(vec), 
00343 //                  "source image and vector field size mismatch");
00344 //     ALWAYS_ERROR_IF(vec.numChannels() != 3, "given vector field was not 2D");
00345 //     ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00346 
00347 //     const int X = src.dimx();
00348 //     const int Y = src.dimy();
00349 //     const int Z = src.dimz();
00350 //     const int C = src.numChannels();
00351 //     std::vector<double> px_val(C);
00352 //     double posx, posy, posz; // position of current point on the traced line
00353 //     for (int z = 0; z < Z; ++z) {
00354 //      for (int y = 0; y < Y; ++y) {
00355 //          for (int x = 0; x < X; ++x) {
00356 //              fill(px_val.begin(), px_val.end(), 0);
00357 //              double accum = 0;
00358 //              int sign = 1;
00359 //              for (int pass = 0; pass != 2; ++pass) { // first forwards, then backwards
00360                     
00361 //                  double posx = x + 0.5; // position of current point on the traced line
00362 //                  double posy = y + 0.5; //                  - " -
00363 //                  double posz = z + 0.5; //                  - " -
00364 //                  double l = 0;
00365 //                  bool end_reached = false;
00366 //                  int prev_x = int(posx);
00367 //                  int prev_y = int(posy);
00368 //                  int prev_z = int(posz);
00369 //                  do {
00370 //                      const int iposx = int(posx); // integer position
00371 //                      const int iposy = int(posy); // integer position
00372 //                      const int iposz = int(posz);
00373 //                      const double w_x = sign * vec(iposx, iposy, iposz, 0); // roundoff to int
00374 //                      const double w_y = sign * vec(iposx, iposy, iposz, 1); // roundoff to int
00375 //                      const double w_z = sign * vec(iposx, iposy, iposz, 2); // roundoff to int
00376 //                      double dl = steplength(posx, posy, posz, w_x, w_y, w_z); 
00377 //                      if (dl < 0) break; // degeneracy detected
00378 //                      l += dl; // l measures parametric length traversed
00379 //                      if (l > L) {
00380 //                          dl = (l - L);
00381 //                          l = L;
00382 //                          // this will be the last cycle of updates.
00383 //                          end_reached = true;
00384 //                      }
00385                     
00386 //                      // contribution to integral
00387 //                      // integrate over param.
00388 //                      const double h = kernel_func(l) * dl;
00389 //                      for (int c = 0; c < C; ++c) {
00390 //                          px_val[c] += h * src(iposx, iposy, iposz, c); 
00391 //                      }
00392 //                      accum += h;
00393                         
00394 //                      // updating position
00395 //                      posx += dl * w_x;
00396 //                      posy += dl * w_y;
00397 //                      posz += dl * w_z;
00398 //                      if (posx < 0 || posx > X) break; // outside image domain
00399 //                      if (posy < 0 || posy > Y) break; // outside image domain
00400 //                      if (posz < 0 || posz > Z) break; // outside image domain
00401 //                      if (int(posx) == prev_x && 
00402 //                          int(posy) == prev_y &&
00403 //                          int(posz) == prev_z) break; // degen. point in field
00404 //                  prev_x = iposx; // NB: iposx and iposy have not yet been updated
00405 //                  prev_y = iposy; // from last iteration, so we here get the previous value
00406 //                  prev_z = iposz; //
00407 //                  } while (!end_reached);
00408 //                  sign *= -1;
00409 //              }
00410 //              if (accum > 0) {
00411 //                  for (int c = 0; c < C; ++c) 
00412 //                      target(x, y, z, c) += px_val[c] / accum;
00413 //              } else {
00414 //                  for (int c = 0; c < C; ++c) 
00415 //                      target(x, y, z, c) += src(x, y, z, c);
00416 //              }
00417 //          }
00418 //      }
00419 //     }
00420 // }
00421 
00422 };// End namespace lsseg
00423 
00424 
00425 namespace { // anonymous namespace
00426 
00427 void LIC_3D_subpart(const int job,
00428                     const int thread,
00429                     void * const idata,
00430                     void * const odata)
00431 {
00432     // grabbing parameters
00433     LIC_idata& input = ((LIC_idata*)idata)[job];
00434 
00435     const int zstart = input.start;
00436     const int zend = input.end;
00437     const Image<double>& src = *(input.src);
00438     const Image<double>& vec = *(input.vec);
00439     double* t_ptr = input.target_ptr;
00440     const double L = input.L;
00441     double (*kernel_func)(double) = input.kernel_func;
00442 
00443     std::cout <<"Now started job " << job << " in thread " << thread << endl;
00444 
00445     const int X = src.dimx();
00446     const int Y = src.dimy();
00447     const int Z = src.dimz();
00448     const int C = src.numChannels();
00449     const unsigned long int channelsize = src.channelSize();
00450     std::vector<double> px_val(C);
00451     for (int z = zstart; z != zend; ++z) {
00452         for (int y = 0; y < Y; ++y) {
00453             for (int x = 0; x < X; ++x) {
00454                 fill(px_val.begin(), px_val.end(), 0);
00455                 double accum = 0;
00456                 int sign = 1;
00457                 for (int pass = 0; pass != 2; ++pass) { // first forwards, then backwards
00458                     
00459                     double posx = x + 0.5; // position of current point on the traced line
00460                     double posy = y + 0.5; //                  - " -
00461                     double posz = z + 0.5; //                  - " -
00462                     double l = 0;
00463                     bool end_reached = false;
00464                     int prev_x = int(posx);
00465                     int prev_y = int(posy);
00466                     int prev_z = int(posz);
00467                     do {
00468                         const int iposx = int(posx); // integer position
00469                         const int iposy = int(posy); // integer position
00470                         const int iposz = int(posz);
00471                         const double w_x = sign * vec(iposx, iposy, iposz, 0); // roundoff to int
00472                         const double w_y = sign * vec(iposx, iposy, iposz, 1); // roundoff to int
00473                         const double w_z = sign * vec(iposx, iposy, iposz, 2); // roundoff to int
00474                         double dl = steplength(posx, posy, posz, w_x, w_y, w_z); 
00475                         if (dl < 0) break; // degeneracy detected
00476                         l += dl; // l measures parametric length traversed
00477                         if (l > L) {
00478                             dl = (l - L);
00479                             l = L;
00480                             // this will be the last cycle of updates.
00481                             end_reached = true;
00482                         }
00483                     
00484                         // contribution to integral
00485                         // integrate over param.
00486                         const double h = kernel_func(l) * dl;
00487                         for (int c = 0; c < C; ++c) {
00488                             px_val[c] += h * src(iposx, iposy, iposz, c); 
00489                         }
00490                         accum += h;
00491                         
00492                         // updating position
00493                         posx += dl * w_x;
00494                         posy += dl * w_y;
00495                         posz += dl * w_z;
00496                         if (posx < 0 || posx > X) break; // outside image domain
00497                         if (posy < 0 || posy > Y) break; // outside image domain
00498                         if (posz < 0 || posz > Z) break; // outside image domain
00499                         if (int(posx) == prev_x && 
00500                             int(posy) == prev_y &&
00501                             int(posz) == prev_z) break; // degen. point in field
00502                     prev_x = iposx; // NB: iposx and iposy have not yet been updated
00503                     prev_y = iposy; // from last iteration, so we here get the previous value
00504                     prev_z = iposz; //
00505                     } while (!end_reached);
00506                     sign *= -1;
00507                 }
00508                 if (accum > 0) {
00509                     for (int c = 0; c < C; ++c) 
00510                         *(t_ptr + c * channelsize) += px_val[c] / accum;
00511                 } else {
00512                     for (int c = 0; c < C; ++c) 
00513                         *(t_ptr + c * channelsize) += src(x, y, z, c);
00514                 }
00515                 ++t_ptr;
00516             }
00517         }
00518     }
00519 }
00520 
00521 void LIC_2D_FS_subpart(const int job,
00522                        const int thread,
00523                        void * const idata,
00524                        void * const odata)
00525 {
00526     // grabbing parameters
00527     LIC_FS_idata& input = ((LIC_FS_idata*)idata)[job];
00528     const int ystart = input.start;
00529     const int yend = input.end;
00530     const Image<double>& src = *(input.src);
00531     const Image<double>& vec = *(input.vec);
00532     double* t_ptr = input.target_ptr;
00533     const double L = input.L;
00534     const double dl = input.dl;
00535     double (*kernel_func)(double) = input.kernel_func;
00536 
00537     std::cout << "Now started job " << job << " in thread: " << thread << endl;
00538     
00539     const int X = src.dimx();
00540     const int Y = src.dimy();
00541     const int C = src.numChannels();
00542     const unsigned long int channelsize = src.channelSize();
00543     std::vector<double> px_val(C);
00544     for (int y = ystart; y != yend; ++y) {
00545         for (int x = 0; x < X; ++x) {
00546             fill(px_val.begin(), px_val.end(), 0);
00547             double accum = 0;
00548             for (int pass = 0; pass != 2; ++pass) { // first time forwards, second time backwards
00549                 double posx = x + 0.5; // position of current point on the traced line
00550                 double posy = y + 0.5; //                 - " -
00551                 //double l = 0;
00552                 //bool end_reached = false;
00553                 double prev_wx = vec(int(posx), int(posy), 0, 0);
00554                 double prev_wy = vec(int(posx), int(posy), 0, 1);
00555                 if (pass != 0) {
00556                     prev_wx *= -1;
00557                     prev_wy *= -1;
00558                 }
00559                 double magnitude = vec(int(posx), int(posy), 0, 2);
00560                 const double traverse_length = L * magnitude;
00561                 for (double l = 0; l < traverse_length; l+=dl) {
00562                     const int iposx = int(posx);
00563                     const int iposy = int(posy);
00564                     double wx = vec(iposx, iposy, 0, 0);
00565                     double wy = vec(iposx, iposy, 0, 1);
00566                     if (wx * prev_wx + wy * prev_wy < 0) {
00567                         wx *= -1;
00568                         wy *= -1;
00569                     }
00570                     // constribution to integral
00571                     const double h= kernel_func(l) * dl;
00572                     for (int c = 0; c < C; ++c) {
00573                         px_val[c] += h * src(iposx, iposy, 0, c);
00574                     }
00575                     accum += h;
00576                     
00577                     // updating position
00578                     posx += dl * wx;
00579                     posy += dl * wy;
00580                     if (posx < 0 || posx >= X) break; // outside image domain
00581                     if (posy < 0 || posy >= Y) break; // outside image domain
00582                     prev_wx = wx;
00583                     prev_wy = wy;
00584                 }
00585             }
00586             if (accum > 0) {
00587                 for (int c = 0; c < C; ++c) {
00588                     *(t_ptr + c * channelsize) += px_val[c] / accum;
00589                 }
00590             } else {
00591                 for (int c = 0; c < C; ++c) {
00592                     *(t_ptr + c * channelsize) = src(x, y, 0, c);
00593                 }
00594             }
00595             ++t_ptr;
00596         }
00597     }
00598 }
00599 
00600 void LIC_3D_FS_subpart(const int job,
00601                        const int thread,
00602                        void * const idata,
00603                        void * const odata)
00604 {
00605     // grabbing parameters
00606     LIC_FS_idata& input = ((LIC_FS_idata*)idata)[job];
00607     const int zstart = input.start;
00608     const int zend = input.end;
00609     const Image<double>& src = *(input.src);
00610     const Image<double>& vec = *(input.vec);
00611     double* t_ptr = input.target_ptr;
00612     const double L = input.L;
00613     const double dl = input.dl;
00614     double (*kernel_func)(double) = input.kernel_func;
00615 
00616     std::cout << "Now started job " << job << " in thread: " << thread << endl;
00617     
00618     const int X = src.dimx();
00619     const int Y = src.dimy();
00620     const int Z = src.dimz();
00621     const int C = src.numChannels();
00622     const unsigned long int channelsize = src.channelSize();
00623     std::vector<double> px_val(C);
00624     for (int z = zstart; z != zend; ++z) {
00625         for (int y = 0; y != Y; ++y) {
00626             for (int x = 0; x < X; ++x) {
00627                 fill(px_val.begin(), px_val.end(), 0);
00628                 double accum = 0;
00629                 for (int pass = 0; pass != 2; ++pass) { // first time forwards, second time backwards
00630                     double posx = x + 0.5; // position of current point on the traced line
00631                     double posy = y + 0.5; //                 - " -
00632                     double posz = z + 0.5; //                 - " -
00633                     //double l = 0;
00634                     //bool end_reached = false;
00635                     double prev_wx = vec(int(posx), int(posy), int(posz), 0);
00636                     double prev_wy = vec(int(posx), int(posy), int(posz), 1);
00637                     double prev_wz = vec(int(posx), int(posy), int(posz), 2);
00638                     if (pass != 0) {
00639                         prev_wx *= -1;
00640                         prev_wy *= -1;
00641                         prev_wz *= -1;
00642                     }
00643                     double magnitude = vec(int(posx), int(posy), int(posz), 3); 
00644                     const double traverse_length = L * magnitude;
00645                     for (double l = 0; l < traverse_length; l+=dl) {
00646                         const int iposx = int(posx);
00647                         const int iposy = int(posy);
00648                         const int iposz = int(posz);
00649                         double wx = vec(iposx, iposy, iposz, 0);
00650                         double wy = vec(iposx, iposy, iposz, 1);
00651                         double wz = vec(iposx, iposy, iposz, 2);
00652                         assert(wx >= -1 && wx <= 1);// @@
00653                         assert(wy >= -1 && wy <= 1);// @@ remove for optimizing!
00654                         assert(wz >= -1 && wz <= 1);// @@
00655                         if (wx * prev_wx + wy * prev_wy + wz * prev_wz < 0) {
00656                             wx *= -1;
00657                             wy *= -1;
00658                             wz *= -1;
00659                         }
00660                         // constribution to integral
00661                         const double h= kernel_func(l) * dl;
00662                         for (int c = 0; c < C; ++c) {
00663                             px_val[c] += h * src(iposx, iposy, iposz, c);
00664                         }
00665                         accum += h;
00666                     
00667                         // updating position
00668                         posx += dl * wx;
00669                         posy += dl * wy;
00670                         posz += dl * wz;
00671                         if (posx < 0 || posx >= X) break; // outside image domain
00672                         if (posy < 0 || posy >= Y) break; // outside image domain
00673                         if (posz < 0 || posz >= Z) break; // outside image domain
00674                         prev_wx = wx;
00675                         prev_wy = wy;
00676                         prev_wz = wz;
00677                     }
00678                 }
00679                 if (accum > 0) {
00680                     for (int c = 0; c < C; ++c) {
00681                         *(t_ptr + c * channelsize) += px_val[c] / accum;
00682                     }
00683                 } else {
00684                     for (int c = 0; c < C; ++c) {
00685                         *(t_ptr + c * channelsize) = src(x, y, z, c);
00686                     }
00687                 }
00688                 ++t_ptr;
00689             }
00690         }
00691     }
00692 }
00693 
00694 
00695 void LIC_2D_subpart(const int job, const int thread,  void * const idata,  void * const odata)
00696 {
00697     // grabbing parameters
00698     LIC_idata& input = ((LIC_idata*)idata)[job];
00699 
00700     const int ystart = input.start;
00701     const int yend = input.end;
00702     const Image<double>& src = *(input.src);
00703     const Image<double>& vec = *(input.vec);
00704     double* t_ptr = input.target_ptr;
00705     const double L = input.L;
00706     double (*kernel_func)(double) = input.kernel_func;
00707 
00708     std::cout << "Now started job " << job << " in thread " << thread << endl;
00709 
00710     const int X = src.dimx();
00711     const int Y = src.dimy();
00712     const int C = src.numChannels();
00713     const unsigned long int channelsize = src.channelSize();
00714     std::vector<double> px_val(C);
00715     for (int y = ystart; y != yend; ++y) {
00716         for (int x = 0; x < X; ++x) {
00717             fill(px_val.begin(), px_val.end(), 0);
00718             double accum = 0;
00719             int sign = 1;
00720             for (int pass = 0; pass != 2; ++pass) {
00721                 double posx = x + 0.5; // position of current point on the traced line
00722                 double posy = y + 0.5; //                  - " -
00723                 double l = 0;
00724                 bool end_reached = false;
00725                 int prev_x = int(posx);
00726                 int prev_y = int(posy);
00727                 do {
00728                     const int iposx = int(posx); // integer position
00729                     const int iposy = int(posy); // integer position
00730                     const double w_x = sign * vec(iposx, iposy, 0, 0); // roundoff to integer
00731                     const double w_y = sign * vec(iposx, iposy, 0, 1); // roundoff to integer
00732                     double dl = steplength(posx, posy, w_x, w_y); 
00733                     if (dl < 0) break; // degeneracy detected
00734                     l += dl; // l measures parametric length traversed
00735                     if (l > L) {
00736                         dl = (l - L);
00737                         l = L;
00738                         // this will be the last cycle of updates.
00739                         end_reached = true;
00740                     }
00741                     
00742                     // contribution to integral
00743                     // integrate over param.
00744                     const double h = kernel_func(l) * dl;
00745                     for (int c = 0; c < C; ++c) {
00746                         px_val[c] += h * src(iposx, iposy, 0, c); 
00747                     }
00748                     accum += h;
00749                     
00750                     // updating position
00751                     posx += dl * w_x;
00752                     posy += dl * w_y;
00753                     if (posx < 0 || posx > X) break; // outside image domain
00754                     if (posy < 0 || posy > Y) break; // outside image domain
00755                     if (int(posx) == prev_x && int(posy) == prev_y) break; // degen. point in field
00756                     prev_x = iposx; // NB: iposx and iposy have not yet been updated
00757                     prev_y = iposy; // from last iteration, so we here get the previous value
00758                 } while (!end_reached);
00759                 sign *= -1;
00760             }
00761             if (accum > 0) {
00762                 for (int c = 0; c < C; ++c) {
00763                     //cout << px_val[c] << " " << accum << endl;
00764                     *(t_ptr + c * channelsize) += px_val[c] / accum;
00765                 }
00766             } else {
00767                 for (int c = 0; c < C; ++c) 
00768                     *(t_ptr + c * channelsize) = src(x, y, 0, c);
00769             }
00770             ++t_ptr;
00771         }
00772     }
00773 }
00774 
00775 // negative return value indicates degenerated point
00776 double steplength(const double posx, 
00777                          const double posy,
00778                          const double vecx,
00779                          const double vecy)
00780 {
00781     const double EPS = 1.0e-10;
00782     if (fabs(vecx) < EPS && fabs(vecy) < EPS) {
00783         // quasi-zero vector.  This cell will be considered a degenerated point in
00784         // the vector field
00785         return -1; // 
00786     }
00787     const double rem_x = int(posx) - posx;
00788     const double rem_y = int(posy) - posy;
00789     
00790     // vecx must be negative, angle 
00791     const double x_limit = TAN_LIM_ANGLE * fabs(vecy);
00792     const double y_limit = TAN_LIM_ANGLE * fabs(vecx);
00793 
00794     double sx_left, sx_right, sy_left, sy_right;
00795     if (vecx < -x_limit) {
00796         sx_left = rem_x / vecx;
00797         sx_right = INFINITE;
00798     } else if (vecx > x_limit) {
00799         sx_left = INFINITE;
00800         sx_right = (rem_x+1)/vecx;
00801     } else {
00802         sx_left = sx_right = INFINITE;
00803     }
00804     if (vecy < -y_limit) {
00805         sy_left = rem_y / vecy;
00806         sy_right = INFINITE;
00807     } else if (vecy > y_limit) {
00808         sy_left = INFINITE;
00809         sy_right = (rem_y+1)/vecy;
00810     } else {
00811         sy_left = sy_right = INFINITE;
00812     }
00813 
00814     const double min_x = (sx_left < sx_right) ? sx_left : sx_right;
00815     const double min_y = (sy_left < sy_right) ? sy_left : sy_right;
00816     assert(min_x >=0);
00817     assert(min_y >=0);
00818 
00819     const double res = min_x < min_y ? min_x : min_y;
00820     if (res == INFINITE) {
00821         // problem, consider this point a degeneracy
00822         return -1;
00823     }
00824     return res + ROUNDOFF_TERM;
00825 }
00826 
00827 inline double steplength(const double posx, 
00828                          const double posy,
00829                          const double posz,
00830                          const double vecx,
00831                          const double vecy,
00832                          const double vecz)
00833 {
00834     const double EPS = 1.0e-10;
00835     if ((fabs(vecx) < EPS) && (fabs(vecy) < EPS) && (fabs(vecz) < EPS)) {
00836         // quasi-zero vector.  This cell will be considered a degenerated point in
00837         // the vector field
00838         return -1; // 
00839     }
00840     const double rem_x = int(posx) - posx;
00841     const double rem_y = int(posy) - posy;
00842     const double rem_z = int(posz) - posz;
00843     
00844     const double vecx2 = vecx*vecx;
00845     const double vecy2 = vecy*vecy;
00846     const double vecz2 = vecz*vecz;
00847     const double vnorm2 = vecx2 + vecy2 + vecz2;
00848     const double limit2 = vnorm2 * SIN2_LIM_ANGLE;
00849 
00850     double sx_left, sx_right, sy_left, sy_right, sz_left, sz_right;
00851     sx_left = sx_right = sy_left = sy_right = sz_left = sz_right = INFINITE;
00852     if (vecx2 > limit2) {
00853         if (vecx < 0) {
00854             sx_left = rem_x / vecx;
00855         } else {
00856             sx_right = (rem_x + 1)/vecx;
00857         }
00858     } 
00859     if (vecy2 > limit2) {
00860         if (vecy < 0) {
00861             sy_left = rem_y / vecy;
00862         } else {
00863             sy_right = (rem_y + 1) / vecy;
00864         }
00865     }
00866     if (vecz2 > limit2) {
00867         if (vecz < 0) {
00868             sz_left = rem_z / vecz;
00869         } else {
00870             sz_right = (rem_z + 1) / vecz;
00871         }
00872     }
00873     const double min_x = (sx_left < sx_right) ? sx_left : sx_right;
00874     const double min_y = (sy_left < sy_right) ? sy_left : sy_right;
00875     const double min_z = (sz_left < sz_right) ? sz_left : sz_right;
00876     assert(min_x >=0);
00877     assert(min_y >=0);
00878     assert(min_z >=0);
00879 
00880     double res = min_x < min_y ? min_x : min_y;
00881     res = (min_z < res) ? min_z : res;
00882     if (res == INFINITE) {
00883         // problem, consider this point a degeneracy
00884         return -1;
00885     }
00886     return res + ROUNDOFF_TERM;
00887 }
00888 
00889 }; // end anonymous namespace

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