00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
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
00150
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
00157
00158 if (e > energy_max) energy_max = e;
00159 if (e < energy_min) energy_min = e;
00160
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;
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 }
00206
00207 }
00208
00209
00210 #endif // !OLENA_SNAKES_GREEDY_HXX