$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
integral.hh
1 // Copyright (C) 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 SCRIBO_SUBSAMPLING_INTEGRAL_HH
27 # define SCRIBO_SUBSAMPLING_INTEGRAL_HH
28 
32 
33 #include <mln/core/concept/image.hh>
34 #include <mln/metal/equal.hh>
35 #include <mln/extension/fill.hh>
36 #include <mln/debug/println.hh>
37 #include <mln/debug/println_with_border.hh>
38 
39 
40 
41 namespace scribo
42 {
43 
44  namespace subsampling
45  {
46  using namespace mln;
47 
48 
62  template <typename I, typename J>
63  inline
64  mln_concrete(I)
65  integral(const Image<I>& input, unsigned scale,
66  Image<J>& integral_sum, Image<J>& integral_sum_2,
67  const mln_domain(I)& output_domain, unsigned border_thickness);
68 
80  template <typename I, typename J>
81  inline
82  mln_concrete(I)
83  integral(const Image<I>& input, unsigned scale,
84  Image<J>& integral_sum, Image<J>& integral_sum_2);
85 
86 
87 
88 # ifndef MLN_INCLUDE_ONLY
89 
90 
91  // Implementation.
92 
93  namespace impl
94  {
95 
96  template <typename I, typename J>
97  inline
98  mln_concrete(I)
99  integral_3(const Image<I>& input_,
100  Image<J>& integral_sum_, Image<J>& integral_sum_2_,
101  const mln_domain(I)& output_domain,
102  unsigned border_thickness)
103  {
104  mln_trace("subsampling::impl::integral_3");
105 
106  const unsigned
107  scale = 3,
108  area = scale * scale;
109 
110  const I& input = exact(input_);
111  J& integral_sum = exact(integral_sum_);
112  J& integral_sum_2 = exact(integral_sum_2_);
113 
114  mln_precondition(input.is_valid());
115  mln_precondition(input.domain().pmin() == literal::origin);
116  mln_precondition(scale > 1);
117 
118  typedef mln_value(I) V;
119  typedef mln_value(J) S;
120  typedef mln_site(I) P;
121 // mlc_is(mln_value(J), S)::check();
122 
123  mln_concrete(I) sub(output_domain, border_thickness);
124  V* p_sub = sub.buffer();
125 
126  integral_sum.init_(output_domain, border_thickness);
127  S* p_isum = integral_sum.buffer();
128 
129  integral_sum_2.init_(output_domain, border_thickness);
130  S* p_isum_2 = integral_sum_2.buffer();
131 
132  const unsigned up = sub.delta_offset(dpoint2d(-1, 0));
133 
134  const unsigned nrows = 3 * output_domain.nrows();
135  const unsigned ncols = 3 * output_domain.ncols();
136 
137  unsigned row = 0;
138 
139  unsigned b_offset = sub.delta_offset(dpoint2d(border_thickness,
140  border_thickness));
141  p_sub += b_offset;
142  p_isum += b_offset;
143  p_isum_2 += b_offset;
144  {
145  S h_sum = 0, h_sum_2 = 0;
146  const V* ptr1 = & input.at_(row, 0);
147  const V* ptr2 = & input.at_(row + 1, 0);
148  const V* ptr3 = & input.at_(row + 2, 0);
149  for (unsigned col = 0; col < ncols; col += scale)
150  {
151  S sum;
152  sum = *ptr1 + *(ptr1 + 1) + *(ptr1 + 2);
153  sum += *ptr2 + *(ptr2 + 1) + *(ptr2 + 2);
154  sum += *ptr3 + *(ptr3 + 1) + *(ptr3 + 2);
155  ptr1 += 3;
156  ptr2 += 3;
157  ptr3 += 3;
158 
159  *p_sub++ = sum / area;
160 
161  h_sum += sum;
162  h_sum_2 += sum * sum;
163 
164  // exception
165  *p_isum = h_sum;
166  *p_isum_2 = h_sum_2;
167 
168  p_isum += 1;
169  p_isum_2 += 1;
170  }
171  }
172 
173  unsigned b_next = 2 * border_thickness;
174 
175  p_sub += b_next;
176  p_isum += b_next;
177  p_isum_2 += b_next;
178 
179  for (row += scale; row < nrows; row += scale)
180  {
181  S h_sum = 0, h_sum_2 = 0;
182  const V* ptr1 = & input.at_(row, 0);
183  const V* ptr2 = & input.at_(row + 1, 0);
184  const V* ptr3 = & input.at_(row + 2, 0);
185  for (unsigned col = 0; col < ncols; col += scale)
186  {
187  S sum;
188  sum = *ptr1 + *(ptr1 + 1) + *(ptr1 + 2);
189  sum += *ptr2 + *(ptr2 + 1) + *(ptr2 + 2);
190  sum += *ptr3 + *(ptr3 + 1) + *(ptr3 + 2);
191  ptr1 += 3;
192  ptr2 += 3;
193  ptr3 += 3;
194 
195  *p_sub++ = sum / area;
196 
197  h_sum += sum;
198  h_sum_2 += sum * sum;
199 
200  *p_isum = h_sum + *(p_isum + up);
201  *p_isum_2 = h_sum_2 + *(p_isum_2 + up);
202 
203  p_isum += 1;
204  p_isum_2 += 1;
205  }
206 
207  p_sub += b_next;
208  p_isum += b_next;
209  p_isum_2 += b_next;
210  }
211 
212  return sub;
213  }
214 
215 
216  template <typename I, typename J>
217  inline
218  mln_concrete(I)
219  integral_2(const Image<I>& input_,
220  Image<J>& integral_sum_, Image<J>& integral_sum_2_,
221  const mln_domain(I)& output_domain,
222  unsigned border_thickness)
223  {
224  mln_trace("subsampling::impl::integral_2");
225 
226  const unsigned
227  scale = 2,
228  area = scale * scale;
229 
230  const I& input = exact(input_);
231  J& integral_sum = exact(integral_sum_);
232  J& integral_sum_2 = exact(integral_sum_2_);
233 
234  typedef mln_value(I) V;
235  typedef mln_value(J) S;
236  typedef mln_site(I) P;
237 
238  mlc_bool(P::dim == 2)::check();
239  mln_precondition(input.is_valid());
240  mln_precondition(input.domain().pmin() == literal::origin);
241  mln_precondition(scale > 1);
242 
243 // mlc_is(mln_value(J), S)::check();
244 
245  mln_concrete(I) sub(output_domain, border_thickness);
246  V* p_sub = sub.buffer();
247 
248  integral_sum.init_(output_domain, border_thickness);
249  S* p_isum = integral_sum.buffer();
250 
251  integral_sum_2.init_(output_domain, border_thickness);
252  S* p_isum_2 = integral_sum_2.buffer();
253 
254  const unsigned up = sub.delta_offset(dpoint2d(-1, 0));
255 
256  const unsigned nrows = 2 * output_domain.nrows();
257  const unsigned ncols = 2 * output_domain.ncols();
258 
259  extension::fill(sub, 0);
260 
261  unsigned b_offset = sub.delta_offset(dpoint2d(border_thickness,
262  border_thickness));
263  p_sub += b_offset;
264  p_isum += b_offset;
265  p_isum_2 += b_offset;
266 
267  unsigned row = 0;
268  {
269  S h_sum = 0, h_sum_2 = 0;
270  const V* ptr1 = & input.at_(row, 0);
271  const V* ptr2 = & input.at_(row + 1, 0);
272  for (unsigned col = 0; col < ncols; col += scale)
273  {
274  S sum;
275  sum = *ptr1 + *(ptr1 + 1);
276  sum += *ptr2 + *(ptr2 + 1);
277  ptr1 += 2;
278  ptr2 += 2;
279 
280  *p_sub++ = sum / area;
281 
282  h_sum += sum;
283  h_sum_2 += sum * sum;
284 
285  // exception
286  *p_isum = h_sum;
287  *p_isum_2 = h_sum_2;
288 
289  p_isum += 1;
290  p_isum_2 += 1;
291  }
292  }
293 
294  unsigned b_next = 2 * border_thickness;
295 
296  p_sub += b_next;
297  p_isum += b_next;
298  p_isum_2 += b_next;
299 
300  for (row += scale; row < nrows; row += scale)
301  {
302  S h_sum = 0, h_sum_2 = 0;
303  const V* ptr1 = & input.at_(row, 0);
304  const V* ptr2 = & input.at_(row + 1, 0);
305  for (unsigned col = 0; col < ncols; col += scale)
306  {
307  S sum;
308  sum = *ptr1 + *(ptr1 + 1);
309  sum += *ptr2 + *(ptr2 + 1);
310  ptr1 += 2;
311  ptr2 += 2;
312 
313  *p_sub++ = sum / area;
314 
315  h_sum += sum;
316  h_sum_2 += sum * sum;
317 
318  *p_isum = h_sum + *(p_isum + up);
319  *p_isum_2 = h_sum_2 + *(p_isum_2 + up);
320 
321  p_isum += 1;
322  p_isum_2 += 1;
323  }
324 
325  p_sub += b_next;
326  p_isum += b_next;
327  p_isum_2 += b_next;
328  }
329 
330  return sub;
331  }
332 
333 
334  template <typename I, typename J>
335  inline
336  mln_concrete(I)
337  integral(const Image<I>& input, unsigned scale,
338  Image<J>& simple, Image<J>& squared,
339  const mln_domain(I)& output_domain, unsigned border_thickness)
340  {
341  // mln_precondition(input.nrows() % scale == 0);
342  // mln_precondition(input.ncols() % scale == 0);
343  if (scale == 3)
344  return integral_3(input, simple, squared,
345  output_domain, border_thickness);
346  else if (scale == 2)
347  return integral_2(input, simple, squared,
348  output_domain, border_thickness);
349  else
350  std::cerr << "NYI!" << std::endl;
351 
352  typedef mln_concrete(I) output_t;
353  return output_t();
354  }
355 
356 
357  } // end of namespace mln::subsampling::impl
358 
359 
360 
361 
362  // Facades.
363 
364  template <typename I, typename J>
365  inline
366  mln_concrete(I)
367  integral(const Image<I>& input_, unsigned scale,
368  Image<J>& integral_sum, Image<J>& integral_sum_2,
369  const mln_domain(I)& output_domain, unsigned border_thickness)
370  {
371  mln_trace("subsampling::integral");
372 
373  const I& input = exact(input_);
374 
375  mln_precondition(input.is_valid());
376  mln_precondition(input.domain().pmin() == literal::origin);
377  mln_precondition(scale > 1);
378 
379  mln_concrete(I)
380  output = impl::integral(input, scale, integral_sum, integral_sum_2,
381  output_domain, border_thickness);
382 
383  return output;
384  }
385 
386  template <typename I, typename J>
387  inline
388  mln_concrete(I)
389  integral(const Image<I>& input_, unsigned scale,
390  Image<J>& integral_sum, Image<J>& integral_sum_2)
391  {
392  mln_trace("subsampling::integral");
393 
394  const I& input = exact(input_);
395 
396  mln_precondition(input.is_valid());
397  mln_precondition(input.domain().pmin() == literal::origin);
398  mln_precondition(scale > 1);
399 
400  box<mln_site(I)> b = make::box2d((input.nrows() + scale - 1) / scale,
401  (input.ncols() + scale - 1) / scale);
402  mln_concrete(I) output;
403  output = integral(input_, scale, integral_sum, integral_sum_2,
404  b, mln::border::thickness);
405 
406  return output;
407  }
408 
409 # endif // ! MLN_INCLUDE_ONLY
410 
411  } // end of namespace scribo::subsampling
412 
413 } // end of namespace scribo
414 
415 
416 #endif // ! SCRIBO_SUBSAMPLING_INTEGRAL_HH