Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
was.median.hh
1 // Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_DATA_WAS_MEDIAN_HH
27 # define MLN_DATA_WAS_MEDIAN_HH
28 
34 # include <mln/win/shift.hh>
35 # include <mln/core/alias/window2d.hh>
36 
37 # include <mln/geom/min_col.hh>
38 # include <mln/geom/max_col.hh>
39 # include <mln/geom/max_row.hh>
40 # include <mln/geom/min_row.hh>
41 
42 # include <mln/win/diff.hh>
43 # include <mln/win/shift.hh>
44 
45 # include <mln/data/median.hh>
46 # include <mln/win/hline2d.hh>
47 
48 # include <mln/opt/at.hh>
49 
50 namespace mln
51 {
52 
53  namespace data
54  {
55 
56  namespace impl
57  {
58 
59 
60  // prefer using a canvas
61 
62  template <typename I, typename W, typename O>
63  void median_as_procedure(const I& input,
64  const W& win,
65  O& output)
66  {
67  mln_precondition(input.is_valid());
68  mln_precondition(output.is_valid());
69 
70  int
71  min_row = geom::min_row(input), max_row = geom::max_row(input),
72  min_col = geom::min_col(input), max_col = geom::max_col(input);
73 
74  window2d
75  win_fwd_plus = win - win::shift(win, left),
76  win_fwd_minus = win::shift(win, left) - win,
77  win_bkd_plus = win - win::shift(win, right),
78  win_bkd_minus = win::shift(win, right) - win,
79  win_bot = win - win::shift(win, up),
80  win_top = win::shift(win, up) - win;
81 
82  point2d p;
83  mln_qiter(W)
84  q_fp(win_fwd_plus, p), q_fm(win_fwd_minus, p),
85  q_bp(win_bkd_plus, p), q_bm(win_bkd_minus, p),
86  q_top(win_top, p), q_bot(win_bot, p);
87 
88  accu::stat::median_h<mln_vset(I)> med(input.values());
89 
90  // initialization
91 
92  p = input.bbox().pmin() + up;
93  med.init();
94  {
95  mln_qiter(W) q(win, p);
96  for_all(q) if (input.has(q))
97  med.take(input(q));
98  }
99 
100  def::coord& row = p.row();
101  def::coord& col = p.col();
102  bool fwd = true;
103 
104  mln_assertion(p.col() == min_col);
105  mln_assertion(p.row() == min_row - 1);
106 
107  for (row = min_row; row <= max_row; ++row)
108  {
109  // "go down"
110  for_all(q_top) if (input.has(q_top))
111  med.untake(input(q_top));
112  for_all(q_bot) if (input.has(q_bot))
113  med.take(input(q_bot));
114  output(p) = med;
115 
116  if (fwd)
117  // browse line fwd
118  while (col < max_col)
119  {
120  ++col;
121  for_all(q_fm) if (input.has(q_fm))
122  med.untake(input(q_fm));
123  for_all(q_fp) if (input.has(q_fp))
124  med.take(input(q_fp));
125  output(p) = med;
126  }
127  else
128  // browse line bkd
129  while (col > min_col)
130  {
131  --col;
132  for_all(q_bm) if (input.has(q_bm))
133  med.untake(input(q_bm));
134  for_all(q_bp) if (input.has(q_bp))
135  med.take(input(q_bp));
136  output(p) = med;
137  }
138 
139  // change browsing
140  fwd = ! fwd;
141  }
142  }
143 
144 
145 
146  // horizontal median
147 
148  template <typename I, typename O>
149  void hmedian(const I& input, const win::hline2d& win, O& output)
150  {
151 
152  const int
153  min_row = geom::min_row(input), max_row = geom::max_row(input),
154  min_col = geom::min_col(input), max_col = geom::max_col(input);
155  const unsigned half = win.length() / 2;
156 
157  point2d p;
158  def::coord& row = p.row();
159  def::coord& col = p.col();
160 
161  accu::stat::median_h<mln_vset(I)> med(input.values());
162 
163  for (row = min_row; row <= max_row; ++row)
164  {
165  int ct, cu;
166 
167  // initialization (before first point of the row)
168  med.init();
169  for (ct = min_col; ct < min_col + half; ++ct)
170  med.take(opt::at(input, row, ct));
171 
172  // left columns (just take new points)
173  for (col = min_col; col <= min_col + half; ++col, ++ct)
174  {
175  med.take(opt::at(input, row, ct));
176  output(p) = med;
177  }
178 
179  // middle columns (both take and untake)
180  cu = min_col;
181  for (; col <= max_col - half; ++cu, ++col, ++ct)
182  {
183  med.take(opt::at(input, row, ct));
184  med.untake(opt::at(input, row, cu));
185  output(p) = med;
186  }
187 
188  // right columns (now just untake old points)
189  for (; col <= max_col; ++cu, ++col)
190  {
191  med.untake(opt::at(input, row, cu));
192  output(p) = med;
193  }
194  }
195 
196  } // end of hmedian
197 
198 
199 
200  } // end of namespace mln::data::impl
201 
202  } // end of namespace mln::data
203 
204 } // end of namespace mln
205 
206 
207 #endif // ! MLN_DATA_WAS_MEDIAN_HH