https://svn/svn/oln/prototypes/proto-1.0/olena
Index: ChangeLog
from Nicolas Widynski <nicolas.widynski(a)lrde.epita.fr>
Add sample for real time segmentation.
* oln/appli/snakes/snakes.cc: New. Real time segmentation using snakes
and watersnakes.
snakes.cc | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 227 insertions(+)
Index: oln/appli/snakes/snakes.cc
--- oln/appli/snakes/snakes.cc (revision 0)
+++ oln/appli/snakes/snakes.cc (revision 0)
@@ -0,0 +1,227 @@
+#include <oln/basics2d.hh>
+#include <ntg/all.hh>
+#include <oln/morpho/watersnakes.hh>
+#include <oln/level/fill.hh>
+#include <oln/appli/snakes/snakes.hh>
+
+#define my_abs(u) ((u) > 0 ? (u) : (-(u)))
+
+using ntg::int_u8;
+
+template <typename T>
+void aff_points(const oln::image2d<T>& input,
+ const std::vector<oln::point2d>& v,
+ oln::image2d<T>& out)
+{
+ oln_iter_type(oln::image2d<T>) p(input);
+ oln::image2d<bool> mask(input.size());
+
+ for_all(p)
+ mask[p] = false;
+
+ std::vector<oln::point2d>::const_iterator it = v.begin();
+ for (; it != v.end(); it++)
+ mask[*it] = true;
+
+ for_all(p)
+ {
+ if (mask[p] == true)
+ out[p] = 255;
+ else
+ out[p] = input[p];
+ }
+}
+
+template <typename T>
+void aff_droites(const oln::image2d<T>& input,
+ const std::vector<oln::point2d>& v,
+ oln::image2d<T>& out)
+{
+ oln_iter_type(oln::image2d<T>) p(input);
+ oln::image2d<bool> mask(input.size());
+
+ for_all(p)
+ mask[p] = false;
+
+ std::vector<oln::point2d>::const_iterator it = v.begin();
+ for (; it + 1!= v.end(); it++)
+ {
+ std::vector<oln::point2d> vec = oln::snakes::impl::draw_line_(*it, *(it+1));
+ std::vector<oln::point2d>::const_iterator it2 = vec.begin();
+
+ for (; it2 != vec.end(); it2++)
+ mask[*it2] = true;
+ }
+
+ for_all(p)
+ {
+ if (mask[p] == true)
+ out[p] = 255;
+ else
+ out[p] = input[p];
+ }
+}
+
+
+
+bool nearly_equal(int x1, int x2, int y1, int y2)
+{
+ return (my_abs(x1 - x2) < 5 and my_abs(y1 - y2) < 5);
+}
+
+template <typename T>
+std::vector<oln::point2d> tri_vec(const oln::image2d<T>& ima,
+ const std::vector<oln::point2d>& v)
+{
+ std::vector<oln::point2d> res;
+ std::vector<oln::point2d>::const_iterator it;
+ std::vector<oln::point2d>::iterator it2;
+
+ int ex_1_x = -100;
+ int ex_1_y = -100;
+ int ex_2_x = 0;
+ int ex_2_y = 0;
+ int save_x = -1;
+ int save_y = -1;
+
+
+ for (int i = 0; i < 2; i++)
+ {
+ double min = 100000000;
+
+ for (it = v.begin(); it != v.end(); it++)
+ {
+ if (i and nearly_equal((*it).row(), ex_1_x, (*it).col(), ex_1_y))
+ continue;
+
+ double tmp1 = oln::snakes::impl::euclidian_distance((*it).row(), 0, 0, 0);
+ double tmp2 = oln::snakes::impl::euclidian_distance((*it).row(), ima.nrows(), 0, 0);
+ double tmp3 = oln::snakes::impl::euclidian_distance(0, 0, (*it).col(), 0);
+ double tmp4 = oln::snakes::impl::euclidian_distance(0, 0, (*it).col(), ima.ncols());
+
+ double tmp_min;
+
+ if (tmp1 <= tmp2 and tmp1 <= tmp3 and tmp1 <= tmp4)
+ tmp_min = tmp1;
+ if (tmp2 <= tmp1 and tmp2 <= tmp3 and tmp2 <= tmp4)
+ tmp_min = tmp2;
+ if (tmp3 <= tmp1 and tmp3 <= tmp2 and tmp3 <= tmp4)
+ tmp_min = tmp3;
+ if (tmp4 <= tmp1 and tmp4 <= tmp2 and tmp4 <= tmp3)
+ tmp_min = tmp4;
+
+ if (tmp_min < min)
+ {
+ min = tmp_min;
+ save_x = (*it).row();
+ save_y = (*it).col();
+ }
+ }
+ if (not i)
+ {
+ ex_1_x = save_x;
+ ex_1_y = save_y;
+ }
+ else
+ {
+ ex_2_x = save_x;
+ ex_2_y = save_y;
+ }
+ }
+
+ res.push_back(oln::point2d(ex_1_x, ex_1_y));
+
+ std::vector<oln::point2d> tmp;
+ for (it = v.begin(); it != v.end(); it++)
+ if (((*it).row() != ex_1_x or (*it).col() != ex_1_y) and
+ ((*it).row() != ex_2_x or (*it).col() != ex_2_y))
+ tmp.push_back(*it);
+
+
+ bool stop = false;
+
+ int tmp_x = ex_1_x;
+ int tmp_y = ex_1_y;
+
+ while (stop == false)
+ {
+ if (tmp.size() > 1)
+ {
+ double min = 10000000;
+ oln::point2d p;
+ std::vector<oln::point2d>::iterator p_ref;
+ for (it2 = tmp.begin(); it2 != tmp.end(); it2++)
+ {
+ double tmp_d = oln::snakes::impl::euclidian_distance((*it2).row(), tmp_x,
(*it2).col(), tmp_y);
+ if (tmp_d < min)
+ {
+ min = tmp_d;
+ p = *it2;
+ p_ref = it2;
+ }
+ }
+ res.push_back(p);
+ tmp.erase(p_ref);
+ tmp_x = p.row();
+ tmp_y = p.col();
+ }
+ else
+ {
+ res.push_back(oln::point2d(tmp.front().row(), tmp.front().col()));
+ stop = true;
+ }
+ }
+
+ res.push_back(oln::point2d(ex_2_x, ex_2_y));
+ return res;
+}
+
+
+int main(int argc, char **argv)
+{
+ using namespace oln;
+
+ if (argc < 10)
+ {
+ std::cout << "Usage : ./cmd force_type(0: grad, 1: variance) fen nb_gen
lamda dmax snake_type(0:ferme, 1:ouvert) max_pts image_bool images(1+) " <<
std::endl;
+ exit(1);
+ }
+
+ std::vector<oln::point2d> v;
+ unsigned max_pts = (unsigned)atoi(argv[7]);
+
+ oln::image2d<ntg::bin> mask = load(argv[8]);
+ oln::image2d<int_u8> input1 = load(argv[9]);
+
+ v = morpho::watersnakes(input1, mask, win_c8p(), 5);
+
+ v = tri_vec(input1, v);
+
+ if (max_pts)
+ v = oln::snakes::impl::redispatch(v, max_pts);
+
+ for (int i = 9; i < argc; i++)
+ {
+ std::cout << i - 8 << " / " << argc - 9 <<
std::endl;
+
+ oln::image2d<int_u8> input;
+ input = load(argv[i]);
+ oln::image2d<int_u8> out(input.size());
+ unsigned nb_gen = 0;
+
+ if (i == 9)
+ nb_gen = (unsigned)atoi(argv[3]);
+ else
+ nb_gen = 1;
+
+ v = oln::snakes::snakes(input, v, (force_type)(atoi(argv[1])),
(unsigned)atoi(argv[2]), nb_gen, max_pts, atof(argv[4]), (unsigned)atoi(argv[5]),
(snake_type)atoi(argv[6]));
+
+ aff_droites(input, v, out);
+ // aff_points(input, v, out);
+
+ char t[30];
+ sprintf(t, "snakes_%d.pgm", i - 8);
+
+ save(out, t);
+ }
+}