[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

applywindowfunction.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2007-2014 by Benjamin Seppke */
4 /* Cognitive Systems Group, University of Hamburg, Germany */
5 /* */
6 /************************************************************************/
7 
8 #ifndef VIGRA_APPLYWINDOWFUCTION_HXX
9 #define VIGRA_APPLYWINDOWFUCTION_HXX
10 
11 #include "basicimage.hxx"
12 #include "copyimage.hxx"
13 #include "basicgeometry.hxx"
14 #include "initimage.hxx"
15 #include "bordertreatment.hxx"
16 
17 namespace vigra {
18 
19 /********************************************************/
20 /* */
21 /* Apply window filters to images */
22 /* */
23 /********************************************************/
24 
25 /**
26  This function calculates the results for a window function (given as a functor) when
27  applied to the complete image. Also allows a correct border handling!
28  See \ref medianFilter() for an example of a quite basic window function and its application.
29 */
30 //@{
31 
32 /** \brief Apply a window function to each pixels of a given image.
33 
34  If you pass a functor to this function, which implements the two functions:
35  <ol>
36  <li>Diff2D windowShape() const<br/>
37  to return the filter window size, which has to be odd in each dimension and</li>
38  <li>void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)<br/>
39  to compute the results of the current window,</li>
40  </ol>
41  this function calculates the results for the complete image.
42 
43  All \ref BorderTreatmentMode "border treatment modes" (except BORDER_TREATMENT_CLIP) are supported.
44 
45  The input pixel type <tt>T1</tt> must be a \ref LinearSpace "linear space" over
46  the window functions' value_type <tt>T</tt>, i.e. addition of source values, multiplication with functions' values,
47  and NumericTraits must be defined. The filters' value_type must be an \ref AlgebraicField "algebraic field",
48  i.e. the arithmetic operations (+, -, *, /) and NumericTraits must be defined.
49 
50  <b> Declarations:</b>
51 
52  pass 2D array views:
53  \code
54  namespace vigra {
55  template <class T1, class S1,
56  class T2, class S2,
57  class ProcessingFunctor>
58  void
59  applyWindowFunction(MultiArrayView<2, T1, S1> const & src,
60  MultiArrayView<2, T2, S2> dest,
61  ProcessingFunctor func,
62  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
63 
64  }
65  \endcode
66 
67  \deprecatedAPI{applyWindowFunction}
68  pass \ref ImageIterators and \ref DataAccessors :
69  \code
70  namespace vigra {
71  template <class SrcIterator, class SrcAccessor,
72  class DestIterator, class DestAccessor,
73  class ProcessingFunctor>
74  void applyWindowFunction(SrcIterator supperleft,
75  SrcIterator slowerright, SrcAccessor sa,
76  DestIterator dupperleft, DestAccessor da,
77  ProcessingFunctor func,
78  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
79  }
80  \endcode
81  use argument objects in conjunction with \ref ArgumentObjectFactories :
82  \code
83  namespace vigra {
84  template <class SrcIterator, class SrcAccessor,
85  class DestIterator, class DestAccessor,
86  class ProcessingFunctor>
87  void
88  applyWindowFunction(triple<SrcIterator, SrcIterator, SrcAccessor> src,
89  pair<DestIterator, DestAccessor> dest,
90  ProcessingFunctor func,
91  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
92  }
93  \endcode
94  \deprecatedEnd
95 
96  <b> Usage:</b>
97 
98  <b>\#include</b> <vigra/applywindowfunction.hxx><br/>
99  Namespace: vigra
100 
101  \code
102  unsigned int w=1000, h=1000;
103  MultiArray<2, float> src(w,h), dest(w,h);
104  ...
105 
106  template<class VALUETYPE>
107  class AvgFunctor
108  {
109  public:
110  MedianFunctor(Diff2D window_shape)
111  : m_window_shape(window_shape)
112  {
113  }
114 
115  template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor>
116  void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)
117  {
118  SrcIterator s_ul = s - m_window_shape/2,
119  s_lr = s_ul + m_window_shape;
120 
121  VALUETYPE result = NumericTraits<float>::zero();
122 
123  SrcIterator ys = s_ul;
124  SrcIterator xs = ys;
125 
126  for( ; ys.y != s_lr.y; ys.y++)
127  {
128  for(xs = ys; xs.x != s_lr.x; xs.x++, iter++)
129  {
130  res += s_acc(xs);
131  }
132  }
133 
134  d_acc.set(res/(m_window_shape.x*m_window_shape.y),d);
135  }
136 
137  Diff2D windowShape() const
138  {
139  return m_window_shape;
140  }
141  private:
142  Diff2D m_window_shape;
143  };
144 
145 
146  // create an AverageFilter function for a 5x5 filter
147  AvgFunctor func(Diff2D(5,5));
148 
149 
150  // apply the filter function to the input image
151  applyWindowFunction(src, dest, func);
152  \endcode
153 
154  <b> Preconditions:</b>
155 
156  The image must be larger than the window size.
157 */
158 
160 
161 template <class SrcIterator, class SrcAccessor,
162  class DestIterator, class DestAccessor,
163  class ProcessingFunctor>
164 void applyWindowFunction(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
165  DestIterator d_ul, DestAccessor d_acc,
166  ProcessingFunctor func,
167  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
168 {
169  vigra_precondition((border == BORDER_TREATMENT_AVOID ||
170  //border == BORDER_TREATMENT_CLIP ||
171  border == BORDER_TREATMENT_REPEAT ||
172  border == BORDER_TREATMENT_REFLECT ||
173  border == BORDER_TREATMENT_WRAP ||
174  border == BORDER_TREATMENT_ZEROPAD
175  ),
176  "vigra::applyWindowFunction():\n"
177  " Border treatment must be one of follow treatments:\n"
178  " - BORDER_TREATMENT_AVOID\n"
179  //" - BORDER_TREATMENT_CLIP\n"
180  " - BORDER_TREATMENT_REPEAT\n"
181  " - BORDER_TREATMENT_REFLECT\n"
182  " - BORDER_TREATMENT_WRAP\n"
183  " - BORDER_TREATMENT_ZEROPAD\n"
184  );
185 
186  typename SrcIterator::difference_type img_shape = s_lr - s_ul;
187  Diff2D win_shape = func.windowShape();
188 
189  vigra_precondition( win_shape.x % 2 == 1 , "vigra::applyWindowFunction(): Filter window width has to be of odd size!");
190  vigra_precondition( win_shape.y % 2 == 1 , "vigra::applyWindowFunction(): Filter window height has to be of odd size!");
191 
192  vigra_precondition( win_shape.x <= img_shape.x && win_shape.y <= img_shape.y , "vigra::applyWindowFunction(): Filter window is larger than image!");
193 
194  /**********************************************************************************
195  * *
196  * COMPUTE ALL "SAFE" PIXELS, WHERE THE MASK FITS COMPLETELY INTO THE IMAGE *
197  * *
198  **********************************************************************************/
199 
200 
201  SrcIterator ys = s_ul,
202  xs = ys;
203 
204  DestIterator yd = d_ul,
205  xd = yd;
206 
207  SrcIterator end = s_ul + img_shape - win_shape/2;
208 
209  ys.y += win_shape.y/2;
210  yd.y += win_shape.y/2;
211 
212  unsigned int y=0;
213 
214  for( ; ys.y != end.y; ys.y++, yd.y++, y++)
215  {
216  xs = ys;
217  xs.x += win_shape.x/2;
218 
219  xd = yd;
220  xd.x += win_shape.x/2;
221 
222  for( ; xs.x != end.x; xs.x++, xd.x++)
223  {
224  func(xs, s_acc, xd, d_acc);
225  }
226  }
227 
228 
229 
230  /**********************************************************************************
231  * *
232  * HANDLE THE EIGHT BORDER CASES SEPARATELY *
233  * *
234  * *
235  * and do this diffently according to the used border treatment type, of course *
236  * *
237  **********************************************************************************/
238 
239 
240  if(border == BORDER_TREATMENT_AVOID)
241  return; // skip processing near the border
242 
243 
244  //Do some preparation for the special cases:
245  //Create window of width = image width and height = win_shape
246  BasicImage<typename SrcIterator::PixelType> temp(img_shape.x, win_shape.y + win_shape.y/2);
247  typedef typename BasicImage<typename SrcIterator::PixelType>::Iterator TempIterator;
248 
249  TempIterator t_ul = temp.upperLeft(),
250  t_lr = temp.lowerRight();
251 
252  DestAccessor t_acc = temp.accessor();
253 
254  TempIterator yt = t_ul,
255  xt = yt;
256 
257 
258  /**********************************************************************************
259  * *
260  * SIDE CASE 1 (1/8): *
261  * * *
262  * HANDLE UPPER PIXELS WHERE THE MASK IS MISSING MINIMUM y-COORDINATES *
263  * *
264  **********************************************************************************/
265  if(border == BORDER_TREATMENT_REPEAT)
266  {
267  ys = s_ul;
268  Diff2D lineDiff(img_shape.x,1);
269 
270  for( ; yt.y != t_lr.y - win_shape.y; ++yt.y)
271  {
272  copyImage(ys, ys+lineDiff, s_acc, yt, t_acc);
273  }
274  copyImage(ys, ys+Diff2D(img_shape.x,win_shape.y), s_acc, yt, t_acc);
275 
276  }
277  else if(border == BORDER_TREATMENT_REFLECT)
278  {
279  reflectImage(s_ul, s_ul+Diff2D(img_shape.x,win_shape.y/2), s_acc, t_ul, t_acc, horizontal);
280  copyImage(s_ul, s_ul+Diff2D(img_shape.x,win_shape.y), s_acc, t_ul+Diff2D(0,win_shape.y/2), t_acc);
281 
282  }
283  else if(border == BORDER_TREATMENT_WRAP)
284  {
285  copyImage(s_ul+Diff2D(0, img_shape.y-win_shape.y/2), s_lr, s_acc, t_ul, t_acc);
286  copyImage(s_ul, s_ul+Diff2D(img_shape.x,win_shape.y), s_acc, t_ul+Diff2D(0,win_shape.y/2), t_acc);
287 
288  }
289  else if(border == BORDER_TREATMENT_ZEROPAD)
290  {
291  initImage(t_ul, t_lr, t_acc, 0);
292  copyImage(s_ul, s_ul+Diff2D(img_shape.x,win_shape.y), s_acc, t_ul+Diff2D(0,win_shape.y/2), t_acc);
293 
294  }
295 
296  yt = t_ul;
297  yt.y += win_shape.y/2;
298  yd = d_ul;
299 
300  for( ; yt.y != t_lr.y-win_shape.y/2; ++yd.y, ++yt.y)
301  {
302  xt = yt;
303  xt.x += win_shape.x/2;
304 
305  xd = yd;
306  xd.x += win_shape.x/2;
307 
308  for( ; xt.x != t_lr.x-win_shape.x/2; xd.x++, xt.x++)
309  {
310  func(xt, t_acc, xd, d_acc);
311  }
312  }
313 
314  /**********************************************************************************
315  * *
316  * SIDE CASE 2 (2/8): *
317  * * *
318  * HANDLE LOWER PIXELS WHERE THE MASK IS MISSING MAXIMUM y-COORDINATES *
319  * *
320  **********************************************************************************/
321  if(border == BORDER_TREATMENT_REPEAT)
322  {
323  ys = s_ul + Diff2D(0, img_shape.y-1);
324  yt = t_ul + Diff2D(0, win_shape.x);
325 
326  Diff2D lineDiff(img_shape.x,1);
327 
328  for( ; yt.y != t_lr.y ; ++yt.y)
329  {
330  copyImage(ys, ys+lineDiff, s_acc, yt, t_acc);
331  }
332  ys = s_ul + Diff2D(0, img_shape.y-win_shape.y);
333  yt = t_ul;
334  copyImage(ys, ys+Diff2D(img_shape.x,win_shape.y), s_acc, yt, t_acc);
335 
336  }
337  else if(border == BORDER_TREATMENT_REFLECT)
338  {
339  reflectImage(s_ul+Diff2D(0, img_shape.y-win_shape.y/2), s_lr, s_acc, t_ul+Diff2D(0, win_shape.y), t_acc, horizontal);
340  copyImage(s_ul+Diff2D(0, img_shape.y-win_shape.y), s_lr, s_acc, t_ul, t_acc);
341 
342  }
343  else if(border == BORDER_TREATMENT_WRAP)
344  {
345  copyImage(s_ul, s_ul + Diff2D(img_shape.x, win_shape.y/2), s_acc, t_ul+Diff2D(0, win_shape.y), t_acc);
346  copyImage(s_ul+Diff2D(0, img_shape.y-win_shape.y), s_lr, s_acc, t_ul, t_acc);
347 
348  }
349  else if(border == BORDER_TREATMENT_ZEROPAD)
350  {
351  initImage(t_ul, t_lr, t_acc, 0);
352  copyImage(s_ul+Diff2D(0, img_shape.y-win_shape.y), s_lr, s_acc, t_ul, t_acc);
353 
354  }
355 
356 
357  yt = t_ul;
358  yt.y += win_shape.y/2;
359  yd = d_ul;
360  yd.y += img_shape.y-win_shape.y/2-1;
361 
362  for( ; yt.y != t_lr.y - win_shape.y/2 ; ++yd.y, ++yt.y)
363  {
364  xt = yt;
365  xt.x += win_shape.x/2;
366 
367  xd = yd;
368  xd.x += win_shape.x/2;
369 
370  for( ; xt.x != t_lr.x-win_shape.x/2; xd.x++, xt.x++)
371  {
372  func(xt, t_acc, xd, d_acc);
373  }
374  }
375 
376 
377  //Preparation needed for left and right processing
378  temp.resize(win_shape.x+win_shape.x/2,img_shape.y);
379  t_ul = temp.upperLeft(); t_lr = temp.lowerRight();
380  t_acc = temp.accessor();
381 
382 
383 
384  /**********************************************************************************
385  * *
386  * SIDE CASE 3 (3/8): *
387  * *
388  * HANDLE LEFT PIXELS WHERE THE MASK IS MISSING MINIMUM x-COORDINATES *
389  * *
390  **********************************************************************************/
391  if(border == BORDER_TREATMENT_REPEAT)
392  {
393  xs = s_ul;
394  xt = t_ul;
395  xd = d_ul;
396 
397  Diff2D colDiff(1,img_shape.y);
398 
399  for( ; xt.x != t_lr.x - win_shape.x; ++xt.x)
400  {
401  copyImage(xs, xs+colDiff, s_acc, xt, t_acc);
402  }
403  copyImage(xs, xs+Diff2D(win_shape.x, img_shape.y), s_acc, xt, t_acc);
404 
405  }
406  else if(border == BORDER_TREATMENT_REFLECT)
407  {
408  reflectImage(s_ul, s_ul+Diff2D(win_shape.x/2, img_shape.y), s_acc, t_ul, t_acc, vertical);
409  copyImage(s_ul, s_ul+Diff2D(win_shape.x, img_shape.y), s_acc, t_ul + Diff2D(win_shape.x/2, 0), t_acc);
410 
411  }
412  else if(border == BORDER_TREATMENT_WRAP)
413  {
414  copyImage(s_ul+Diff2D(img_shape.x-win_shape.x/2, 0), s_lr, s_acc, t_ul, t_acc);
415  copyImage(s_ul, s_ul+Diff2D(win_shape.x, img_shape.y), s_acc, t_ul + Diff2D(win_shape.x/2, 0), t_acc);
416 
417  }
418  else if(border == BORDER_TREATMENT_ZEROPAD)
419  {
420  initImage(t_ul, t_lr, t_acc, 0);
421  copyImage(s_ul, s_ul+Diff2D(win_shape.x, img_shape.y), s_acc, t_ul + Diff2D(win_shape.x/2, 0), t_acc);
422 
423  }
424 
425 
426  yt = t_ul;
427  yt.y += win_shape.y/2;
428  yd = d_ul;
429  yd.y += win_shape.y/2;
430 
431  for( ; yt.y != t_lr.y-win_shape.y/2; ++yd.y, ++yt.y)
432  {
433  xt = yt;
434  xt.x += win_shape.x/2;
435 
436  xd = yd;
437 
438  for( ; xt.x != t_lr.x-win_shape.x/2; xd.x++, xt.x++)
439  {
440  func(xt, t_acc, xd, d_acc);
441  }
442  }
443 
444 
445  /**********************************************************************************
446  * *
447  * SIDE CASE 4 (4/8): *
448  * *
449  * HANDLE RIGHT PIXELS WHERE THE MASK IS MISSING MAXIMUM x-COORDINATES *
450  * *
451  **********************************************************************************/
452  if(border == BORDER_TREATMENT_REPEAT)
453  {
454  xs = s_ul + Diff2D(img_shape.x-1,0);
455  xt = t_ul + Diff2D(win_shape.x,0);
456  xd = d_ul;
457 
458  Diff2D colDiff(1,img_shape.y);
459 
460  for( ; xt.x != t_lr.x ; ++xt.x)
461  {
462  copyImage(xs, xs+colDiff, s_acc, xt, t_acc);
463  }
464  ys = s_ul + Diff2D(img_shape.x-win_shape.x,0);
465  yt = t_ul;
466  copyImage(ys, ys+Diff2D(win_shape.x,img_shape.y), s_acc, yt, t_acc);
467 
468 
469  }
470  else if(border == BORDER_TREATMENT_REFLECT)
471  {
472  reflectImage(s_ul+Diff2D(img_shape.x-win_shape.x/2,0), s_lr, s_acc, t_ul+Diff2D(win_shape.x,0), t_acc, vertical);
473  copyImage(s_ul+Diff2D(img_shape.x-win_shape.x,0), s_lr, s_acc, t_ul, t_acc);
474 
475 
476  }
477  else if(border == BORDER_TREATMENT_WRAP)
478  {
479  copyImage(s_ul, s_ul+Diff2D(win_shape.x/2,img_shape.y), s_acc, t_ul+Diff2D(win_shape.x,0), t_acc);
480  copyImage(s_ul+Diff2D(img_shape.x-win_shape.x,0), s_lr, s_acc, t_ul, t_acc);
481 
482 
483  }
484  else if(border == BORDER_TREATMENT_ZEROPAD)
485  {
486  initImage(t_ul, t_lr, t_acc, 0);
487  copyImage(s_ul+Diff2D(img_shape.x-win_shape.x,0), s_lr, s_acc, t_ul, t_acc);
488 
489  }
490 
491 
492  yt = t_ul;
493  yt.y += win_shape.x/2;
494  yd = d_ul;
495  yd.x += img_shape.x-win_shape.x/2-1;
496  yd.y += win_shape.y/2;
497 
498  for( ; yt.y != t_lr.y-win_shape.y/2; ++yd.y, ++yt.y)
499  {
500  xt = yt;
501  xt.x += win_shape.x/2;
502 
503  xd = yd;
504 
505  for( ; xt.x != t_lr.x-win_shape.x/2; xd.x++, xt.x++)
506  {
507  func(xt, t_acc, xd, d_acc);
508  }
509  }
510 
511  //Do some preaparations for the corner cases
512  temp.resize(win_shape+win_shape/2);
513  t_ul = temp.upperLeft(); t_lr = temp.lowerRight();
514  t_acc = temp.accessor();
515 
516 
517 
518  /**********************************************************************************
519  * *
520  * CORNER CASE 1 (5/8): *
521  * *
522  * HANDLE UPPERLEFT PIXELS WHERE THE MASK IS MISSING MINIMUM *
523  * x-COORDINATES AND MINIMUM y-COORDINATES *
524  * *
525  **********************************************************************************/
526  if(border == BORDER_TREATMENT_REPEAT)
527  {
528  //init upperleft rect with single value
529  ys = s_ul;
530  yt = t_ul;
531  initImage(yt,yt+win_shape/2, t_acc, s_acc(ys));
532 
533  //init upperright rect with vertical stripes
534  ys = s_ul;
535  yt = t_ul + Diff2D(win_shape.x/2,0);
536  Diff2D lineDiff(win_shape.x,1);
537  for( ; yt.y != t_lr.y-win_shape.y ; ++yt.y)
538  {
539  copyImage(ys, ys+lineDiff, s_acc, yt, t_acc);
540  }
541 
542  //init lowerleft rect with horizontal stripes
543  xs = s_ul;
544  xt = t_ul + Diff2D(0,win_shape.y/2);
545  Diff2D rowDiff(1, win_shape.y);
546  for( ; xt.x != t_lr.x-win_shape.x ; ++xt.x)
547  {
548  copyImage(xs, xs+rowDiff, s_acc, xt, t_acc);
549  }
550 
551  //copy image patch in lower right patch
552  ys = s_ul;
553  yt = t_ul + win_shape/2;
554  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
555 
556  }
557  else if(border == BORDER_TREATMENT_REFLECT)
558  {
559  //init upperleft rect with double reflect image
560  ys = s_ul;
561  yt = t_ul;
562  rotateImage(ys,ys+win_shape/2, s_acc, yt, t_acc, 180);
563 
564  //init upperright rect with horizontal reflected image
565  ys = s_ul;
566  yt = t_ul + Diff2D(win_shape.x/2,0);
567  reflectImage(ys, ys+Diff2D(win_shape.x, win_shape.y/2), s_acc, yt, t_acc, horizontal);
568 
569  //init lowerleft rect with vertical reflected image
570  xs = s_ul;
571  xt = t_ul + Diff2D(0,win_shape.y/2);
572  reflectImage(xs, xs+Diff2D(win_shape.x/2, win_shape.y), s_acc, xt, t_acc,vertical);
573 
574  //copy image patch in lower right patch
575  ys = s_ul;
576  yt = t_ul + win_shape/2;
577  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
578 
579  }
580  else if(border == BORDER_TREATMENT_WRAP)
581  {
582  //init upperleft rect with lower right image part
583  ys = s_ul+ img_shape - win_shape/2;
584  yt = t_ul;
585  copyImage(ys, s_lr, s_acc, yt, t_acc);
586 
587  //init upperright rect with images lower left part
588  ys = s_ul + Diff2D(0, img_shape.y-win_shape.y/2);
589  yt = t_ul + Diff2D(win_shape.x/2,0);
590  copyImage(ys, ys+Diff2D(win_shape.x, win_shape.y/2), s_acc, yt, t_acc);
591 
592  //init lowerleft rect with with images upper right part
593  xs = s_ul + Diff2D(img_shape.x-win_shape.x/2, 0);
594  xt = t_ul + Diff2D(0,win_shape.y/2);
595  copyImage(xs, xs+Diff2D(win_shape.x/2, win_shape.y), s_acc, xt, t_acc);
596 
597  //copy image patch in lower right patch
598  ys = s_ul;
599  yt = t_ul + win_shape/2;
600  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
601 
602  }
603  else if(border == BORDER_TREATMENT_ZEROPAD)
604  {
605  initImage(t_ul, t_lr, t_acc, 0);
606 
607  //copy image patch in lower right patch
608  ys = s_ul;
609  yt = t_ul + win_shape/2;
610  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
611 
612  }
613 
614 
615  yt = t_ul;
616  yt.y += win_shape.y/2;
617  yd = d_ul;
618 
619  for( ; yt.y != t_lr.y-win_shape.y/2; ++yd.y, ++yt.y)
620  {
621  xt = yt;
622  xt.x += win_shape.x/2;
623 
624  xd = yd;
625 
626  for( ; xt.x != t_lr.x-win_shape.x/2; xd.x++, xt.x++)
627  {
628  func(xt, t_acc, xd, d_acc);
629  }
630  }
631 
632 
633  /**********************************************************************************
634  * *
635  * CORNER CASE 2 (6/8): *
636  * *
637  * HANDLE UPPERRIGHT PIXELS WHERE THE MASK IS MISSING MAXIMUM *
638  * x-COORDINATES AND MINIMUM y-COORDINATES *
639  * *
640  **********************************************************************************/
641  if(border == BORDER_TREATMENT_REPEAT)
642  {
643  //init upperright rect with single value
644  ys = s_ul + Diff2D(img_shape.x-1,0);
645  yt = t_ul + Diff2D(win_shape.x,0);
646  initImage(yt, yt+win_shape/2, t_acc, s_acc(ys));
647 
648  //init upperleft rect with vertical stripes
649  ys = s_ul + Diff2D(img_shape.x-win_shape.x,0);;
650  yt = t_ul;
651  Diff2D lineDiff(win_shape.x,1);
652  for( ; yt.y != t_lr.y-win_shape.y ; ++yt.y)
653  {
654  copyImage(ys, ys+lineDiff, s_acc, yt, t_acc);
655  }
656 
657  //init lowerright rect with horizontal stripes
658  xs = s_ul + Diff2D(img_shape.x-1,0);;
659  xt = t_ul + Diff2D(win_shape.x,win_shape.y/2);
660  Diff2D rowDiff(1, win_shape.y);
661  for( ; xt.x != t_lr.x; ++xt.x)
662  {
663  copyImage(xs, xs+rowDiff, s_acc, xt, t_acc);
664  }
665 
666  //copy image patch in lower left patch
667  ys = s_ul + Diff2D(img_shape.x-win_shape.x,0);
668  yt = t_ul + Diff2D(0, win_shape.y/2);
669  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
670 
671  }
672  else if(border == BORDER_TREATMENT_REFLECT)
673  {
674  //init upperright rect with double flipped image
675  ys = s_ul + Diff2D(img_shape.x-win_shape.x/2,0);
676  yt = t_ul + Diff2D(win_shape.x,0);
677  rotateImage(ys, ys+win_shape/2, s_acc, yt, t_acc, 180);
678 
679  //init upperleft rect with horizontal reflected image
680  ys = s_ul + Diff2D(img_shape.x-win_shape.x,0);
681  yt = t_ul;
682  reflectImage(ys, ys+Diff2D(win_shape.x, win_shape.y/2), s_acc, yt, t_acc, horizontal);
683 
684  //init lowerright rect with vertical reflected image
685  xs = s_ul + Diff2D(img_shape.x-win_shape.x/2,0);
686  xt = t_ul + Diff2D(win_shape.x,win_shape.y/2);
687  reflectImage(xs, xs+Diff2D(win_shape.x/2, win_shape.y), s_acc, xt, t_acc,vertical);
688 
689  //copy image patch in lower left patch
690  ys = s_ul + Diff2D(img_shape.x-win_shape.x,0);
691  yt = t_ul + Diff2D(0, win_shape.y/2);
692  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
693 
694  }
695  else if(border == BORDER_TREATMENT_WRAP)
696  {
697  //init upperright rect with lower left image part
698  ys = s_ul + Diff2D(0, img_shape.y-win_shape.y/2);
699  yt = t_ul + Diff2D(win_shape.x,0);
700  copyImage(ys, ys+win_shape/2, s_acc, yt, t_acc);
701 
702  //init upperleft rect with lower right image part
703  ys = s_ul + Diff2D(img_shape.x-win_shape.x, img_shape.y-win_shape.y/2);
704  yt = t_ul;
705  copyImage(ys, ys+Diff2D(win_shape.x, win_shape.y/2), s_acc, yt, t_acc);
706 
707  //init lowerright rect with upperleft image part
708  xs = s_ul;
709  xt = t_ul + Diff2D(win_shape.x,win_shape.y/2);
710  copyImage(xs, xs+Diff2D(win_shape.x/2, win_shape.y), s_acc, xt, t_acc);
711 
712  //copy image patch in lower left patch
713  ys = s_ul + Diff2D(img_shape.x-win_shape.x,0);
714  yt = t_ul + Diff2D(0, win_shape.y/2);
715  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
716 
717  }
718  else if(border == BORDER_TREATMENT_ZEROPAD)
719  {
720  initImage(t_ul, t_lr, t_acc, 0);
721 
722  //copy image patch in lower left patch
723  ys = s_ul + Diff2D(img_shape.x-win_shape.x,0);
724  yt = t_ul + Diff2D(0, win_shape.y/2);
725  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
726 
727  }
728 
729 
730  yt = t_ul;
731  yt.y += win_shape.y/2;
732  yd = d_ul + Diff2D(img_shape.x-win_shape.x/2-1, 0);
733 
734  for( ; yt.y != t_lr.y-win_shape.y/2; ++yd.y, ++yt.y)
735  {
736  xt = yt;
737  xt.x += win_shape.x/2;
738 
739  xd = yd;
740 
741  for( ; xt.x != t_lr.x-win_shape.x/2; xd.x++, xt.x++)
742  {
743  func(xt, t_acc, xd, d_acc);
744  }
745  }
746 
747  /**********************************************************************************
748  * *
749  * CORNER CASE 3 (7/8): *
750  * *
751  * HANDLE LOWERLEFT PIXELS WHERE THE MASK IS MISSING MINIMUM *
752  * x-COORDINATES AND MAXIMUM y-COORDINATES *
753  * *
754  **********************************************************************************/
755  if(border == BORDER_TREATMENT_REPEAT)
756  {
757  //init lowerleft rect with single value
758  ys = s_ul + Diff2D(0,img_shape.y-1);
759  yt = t_ul + Diff2D(0,win_shape.y);
760  initImage(yt, yt+win_shape/2, t_acc, s_acc(ys));
761 
762  //init lowerright rect with vertical stripes
763  ys = s_ul + Diff2D(0,img_shape.y-1);
764  yt = t_ul + Diff2D(win_shape.x/2,win_shape.y);
765  Diff2D lineDiff(win_shape.x,1);
766  for( ; yt.y != t_lr.y ; ++yt.y)
767  {
768  copyImage(ys, ys+lineDiff, s_acc, yt, t_acc);
769  }
770 
771  //init upperleft rect with horizontal stripes
772  xs = s_ul + Diff2D(0,img_shape.y-win_shape.y);
773  xt = t_ul;
774  Diff2D rowDiff(1, win_shape.y);
775  for( ; xt.x != t_lr.x-win_shape.x; ++xt.x)
776  {
777  copyImage(xs, xs+rowDiff, s_acc, xt, t_acc);
778  }
779 
780  //copy image patch in upper right patch
781  yt = t_ul + Diff2D(win_shape.x/2,0);
782  ys = s_ul + Diff2D(0,img_shape.y-win_shape.y);
783  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
784 
785  }
786  else if(border == BORDER_TREATMENT_REFLECT)
787  {
788  //init lowerleft rect with double reflected image
789  ys = s_ul + Diff2D(0,img_shape.y-win_shape.y/2);
790  yt = t_ul + Diff2D(0,win_shape.y);
791  rotateImage(ys, ys+win_shape/2, s_acc, yt, t_acc, 180);
792 
793  //init lowerright rect with horizontal reflected image
794  ys = s_ul + Diff2D(0,img_shape.y-win_shape.y/2);
795  yt = t_ul + Diff2D(win_shape.x/2,win_shape.y);
796  reflectImage(ys, ys+Diff2D(win_shape.x, win_shape.y/2), s_acc, yt, t_acc, horizontal);
797 
798  //init upperleft rect with vertical reflected image
799  xs = s_ul + Diff2D(0,img_shape.y-win_shape.y);
800  xt = t_ul;
801  reflectImage(xs, xs+Diff2D(win_shape.x/2, win_shape.y), s_acc, xt, t_acc,vertical);
802 
803  //copy image patch in upper right patch
804  yt = t_ul + Diff2D(win_shape.x/2,0);
805  ys = s_ul + Diff2D(0,img_shape.y-win_shape.y);
806  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
807 
808  }
809  else if(border == BORDER_TREATMENT_WRAP)
810  {
811  //init lowerleft rect with upper right image part
812  ys = s_ul + Diff2D(img_shape.x-win_shape.x/2,0);
813  yt = t_ul + Diff2D(0,win_shape.y);
814  copyImage(ys, ys+win_shape/2, s_acc, yt, t_acc);
815 
816  //init lowerright rect with upper left image part
817  ys = s_ul;
818  yt = t_ul + Diff2D(win_shape.x/2,win_shape.y);
819  copyImage(ys, ys+Diff2D(win_shape.x, win_shape.y/2), s_acc, yt, t_acc);
820 
821  //init upperleft rect with lower right image part
822  xs = s_ul + Diff2D(img_shape.x-win_shape.x/2,img_shape.y-win_shape.y);
823  xt = t_ul;
824  copyImage(xs, xs+Diff2D(win_shape.x/2, win_shape.y), s_acc, xt, t_acc);
825 
826  //copy image patch in upper right patch
827  yt = t_ul + Diff2D(win_shape.x/2,0);
828  ys = s_ul + Diff2D(0,img_shape.y-win_shape.y);
829  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
830 
831  }
832  else if(border == BORDER_TREATMENT_ZEROPAD)
833  {
834  initImage(t_ul, t_lr, t_acc, 0);
835 
836  //copy image patch in upper right patch
837  yt = t_ul + Diff2D(win_shape.x/2,0);
838  ys = s_ul + Diff2D(0,img_shape.y-win_shape.y);
839  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
840 
841  }
842 
843 
844  yt = t_ul;
845  yt.y += win_shape.y/2;
846  yd = d_ul + Diff2D(0, img_shape.y-win_shape.y/2-1);
847 
848  for( ; yt.y != t_lr.y-win_shape.y/2; ++yd.y, ++yt.y)
849  {
850  xt = yt;
851  xt.x += win_shape.x/2;
852 
853  xd = yd;
854 
855  for( ; xt.x != t_lr.x-win_shape.x/2; xd.x++, xt.x++)
856  {
857  func(xt, t_acc, xd, d_acc);
858  }
859  }
860 
861  /**********************************************************************************
862  * *
863  * CORNER CASE 4 (8/8): *
864  * *
865  * HANDLE LOWERRIGHT PIXELS WHERE THE MASK IS MISSING MAXIMUM *
866  * x-COORDINATES AND MAXIMUM y-COORDINATES *
867  * *
868  **********************************************************************************/
869  if(border == BORDER_TREATMENT_REPEAT)
870  {
871  //init lowerright rect with single value
872  ys = s_ul + Diff2D(img_shape.x-1,img_shape.y-1);
873  yt = t_ul + win_shape;
874  initImage(yt,yt+win_shape/2, t_acc, s_acc(ys));
875 
876  //init lowerleft rect with vertical stripes
877  ys = s_ul + Diff2D(img_shape.x-win_shape.x,img_shape.y-1);
878  yt = t_ul + Diff2D(0,win_shape.y);
879  Diff2D lineDiff(win_shape.x,1);
880  for( ; yt.y != t_lr.y ; ++yt.y)
881  {
882  copyImage(ys, ys+lineDiff, s_acc, yt, t_acc);
883  }
884 
885  //init upperright rect with horizontal stripes
886  xs = s_ul + Diff2D(img_shape.x-1,img_shape.y-win_shape.y);
887  xt = t_ul + Diff2D(win_shape.x,0);
888  Diff2D rowDiff(1, win_shape.y);
889  for( ; xt.x != t_lr.x; ++xt.x)
890  {
891  copyImage(xs, xs+rowDiff, s_acc, xt, t_acc);
892  }
893 
894  //copy image patch in upperleft patch
895  ys = s_ul + img_shape - win_shape;
896  yt = t_ul;
897  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
898 
899  }
900  else if(border == BORDER_TREATMENT_REFLECT)
901  {
902  //init lowerright rect with double reflected image
903  ys = s_ul + img_shape-win_shape/2;
904  yt = t_ul + win_shape;
905  rotateImage(ys, ys+win_shape/2, s_acc, yt, t_acc, 180);
906 
907  //init lowerleft rect with horizontal reflected image
908  ys = s_ul + Diff2D(img_shape.x-win_shape.x,img_shape.y-win_shape.y/2);
909  yt = t_ul + Diff2D(0,win_shape.y);
910  reflectImage(ys, ys+Diff2D(win_shape.x, win_shape.y/2), s_acc, yt, t_acc, horizontal);
911 
912  //init upperright rect with vertical reflected image
913  xs = s_ul + Diff2D(img_shape.x-win_shape.x/2,img_shape.y-win_shape.y);
914  xt = t_ul + Diff2D(win_shape.x,0);
915  reflectImage(xs, xs+Diff2D(win_shape.x/2, win_shape.y), s_acc, xt, t_acc,vertical);
916 
917  //copy image patch in upperleft patch
918  ys = s_ul + img_shape - win_shape;
919  yt = t_ul;
920  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
921 
922  }
923  else if(border == BORDER_TREATMENT_WRAP)
924  {
925  //init lowerright with upperleft image part
926  ys = s_ul;
927  yt = t_ul + win_shape;
928  copyImage(ys, ys+win_shape/2, s_acc, yt, t_acc);
929 
930  //init lowerleft rect with upper right image part
931  ys = s_ul + Diff2D(img_shape.x-win_shape.x,0);
932  yt = t_ul + Diff2D(0,win_shape.y);
933  copyImage(ys, ys+Diff2D(win_shape.x, win_shape.y/2), s_acc, yt, t_acc);
934 
935  //init upperright rect with lower left image part
936  xs = s_ul + Diff2D(0,img_shape.y-win_shape.y);
937  xt = t_ul + Diff2D(win_shape.x,0);
938  copyImage(xs, xs+Diff2D(win_shape.x/2, win_shape.y), s_acc, xt, t_acc);
939 
940  //copy image patch in upperleft patch
941  ys = s_ul + img_shape-win_shape;
942  yt = t_ul;
943  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
944 
945  }
946  else if(border == BORDER_TREATMENT_ZEROPAD)
947  {
948  initImage(t_ul, t_lr, t_acc, 0);
949 
950  //copy image patch in upperleft patch
951  ys = s_ul + img_shape - win_shape;
952  yt = t_ul;
953  copyImage(ys, ys+win_shape, s_acc, yt, t_acc);
954 
955  }
956 
957 
958  yt = t_ul;
959  yt.y += win_shape.y/2;
960  yd = d_ul + img_shape-win_shape/2-Diff2D(1,1);
961 
962  for( ; yt.y != t_lr.y-win_shape.y/2; ++yd.y, ++yt.y)
963  {
964  xt = yt;
965  xt.x += win_shape.x/2;
966 
967  xd = yd;
968 
969  for( ; xt.x != t_lr.x-win_shape.x/2; xd.x++, xt.x++)
970  {
971  func(xt, t_acc, xd, d_acc);
972  }
973  }
974 }
975 
976 template <class SrcIterator, class SrcAccessor,
977  class DestIterator, class DestAccessor,
978  class ProcessingFunctor>
979 inline void applyWindowFunction(triple<SrcIterator, SrcIterator, SrcAccessor> s,
980  pair<DestIterator, DestAccessor> d,
981  ProcessingFunctor func,
982  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
983 {
984  applyWindowFunction(s.first, s.second, s.third,
985  d.first, d.second,
986  func,
987  border);
988 }
989 
990 template <class T1, class S1,
991  class T2, class S2,
992  class ProcessingFunctor>
993 inline void applyWindowFunction(MultiArrayView<2, T1, S1> const & src,
994  MultiArrayView<2, T2, S2> dest,
995  ProcessingFunctor func,
996  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
997 {
998  vigra_precondition(src.shape() == dest.shape(),
999  "vigra::applyWindowFunction(): shape mismatch between input and output.");
1000  applyWindowFunction(srcImageRange(src),
1001  destImage(dest),
1002  func,
1003  border);
1004 }
1005 
1006 //@}
1007 
1008 } //end of namespace vigra
1009 
1010 #endif //VIGRA_APPLYWINDOWFUNCTION_HXX
void initImage(...)
Write a value to every pixel in an image or rectangular ROI.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
void copyImage(...)
Copy source image into destination image.
void reflectImage(...)
Reflect image horizontally or vertically.
void applyWindowFunction(...)
Apply a window function to each pixels of a given image.

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)