/home/oan/prosjekt/gotools/segmentation/gpl_distro/lsseg_1.0_gpl/src/NormalDistributionForce.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: NormalDistributionForce.C                                           
00037 //                                                                           
00038 // Created: Fri Mar  3 10:56:16 2006                                         
00039 //                                                                           
00040 // Author: Odd A. Andersen <Odd.Andersen@sintef.no>
00041 //                                                                           
00042 // Revision: $Id: NormalDistributionForce.C,v 1.4 2006/11/25 20:08:27 oan Exp $
00043 //                                                                           
00044 // Description:
00047 //                                                                           
00048 //===========================================================================
00049 
00050 #include "NormalDistributionForce.h"
00051 
00052 namespace lsseg {
00053 
00054 //===========================================================================
00055 NormalDistributionForce::NormalDistributionForce(const Image<double>* img,
00056                                                  Mask* m,
00057                                                  bool multireg_mode)
00058 //===========================================================================
00059     : multi_region_mode_(multireg_mode)
00060 {
00061     init(img, m);
00062 }
00063 
00064 //===========================================================================
00065 void NormalDistributionForce::init(const Image<double>* img, const Mask* mask)
00066 //===========================================================================
00067 {
00068     // verification of contract
00069     assert(img);
00070     assert(!mask || mask->numChannels() == 1);
00071     assert(!mask || img->spatial_compatible(*mask));
00072 
00073     img_ = img;
00074     mask_ = mask;
00075     const int nchan = img->numChannels();
00076     mu_in_.resize(nchan);
00077     mu_out_.resize(nchan);
00078     inv_sigma_in_.resize(nchan);
00079     inv_sigma_out_.resize(nchan);
00080     precalc_log_.resize(nchan);
00081 }
00082 
00083 //===========================================================================
00084 void NormalDistributionForce::update(const LevelSetFunction& phi) 
00085 //===========================================================================
00086 {
00087     // verification of contract
00088     assert(phi.spatial_compatible(*img_));
00089     
00090     compute_averages(phi);
00091     compute_deviations(phi);
00092 }
00093 
00094 //===========================================================================
00095 double NormalDistributionForce::force2D(int x, int y) const
00096 //===========================================================================
00097 {
00098     return force(img_->indexOf(x, y));
00099 }
00100 
00101 //===========================================================================
00102 double NormalDistributionForce::force3D(int x, int y, int z) const
00103 //===========================================================================
00104 {
00105     return force(img_->indexOf(x, y, z));
00106 }
00107 
00108 //===========================================================================
00109 double NormalDistributionForce::force(size_t ix) const
00110 //===========================================================================
00111 {
00112     // force only defined inside mask
00113     assert(!mask_ || (*mask_)[ix]); 
00114 
00115     double res = 0;
00116     const int CNUM = img_->numChannels();
00117     const int CSIZE = img_->channelSize();
00118 
00119     if (multi_region_mode_) {
00120         for (int c = 0; c < CNUM; ++c) {
00121             const size_t c_offset = c * CSIZE;
00122             const double s1_inv = inv_sigma_in_[c];
00123             const double img_val = (*img_)[ix + c_offset];
00124             const double tmp = (img_val - mu_in_[c]) * s1_inv;
00125             res += precalc_log_[c] - 0.5 * tmp * tmp;
00126         }
00127     } else {
00128         for (int c = 0; c < CNUM; ++c) {
00129             const size_t c_offset = c * CSIZE;
00130             const double s1_inv = inv_sigma_in_[c];
00131             const double s2_inv = inv_sigma_out_[c];
00132             const double img_val = (*img_)[ix + c_offset];
00133             const double tmp1 = (img_val - mu_in_[c]) * s1_inv;
00134             const double tmp2 = (img_val - mu_out_[c]) * s2_inv;
00135             res += precalc_log_[c] + 0.5 * (tmp2 * tmp2 - tmp1 * tmp1);
00136         }
00137     }
00138     return res;
00139 }    
00140 
00141 //===========================================================================
00142 void NormalDistributionForce::force(LevelSetFunction& res, const Mask* m) const
00143 //===========================================================================
00144 {
00145     assert(!m || img_->spatial_compatible(*m));
00146     assert(img_->spatial_compatible(res));
00147     const size_t SIZE = res.size();
00148 
00149     // explicit checking of mask presence for optimization reasons
00150     if (m) {
00151         if (mask_) {
00152             for (size_t it = 0; it < SIZE; ++it) {
00153                 res[it] = ((*m)[it] && (*mask_)[it]) ? force(it) : 0;
00154             }
00155         } else {
00156             for (size_t it = 0; it < SIZE; ++it) {
00157                 res[it] = (*m)[it] ? force(it) : 0;
00158             }
00159         }
00160     } else {
00161         if (mask_) {
00162             for (size_t it = 0; it < SIZE; ++it) {
00163                 res[it] = (*mask_)[it] ? force(it) : 0;
00164             }
00165         } else {
00166             for (size_t it = 0; it < SIZE; ++it) {
00167                 res[it] = force(it);
00168             }
00169         }
00170     }
00171 }
00172 
00173 //===========================================================================
00174 void NormalDistributionForce::compute_averages(const LevelSetFunction& phi)
00175 //===========================================================================
00176 {
00177     assert(img_->spatial_compatible(phi));
00178     const size_t CSIZE = img_->channelSize();
00179     
00180     for (int c = 0; c < img_->numChannels(); ++c) {
00181         size_t num_in = 0; // count pixels inside region
00182         size_t num_out = 0; // count pixels outside region
00183         
00184         // compute statistics for each channel
00185         mu_in_[c] = mu_out_[c] = 0;
00186         const size_t c_offset = c * CSIZE;
00187         
00188         if (mask_) {
00189             for (size_t i = 0; i < CSIZE; ++i) {
00190                 if ((*mask_)[i]) {
00191                     const double img_val = (*img_)[i + c_offset];
00192                     if (phi[i] <= 0) {
00193                         ++num_in;
00194                         mu_in_[c] += img_val;
00195                     } else {
00196                         ++num_out;
00197                         mu_out_[c] += img_val;
00198                     }
00199                 }
00200             }
00201         } else {
00202             // no mask to worry about
00203             for (size_t i = 0; i < CSIZE; ++i) {
00204                 const double img_val = (*img_)[i + c_offset];
00205                 if (phi[i] <= 0) {
00206                     ++num_in;
00207                     mu_in_[c] +=img_val;
00208                 } else {
00209                     ++num_out;
00210                     mu_out_[c] += img_val;
00211                 }
00212             }
00213         }
00214         if (num_in > 0) {
00215             mu_in_[c] /= double(num_in);
00216         }
00217         if (num_out > 0) {
00218             mu_out_[c] /= double(num_out);
00219         }
00220     }
00221 }
00222 
00223 //===========================================================================
00224 void NormalDistributionForce::compute_deviations(const LevelSetFunction& phi)
00225 //===========================================================================
00226 {
00227     // this function supposes that the averages (mu_in_ and mu_out_)
00228     // have already been calculated for all channels
00229     const double PI = 3.1415926535897932384;
00230     const double log_inv_root_2pi = log(double(1)/sqrt(2 * PI));
00231 
00232     assert(img_->spatial_compatible(phi));
00233     const double EPS = 1.0e-2;
00234     const size_t CSIZE = img_->channelSize();
00235 
00236     for (int c = 0; c < img_->numChannels(); ++c) {
00237         size_t num_in = 0;
00238         size_t num_out = 0;
00239 
00240         const size_t c_offset = c * CSIZE;
00241 
00242         if (mask_) {
00243             for (size_t i = 0; i < CSIZE; ++i) {
00244                 if((*mask_)[i]) {
00245                     const double img_val = (*img_)[i + c_offset];
00246                     if (phi[i] <= double(0)) {
00247                         ++num_in;
00248                         const double diff = mu_in_[c] - img_val;
00249                         inv_sigma_in_[c] += diff * diff;
00250                     } else {
00251                         ++num_out;
00252                         const double diff = mu_out_[c] - img_val;
00253                         inv_sigma_out_[c] += diff * diff;
00254                     }
00255                 }
00256             }
00257         } else {
00258             // no mask to worry about
00259             for (size_t i = 0; i < CSIZE; ++i) {
00260                 const double img_val = (*img_)[i + c_offset];
00261                 if (phi[i] <= double(0)) {
00262                     ++num_in;
00263                     const double diff = mu_in_[c] - img_val;
00264                     inv_sigma_in_[c] += diff * diff;
00265                 } else {
00266                     ++num_out;
00267                     const double diff = mu_out_[c] - img_val;
00268                     inv_sigma_out_[c] += diff * diff;
00269                 }
00270             }
00271         }
00272         if (num_in > 0) {
00273             inv_sigma_in_[c] /= double(num_in);
00274             inv_sigma_in_[c] = sqrt(inv_sigma_in_[c]);
00275             inv_sigma_in_[c] = double(1) / (inv_sigma_in_[c] > EPS ? inv_sigma_in_[c] : EPS);
00276         } else {
00277             inv_sigma_in_[c] = double(1) / EPS;
00278         }
00279         if (num_out > 0) {
00280             inv_sigma_out_[c] /= double(num_out);
00281             inv_sigma_out_[c] = sqrt(inv_sigma_out_[c]);
00282             inv_sigma_out_[c] = double(1) / (inv_sigma_out_[c] > EPS ? inv_sigma_out_[c] : EPS);
00283         } else {
00284             inv_sigma_out_[c] = double(1) / EPS;
00285         }
00286         precalc_log_[c] = multi_region_mode_ ?
00287             log(inv_sigma_in_[c]) + log_inv_root_2pi :
00288             log(inv_sigma_in_[c] / inv_sigma_out_[c]);
00289     }
00290 }
00291 
00292 
00293 }; // end namespace lsseg

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