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

applywindowfunction.hxx |

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
159 doxygen_overloaded_function(template <...> void applyWindowFunction)
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
vigra::initImage
void initImage(...)
Write a value to every pixel in an image or rectangular ROI.
vigra::doxygen_overloaded_function
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
vigra::copyImage
void copyImage(...)
Copy source image into destination image.
vigra::reflectImage
void reflectImage(...)
Reflect image horizontally or vertically.
vigra::applyWindowFunction
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)