$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
integral_browsing.hh
1 // Copyright (C) 2009, 2010, 2011, 2013 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 
28 #ifndef SCRIBO_CANVAS_INTEGRAL_BROWSING_HH
29 # define SCRIBO_CANVAS_INTEGRAL_BROWSING_HH
30 
31 # include <mln/core/image/image2d.hh>
32 # include <mln/util/couple.hh>
33 
34 namespace scribo
35 {
36 
37  namespace canvas
38  {
39  using namespace mln;
40 
41 
42  template <typename F>
43  void integral_browsing(const image2d<mln::util::couple<double, double> >& ima,
44  unsigned step,
45  unsigned w, unsigned h,
46  F& functor);
47 
48 
49 # ifndef MLN_INCLUDE_ONLY
50 
51 
52  namespace internal
53  {
54 
55  inline
56  void compute_stats(// in
57  double sum, double sum_2, unsigned n,
58  // out
59  double& mean, double& stddev)
60  {
61  mean = sum / n;
62 
63  // unbias version:
64  double num = (sum_2 - sum * sum / n);
65  if (num > 0)
66  stddev = std::sqrt(num / (n - 1));
67  else
68  stddev = 0;
69 
70  }
71 
72  } // end of namespace scribo::canvas::internal
73 
74 
75 
76 
77  template <typename F>
78  void integral_browsing(const image2d<mln::util::couple<double, double> >& ima,
79  unsigned step,
80  unsigned w, unsigned h,
81  unsigned s,
82  F& functor)
83  {
85  typedef const V* Ptr;
86  Ptr a_ima, b_ima, c_ima, d_ima;
87 
88 // mln_precondition((h/2) < ima.nrows());
89 // mln_precondition((w/2) < ima.ncols());
90 
91  // Adjust window size to image.
92  if (w > (ima.domain().ncols() - ima.border()))
93  {
94  w = std::min(ima.domain().ncols(), ima.domain().nrows()) - ima.border();
95  if (! (w % 2))
96  --w;
97  mln_trace_warning("integral_browsing - "
98  "Adjusting window width since it"
99  " was larger than image height.");
100  }
101  if (h > (ima.domain().nrows() - ima.border()))
102  {
103  h = std::min(ima.domain().ncols(), ima.domain().nrows()) - ima.border();
104  if (! (h % 2))
105  --h;
106  mln_trace_warning("integral_browsing - "
107  "Adjusting window height since it"
108  " was larger than image width.");
109  }
110 
111  // Initialization
112  functor.init();
113 
114  const int
115  nrows = ima.nrows(),
116  ncols = ima.ncols(),
117  row_0 = step / 2,
118  col_0 = step / 2;
119 
120  const int
121  offset_down = ima.delta_offset(dpoint2d(step, 0)),
122  offset_ante = ima.delta_offset(dpoint2d(0, -w)),
123  offset_below = ima.delta_offset(dpoint2d(+h, 0));
124 
125  const int
126  max_row_top = h/2,
127  max_row_mid = nrows - 1 - h/2,
128  max_col_left = w/2,
129  max_col_mid = ncols - 1 - w/2,
130 
131  step_2 = step * step,
132 
133  h_top = row_0 + h/2 + 1,
134  w_left = col_0 + w/2 + 1;
135 
136 
137  int row, col;
138 
139  for (col = col_0; col <= max_col_mid; col += step) ;
140  int w_right = ncols - col + w/2;
141 
142  // tl: top left
143  // tr: top right
144  // ml: middle left
145  // mr: middle right
146  // bl: bottom left
147  // br: bottom right
148  Ptr
149  d_tl_start, d_tr_start,
150  b_ml_start = 0, d_ml_start = 0, b_mr_start = 0, d_mr_start = 0,
151  b_bl_start = 0, d_bl_start = 0, b_br_start = 0, d_br = 0;
152 
153  double mean, stddev;
154 
155  unsigned s_2 = s * s;
156 
157  // -------------------------------
158  // T (top)
159  // -------------------------------
160 
161  const unsigned
162  delta_start_left = step * w_left,
163  delta_start_right = step * w_right,
164  step_w = step * w;
165  int
166  size_tl_start = h_top * w_left,
167  size_tl,
168  delta_size_tl = h_top * step,
169  size_tc = h_top * w,
170  delta_size_tr = h_top * step,
171  size_tr_start = h_top * w_right,
172  size_tr;
173 
174  d_tl_start = & ima.at_(row_0 + h/2, col_0 + w/2);
175  d_tr_start = & ima.at_(row_0 + h/2, ncols - 1);
176 
177  for (row = row_0; row <= max_row_top; row += step)
178  {
179 
180  // TL (top left)
181 
182  d_ima = d_tl_start;
183  size_tl = size_tl_start;
184 
185  for (col = col_0; col <= max_col_left; col += step)
186  {
187  // D
188  internal::compute_stats(d_ima->first(),
189  d_ima->second(),
190  size_tl * s_2,
191  mean, stddev);
192  functor.exec(mean, stddev);
193  d_ima += step;
194  size_tl += delta_size_tl;
195  }
196 
197  delta_size_tl += step_2;
198  size_tl_start += delta_start_left;
199  d_tl_start += offset_down;
200 
201  // TC (top center)
202 
203  c_ima = d_ima + offset_ante;
204 
205  for (; col <= max_col_mid; col += step)
206  {
207  // D - C
208  internal::compute_stats(d_ima->first() - c_ima->first(),
209  d_ima->second() - c_ima->second(),
210  size_tc * s_2,
211  mean, stddev);
212  functor.exec(mean, stddev);
213  c_ima += step;
214  d_ima += step;
215  }
216 
217  size_tc += step_w;
218 
219  // TR (top right)
220 
221  d_ima = d_tr_start;
222  double
223  d_sum = d_ima->first(),
224  d_sum_2 = d_ima->second();
225  size_tr = size_tr_start;
226 
227  for (; col < ncols; col += step)
228  {
229  // D* - C
230  internal::compute_stats(d_sum - c_ima->first(),
231  d_sum_2 - c_ima->second(),
232  size_tr * s_2,
233  mean, stddev);
234  functor.exec(mean, stddev);
235  c_ima += step;
236  size_tr -= delta_size_tr;
237  }
238 
239  delta_size_tr += step_2;
240  size_tr_start += delta_start_right;
241  d_tr_start += offset_down;
242  functor.end_of_row(row);
243  }
244 
245 
246  // -------------------------------
247  // (M) middle
248  // -------------------------------
249 
250 
251  const unsigned
252  size_ml_start = h * w_left,
253  h_step = h * step,
254  size_mc = w * h;
255  unsigned
256  size_ml,
257  size_mr_start = h * w_right,
258  size_mr;
259 
260  if (row <= max_row_mid)
261  {
262  b_ml_start = & ima.at_(row - h/2 - 1, col_0 + w/2);
263  d_ml_start = b_ml_start + offset_below;
264  b_mr_start = & ima.at_(row - h/2 - 1, ncols - 1);
265  d_mr_start = b_mr_start + offset_below;
266  }
267 
268  for (; row <= max_row_mid; row += step)
269  {
270 
271  // ML (middle left)
272 
273  size_ml = size_ml_start;
274  b_ima = b_ml_start;
275  d_ima = d_ml_start;
276 
277  for (col = col_0; col <= max_col_left; col += step)
278  {
279  // D - B
280  internal::compute_stats(d_ima->first() - b_ima->first(),
281  d_ima->second() - b_ima->second(),
282  size_ml * s_2,
283  mean, stddev);
284  functor.exec(mean, stddev);
285  b_ima += step;
286  d_ima += step;
287  size_ml += h_step;
288  }
289 
290  b_ml_start += offset_down;
291  d_ml_start += offset_down;
292 
293  // MC (middle center)
294 
295  a_ima = b_ima + offset_ante;
296  c_ima = d_ima + offset_ante;
297 
298  for (; col <= max_col_mid; col += step)
299  {
300  // D + A - B - C
301 
302  internal::compute_stats((d_ima->first() - b_ima->first()) + (a_ima->first() - c_ima->first()),
303  (d_ima->second() - b_ima->second()) + (a_ima->second() - c_ima->second()),
304  size_mc * s_2,
305  mean, stddev);
306 
307  functor.exec(mean, stddev);
308 
309  a_ima += step;
310  b_ima += step;
311  c_ima += step;
312  d_ima += step;
313  }
314 
315  // MR (middle right)
316 
317  size_mr = size_mr_start;
318  b_ima = b_mr_start;
319  d_ima = d_mr_start;
320  double
321  d_b_sum = d_ima->first() - b_ima->first(),
322  d_b_sum_2 = d_ima->second() - b_ima->second();
323 
324  for (; col < ncols; col += step)
325  {
326  // D* + A - B* - C
327  internal::compute_stats(d_b_sum + (a_ima->first() - c_ima->first()),
328  d_b_sum_2 + (a_ima->second() - c_ima->second()),
329  size_mr * s_2,
330  mean, stddev);
331  functor.exec(mean, stddev);
332  a_ima += step;
333  c_ima += step;
334  size_mr -= h_step;
335  }
336 
337  b_mr_start += offset_down;
338  d_mr_start += offset_down;
339  functor.end_of_row(row);
340  }
341 
342 
343  // -------------------------------
344  // B (bottom)
345  // -------------------------------
346 
347  unsigned
348  size_bl_start = (nrows - row + h/2) * w_left,
349  size_bl,
350  delta_size_bl = (nrows - row + h/2) * step,
351  size_bc = (nrows - row + h/2) * w,
352 
353  size_br_start = (nrows - row + h/2) * w_right,
354  delta_size_br = (nrows - row + h/2) * step,
355  size_br;
356 
357  if (row < nrows)
358  {
359  b_bl_start = & ima.at_(row - h/2 - 1, col_0 + w/2);
360  d_bl_start = & ima.at_(nrows - 1, col_0 + w/2);
361  b_br_start = & ima.at_(row - h/2 - 1, ncols - 1);
362  d_br = & ima.at_(nrows - 1, ncols - 1);
363  }
364 
365  for (; row < nrows; row += step)
366  {
367 
368  // BL (bottom left)
369 
370  size_bl = size_bl_start;
371  b_ima = b_bl_start;
372  d_ima = d_bl_start;
373 
374  for (col = col_0; col <= max_col_left; col += step)
375  {
376  // D* - B
377  internal::compute_stats(d_ima->first() - b_ima->first(),
378  d_ima->second() - b_ima->second(),
379  size_bl * s_2,
380  mean, stddev);
381  functor.exec(mean, stddev);
382  b_ima += step;
383  d_ima += step;
384  size_bl += delta_size_bl;
385  }
386 
387  delta_size_bl -= step_2;
388  size_bl_start -= delta_start_left;
389  b_bl_start += offset_down;
390 
391  // BC (bottom center)
392 
393  a_ima = b_ima + offset_ante;
394  c_ima = d_ima + offset_ante;
395 
396  for (; col <= max_col_mid; col += step)
397  {
398  // D* + A - B - C*
399  internal::compute_stats((d_ima->first() - b_ima->first()) + (a_ima->first() - c_ima->first()),
400  (d_ima->second() - b_ima->second()) + (a_ima->second() - c_ima->second()),
401  size_bc * s_2,
402  mean, stddev);
403  functor.exec(mean, stddev);
404  a_ima += step;
405  b_ima += step;
406  c_ima += step;
407  d_ima += step;
408  }
409 
410  size_bc -= step_w;
411 
412  // BR (bottom right)
413 
414  size_br = size_br_start;
415  b_ima = b_br_start;
416  d_ima = d_br;
417  double
418  d_b_sum = d_ima->first() - b_ima->first(),
419  d_b_sum_2 = d_ima->second() - b_ima->second();
420 
421  for (; col < ncols; col += step)
422  {
423  // D* + A - B* - C*
424  internal::compute_stats(d_b_sum + (a_ima->first() - c_ima->first()),
425  d_b_sum_2 + (a_ima->second() - c_ima->second()),
426  size_br * s_2,
427  mean, stddev);
428  functor.exec(mean, stddev);
429  a_ima += step;
430  c_ima += step;
431  size_br -= delta_size_br;
432  }
433 
434  delta_size_br -= step_2;
435  size_br_start -= delta_start_right;
436  b_br_start += offset_down;
437  functor.end_of_row(row);
438  }
439 
440  functor.finalize();
441  }
442 
443 # endif // ! MLN_INCLUDE_ONLY
444 
445 
446  } // end of namespace scribo::canvas
447 
448 } // end of namespace mln
449 
450 
451 #endif // ! SCRIBO_CANVAS_INTEGRAL_BROWSING_HH