greedy.hxx

00001 // Copyright (C) 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef OLENA_SNAKES_GREEDY_HXX
00029 # define OLENA_SNAKES_GREEDY_HXX
00030 
00031 namespace oln {
00032 
00033   namespace snakes {
00034 
00035 
00036     template <int N, class I, template<typename> class external_energy>
00037     greedy<N, I, external_energy>::greedy(ntg::float_s alpha,
00038                                           ntg::float_s beta,
00039                                           ntg::float_s gamma,
00040                                           ntg::float_s khi) :
00041       continuity_e(&average_dist),
00042       curvature_e(curvature_energy<I>::cookie()),
00043       image_e(image_energy<I>::cookie()),
00044       external_e(external_energy<I>::cookie()),
00045       alpha(alpha), beta(beta), gamma(gamma), khi(khi)
00046     {
00047     }
00048 
00049 
00050     template <int N, class I, template<typename> class external_energy>
00051     int
00052     greedy<N, I, external_energy>::
00053     update_snake(const I& gradient, snake<greedy<N, I, external_energy> >& s)
00054     {
00057       average_dist = compute_average_dist(s.s);
00058       return update_segment(gradient, s.s);
00059     }
00060 
00061     template <int N, class I, template<typename> class external_energy>
00062     void
00063     greedy<N, I, external_energy>::
00064     converge(const I& gradient, snake<greedy<N, I, external_energy> >& s)
00065     {
00066       // FIXME: think of a real stop condition.
00067       unsigned i = 0;
00068       while (threshold < update_segment(gradient, s.s))
00069         {
00070           average_dist = compute_average_dist(s.s);
00071           std::cout << i << ' ' << s.s << std::endl;
00072           ++i;
00073         };
00074     }
00075 
00076     template <int N, class I, template<typename> class external_energy>
00077     int
00078     greedy<N, I, external_energy>::update_segment(const I& gradient,
00079                                                   segment<I>& s)
00080     {
00081       int nb_updates = 0;
00082       typename segment<I>::iter_type p = s.begin();
00083       typename segment<I>::iter_type c = s.begin();
00084       typename segment<I>::iter_type n = s.begin();
00085 
00086       ++n;
00087       nb_updates += update_node(gradient, s.prev_node(), *c, *n) ? 1 : 0;
00088       for (++c, ++n; n != s.end(); ++p, ++c, ++n)
00089         nb_updates += update_node(gradient, *p, *c, *n) ? 1 : 0;
00090       nb_updates += update_node(gradient, *p, *c, s.next_node()) ? 1 : 0;
00091       return nb_updates;
00092     }
00093 
00094     template <int N, class I, template<typename> class external_energy>
00095     bool
00096     greedy<N, I, external_energy>::update_node(const I&         gradient,
00097                                                const node<I>&   prev,
00098                                                node<I>&         current,
00099                                                const node<I>&   next)
00101     {
00102       store_type                energy;
00103       ntg::float_s              minimum = ntg_sup_val(ntg::float_s);
00104       dpoint2d                  minimum_location;
00105 
00106       energy = compute_and_normalize_energy<continuity_energy<I> >
00107         (gradient, prev, current, next, continuity_e) * alpha;
00108       energy += compute_and_normalize_energy<curvature_energy<I> >
00109         (gradient, prev, current, next, curvature_e) * beta;
00110       energy += compute_and_normalize_energy<image_energy<I> >
00111         (gradient, prev, current, next, image_e) * gamma;
00112       energy += compute_and_normalize_energy<external_energy<I> >
00113         (gradient, prev, current, next, external_e) * khi;
00114 
00115       window2d::iter_type it(neighborhood);
00116       for_all(it)
00117         {
00118           if (minimum > energy(it.cur().col(), it.cur().row()))
00119             {
00120               minimum = energy(it.cur().col(), it.cur().row());
00121               minimum_location = it;
00122             }
00123         }
00124       if (0 != minimum_location.col() || 0 != minimum_location.row())
00125         {
00126           current += minimum_location;
00127           return true;
00128         }
00129       return false;
00130     }
00131 
00132 
00133     template <int N, class I, template<typename> class external_energy>
00134     template <class energy_functor>
00135     inline
00136     typename greedy<N, I, external_energy>::store_type
00137     greedy<N, I, external_energy>::
00138     compute_and_normalize_energy
00139     (const typename energy_functor::image_type&         gradient,
00140      const node<typename energy_functor::image_type>&   prev,
00141      const node<typename energy_functor::image_type>&   current,
00142      const node<typename energy_functor::image_type>&   next,
00143      energy_functor                                     functor)
00144     {
00145       store_type                energy;
00146       ntg::float_s              energy_min = ntg_sup_val(ntg::float_s);
00147       ntg::float_s              energy_max = ntg_inf_val(ntg::float_s);
00148 
00149       // Compute energy of each point of the neighborhood. Those are
00150       // not normalized yet.
00151       window2d::iter_type it(neighborhood);
00152       for_all(it)
00153         {
00154           ntg::float_s e = functor.compute(gradient, prev, current + it, next);
00155 
00156           // Find minimal and maximal energy on the fly, for we need them
00157           // thereafter.
00158           if (e > energy_max) energy_max = e;
00159           if (e < energy_min) energy_min = e;
00160           // Store it in a temporary location.
00161           energy(it.cur().col(), it.cur().row()) = e;
00162         }
00163       if (energy_max > 0)
00164         {
00165           ntg::float_s invmax = 1 / (energy_max - energy_min);
00166           window2d::iter_type itw(neighborhood);
00167           for_all(itw)
00168             {
00169               ntg::float_s tmp = energy(itw.cur().col(), itw.cur().row()) -
00170                 energy_min;
00171               tmp *= invmax;
00172               energy(itw.cur().col(), itw.cur().row()) = tmp;
00173             }
00174         }
00175       return energy;
00176     }
00177 
00178 
00179     template <int N, class I, template<typename> class external_energy>
00180     ntg::float_s
00181     greedy<N, I, external_energy>::compute_average_dist(const segment<I>& s)
00182     {
00183       ntg::float_s mean = 0.f;
00184 
00185       typename segment<I>::const_iter_type prev = s.begin();
00186       typename segment<I>::const_iter_type cur = s.begin();
00187       unsigned card = 0;
00188       for (++cur; cur != s.end(); ++prev, ++cur)
00189         {
00190           mean += (*cur - *prev).norm2();
00191           ++card;
00192         }
00193       return mean / (ntg::float_s)card;
00194     }
00195 
00196 
00197     template <int N, class I, template<typename> class external_energy>
00198     const int greedy<N, I, external_energy>::threshold = 3; // FIXME:
00199 
00200 
00201     template <int N, class I, template<typename> class external_energy>
00202     window2d greedy<N, I, external_energy>::neighborhood = mk_win_square(N);
00203 
00204 
00205   } // end snakes
00206 
00207 } // end oln
00208 
00209 
00210 #endif // !OLENA_SNAKES_GREEDY_HXX

Generated on Thu Apr 15 20:13:10 2004 for Olena by doxygen 1.3.6-20040222