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

stdconvolution.hxx
1/************************************************************************/
2/* */
3/* Copyright 1998-2002 by Ullrich Koethe */
4/* */
5/* This file is part of the VIGRA computer vision library. */
6/* The VIGRA Website is */
7/* http://hci.iwr.uni-heidelberg.de/vigra/ */
8/* Please direct questions, bug reports, and contributions to */
9/* ullrich.koethe@iwr.uni-heidelberg.de or */
10/* vigra@informatik.uni-hamburg.de */
11/* */
12/* Permission is hereby granted, free of charge, to any person */
13/* obtaining a copy of this software and associated documentation */
14/* files (the "Software"), to deal in the Software without */
15/* restriction, including without limitation the rights to use, */
16/* copy, modify, merge, publish, distribute, sublicense, and/or */
17/* sell copies of the Software, and to permit persons to whom the */
18/* Software is furnished to do so, subject to the following */
19/* conditions: */
20/* */
21/* The above copyright notice and this permission notice shall be */
22/* included in all copies or substantial portions of the */
23/* Software. */
24/* */
25/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32/* OTHER DEALINGS IN THE SOFTWARE. */
33/* */
34/************************************************************************/
35
36
37#ifndef VIGRA_STDCONVOLUTION_HXX
38#define VIGRA_STDCONVOLUTION_HXX
39
40#include <cmath>
41#include "stdimage.hxx"
42#include "bordertreatment.hxx"
43#include "separableconvolution.hxx"
44#include "utilities.hxx"
45#include "sized_int.hxx"
46#include "multi_iterator.hxx"
47#include "multi_shape.hxx"
48
49namespace vigra {
50
51template <class ARITHTYPE>
52class Kernel2D;
53
54/** \addtogroup ConvolutionFilters
55*/
56//@{
57
58 // documentation is in convolution.hxx
59template <class SrcIterator, class SrcAccessor,
60 class DestIterator, class DestAccessor,
61 class KernelIterator, class KernelAccessor>
62void convolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
63 DestIterator dest_ul, DestAccessor dest_acc,
64 KernelIterator ki, KernelAccessor ak,
65 Diff2D kul, Diff2D klr, BorderTreatmentMode border)
66{
67 vigra_precondition((border == BORDER_TREATMENT_CLIP ||
68 border == BORDER_TREATMENT_AVOID ||
69 border == BORDER_TREATMENT_REFLECT ||
70 border == BORDER_TREATMENT_REPEAT ||
71 border == BORDER_TREATMENT_WRAP ||
72 border == BORDER_TREATMENT_ZEROPAD),
73 "convolveImage():\n"
74 " Border treatment must be one of follow treatments:\n"
75 " - BORDER_TREATMENT_CLIP\n"
76 " - BORDER_TREATMENT_AVOID\n"
77 " - BORDER_TREATMENT_REFLECT\n"
78 " - BORDER_TREATMENT_REPEAT\n"
79 " - BORDER_TREATMENT_WRAP\n"
80 " - BORDER_TREATMENT_ZEROPAD\n");
81
82 vigra_precondition(kul.x <= 0 && kul.y <= 0,
83 "convolveImage(): coordinates of "
84 "kernel's upper left must be <= 0.");
85 vigra_precondition(klr.x >= 0 && klr.y >= 0,
86 "convolveImage(): coordinates of "
87 "kernel's lower right must be >= 0.");
88
89 // use traits to determine SumType as to prevent possible overflow
90 typedef typename
91 PromoteTraits<typename SrcAccessor::value_type,
92 typename KernelAccessor::value_type>::Promote SumType;
93 typedef typename
94 NumericTraits<typename KernelAccessor::value_type>::RealPromote KernelSumType;
95 typedef typename DestAccessor::value_type DestType;
96
97 // calculate width and height of the image
98 int w = src_lr.x - src_ul.x;
99 int h = src_lr.y - src_ul.y;
100
101 // calculate width and height of the kernel
102 int kernel_width = klr.x - kul.x + 1;
103 int kernel_height = klr.y - kul.y + 1;
104
105 vigra_precondition(w >= std::max(klr.x, -kul.x) + 1 && h >= std::max(klr.y, -kul.y) + 1,
106 "convolveImage(): kernel larger than image.");
107
108 KernelSumType norm = KernelSumType();
109 if(border == BORDER_TREATMENT_CLIP)
110 {
111 // calculate the sum of the kernel elements for renormalization
112 KernelIterator yk = ki + klr;
113
114 // determine sum within kernel (= norm)
115 for(int y = 0; y < kernel_height; ++y, --yk.y)
116 {
117 KernelIterator xk = yk;
118 for(int x = 0; x < kernel_width; ++x, --xk.x)
119 {
120 norm += ak(xk);
121 }
122 }
123 vigra_precondition(norm != NumericTraits<KernelSumType>::zero(),
124 "convolveImage(): Cannot use BORDER_TREATMENT_CLIP with a DC-free kernel");
125 }
126
127 DestIterator yd = dest_ul;
128 SrcIterator ys = src_ul;
129
130 // iterate over the interior part
131 for(int y=0; y<h; ++y, ++ys.y, ++yd.y)
132 {
133 // create x iterators
134 DestIterator xd(yd);
135 SrcIterator xs(ys);
136
137 for(int x=0; x < w; ++x, ++xs.x, ++xd.x)
138 {
139 // init the sum
140 SumType sum = NumericTraits<SumType>::zero();
141 KernelIterator ykernel = ki + klr;
142
143 if(x >= klr.x && y >= klr.y && x < w + kul.x && y < h + kul.y)
144 {
145 // kernel is entirely inside the image
146 SrcIterator yys = xs - klr;
147 SrcIterator yyend = xs - kul;
148
149 for(; yys.y <= yyend.y; ++yys.y, --ykernel.y)
150 {
151 typename SrcIterator::row_iterator xxs = yys.rowIterator();
152 typename SrcIterator::row_iterator xxe = xxs + kernel_width;
153 typename KernelIterator::row_iterator xkernel= ykernel.rowIterator();
154
155 for(; xxs < xxe; ++xxs, --xkernel)
156 {
157 sum += ak(xkernel) * src_acc(xxs);
158 }
159 }
160 }
161 else if(border == BORDER_TREATMENT_REPEAT)
162 {
163 Diff2D diff;
164 for(int yk = klr.y; yk >= kul.y; --yk, --ykernel.y)
165 {
166 diff.y = std::min(std::max(y - yk, 0), h-1);
167 typename KernelIterator::row_iterator xkernel = ykernel.rowIterator();
168
169 for(int xk = klr.x; xk >= kul.x; --xk, --xkernel)
170 {
171 diff.x = std::min(std::max(x - xk, 0), w-1);
172 sum += ak(xkernel) * src_acc(src_ul, diff);
173 }
174 }
175 }
176 else if(border == BORDER_TREATMENT_REFLECT)
177 {
178 Diff2D diff;
179 for(int yk = klr.y; yk >= kul.y; --yk , --ykernel.y)
180 {
181 diff.y = abs(y - yk);
182 if(diff.y >= h)
183 diff.y = 2*h - 2 - diff.y;
184 typename KernelIterator::row_iterator xkernel = ykernel.rowIterator();
185
186 for(int xk = klr.x; xk >= kul.x; --xk, --xkernel)
187 {
188 diff.x = abs(x - xk);
189 if(diff.x >= w)
190 diff.x = 2*w - 2 - diff.x;
191 sum += ak(xkernel) * src_acc(src_ul, diff);
192 }
193 }
194 }
195 else if(border == BORDER_TREATMENT_WRAP)
196 {
197 Diff2D diff;
198 for(int yk = klr.y; yk >= kul.y; --yk, --ykernel.y)
199 {
200 diff.y = (y - yk + h) % h;
201 typename KernelIterator::row_iterator xkernel = ykernel.rowIterator();
202
203 for(int xk = klr.x; xk >= kul.x; --xk, --xkernel)
204 {
205 diff.x = (x - xk + w) % w;
206 sum += ak(xkernel) * src_acc(src_ul, diff);
207 }
208 }
209 }
210 else if(border == BORDER_TREATMENT_CLIP)
211 {
212 KernelSumType ksum = NumericTraits<KernelSumType>::zero();
213 Diff2D diff;
214 for(int yk = klr.y; yk >= kul.y; --yk, --ykernel.y)
215 {
216 diff.y = y - yk;
217 if(diff.y < 0 || diff.y >= h)
218 continue;
219 typename KernelIterator::row_iterator xkernel = ykernel.rowIterator();
220
221 for(int xk = klr.x; xk >= kul.x; --xk, --xkernel)
222 {
223 diff.x = x - xk;
224 if(diff.x < 0 || diff.x >= w)
225 continue;
226 ksum += ak(xkernel);
227 sum += ak(xkernel) * src_acc(src_ul, diff);
228 }
229 }
230
231 sum *= norm / ksum;
232 }
233 else if(border == BORDER_TREATMENT_ZEROPAD)
234 {
235 Diff2D diff;
236 for(int yk = klr.y; yk >= kul.y; --yk, --ykernel.y)
237 {
238 diff.y = y - yk;
239 if(diff.y < 0 || diff.y >= h)
240 continue;
241 typename KernelIterator::row_iterator xkernel = ykernel.rowIterator();
242
243 for(int xk = klr.x; xk >= kul.x; --xk, --xkernel)
244 {
245 diff.x = x - xk;
246 if(diff.x < 0 || diff.x >= w)
247 continue;
248 sum += ak(xkernel) * src_acc(src_ul, diff);
249 }
250 }
251 }
252 else if(border == BORDER_TREATMENT_AVOID)
253 {
254 continue;
255 }
256
257 // store convolution result in destination pixel
258 dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(sum), xd);
259 }
260 }
261}
262
263template <class SrcIterator, class SrcAccessor,
264 class DestIterator, class DestAccessor,
265 class KernelIterator, class KernelAccessor>
266inline void
267convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
268 pair<DestIterator, DestAccessor> dest,
269 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
270 BorderTreatmentMode> kernel)
271{
272 convolveImage(src.first, src.second, src.third,
273 dest.first, dest.second,
274 kernel.first, kernel.second, kernel.third,
275 kernel.fourth, kernel.fifth);
276}
277
278template <class T1, class S1,
279 class T2, class S2,
280 class T3>
281inline void
282convolveImage(MultiArrayView<2, T1, S1> const & src,
283 MultiArrayView<2, T2, S2> dest,
284 Kernel2D<T3> const & kernel)
285{
286 vigra_precondition(src.shape() == dest.shape(),
287 "convolveImage(): shape mismatch between input and output.");
288 convolveImage(srcImageRange(src),
289 destImage(dest),
290 kernel2d(kernel));
291}
292
293/** \brief Performs a 2-dimensional normalized convolution, i.e. convolution with a mask image.
294
295 This functions computes
296 <a href ="http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/PIRODDI1/NormConv/NormConv.html">normalized
297 convolution</a> as defined in
298 Knutsson, H. and Westin, C-F.: <i>Normalized and differential convolution:
299 Methods for Interpolation and Filtering of incomplete and uncertain data</i>.
300 Proc. of the IEEE Conf. on Computer Vision and Pattern Recognition, 1993, 515-523.
301
302 The mask image must be binary and encodes which pixels of the original image
303 are valid. It is used as follows:
304 Only pixel under the mask are used in the calculations. Whenever a part of the
305 kernel lies outside the mask, it is ignored, and the kernel is renormalized to its
306 original norm (analogous to the CLIP \ref BorderTreatmentMode). Thus, a useful convolution
307 result is computed whenever <i>at least one valid pixel is within the current window</i>
308 Thus, destination pixels not under the mask still receive a value if they are <i>near</i>
309 the mask. Therefore, this algorithm is useful as an interpolator of sparse input data.
310 If you are only interested in the destination values under the mask, you can perform
311 a subsequent \ref copyImageIf().
312
313 The KernelIterator must point to the center of the kernel, and
314 the kernel's size is given by its upper left (x and y of distance <= 0) and
315 lower right (distance >= 0) corners. The image must always be larger than the
316 kernel. At those positions where the kernel does not completely fit
317 into the image, the specified \ref BorderTreatmentMode is
318 applied. Only BORDER_TREATMENT_CLIP and BORDER_TREATMENT_AVOID are currently
319 supported.
320
321 The images's pixel type (SrcAccessor::value_type) must be a
322 linear space over the kernel's value_type (KernelAccessor::value_type),
323 i.e. addition of source values, multiplication with kernel values,
324 and NumericTraits must be defined.
325 The kernel's value_type must be an algebraic field,
326 i.e. the arithmetic operations (+, -, *, /) and NumericTraits must
327 be defined.
328
329 <b> Declarations:</b>
330
331 pass 2D array views:
332 \code
333 namespace vigra {
334 template <class T1, class S1,
335 class T2, class S2,
336 class TM, class SM,
337 class T3>
338 void
339 normalizedConvolveImage(MultiArrayView<2, T1, S1> const & src,
340 MultiArrayView<2, TM, SM> const & mask,
341 MultiArrayView<2, T2, S2> dest,
342 Kernel2D<T3> const & kernel);
343 }
344 \endcode
345
346 \deprecatedAPI{normalizedConvolveImage}
347 pass \ref ImageIterators and \ref DataAccessors :
348 \code
349 namespace vigra {
350 template <class SrcIterator, class SrcAccessor,
351 class MaskIterator, class MaskAccessor,
352 class DestIterator, class DestAccessor,
353 class KernelIterator, class KernelAccessor>
354 void
355 normalizedConvolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
356 MaskIterator mul, MaskAccessor am,
357 DestIterator dest_ul, DestAccessor dest_acc,
358 KernelIterator ki, KernelAccessor ak,
359 Diff2D kul, Diff2D klr, BorderTreatmentMode border);
360 }
361 \endcode
362 use argument objects in conjunction with \ref ArgumentObjectFactories :
363 \code
364 namespace vigra {
365 template <class SrcIterator, class SrcAccessor,
366 class MaskIterator, class MaskAccessor,
367 class DestIterator, class DestAccessor,
368 class KernelIterator, class KernelAccessor>
369 void normalizedConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
370 pair<MaskIterator, MaskAccessor> mask,
371 pair<DestIterator, DestAccessor> dest,
372 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
373 BorderTreatmentMode> kernel);
374 }
375 \endcode
376 \deprecatedEnd
377
378 <b> Usage:</b>
379
380 <b>\#include</b> <vigra/stdconvolution.hxx><br>
381 Namespace: vigra
382
383 \code
384 MultiArray<2, float> src(w,h), dest(w,h);
385 MultiArray<2, unsigned char> mask(w,h);
386 ...
387 // define 3x3 binomial filter
388 vigra::Kernel2D<float> binom;
389 binom.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and lower right
390 0.0625, 0.125, 0.0625,
391 0.125, 0.25, 0.125,
392 0.0625, 0.125, 0.0625;
393
394 normalizedConvolveImage(src, mask, dest, binom);
395 \endcode
396
397 \deprecatedUsage{normalizedConvolveImage}
398 \code
399 vigra::FImage src(w,h), dest(w,h);
400 vigra::CImage mask(w,h);
401 ...
402
403 // define 3x3 binomial filter
404 vigra::Kernel2D<float> binom;
405
406 binom.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and lower right
407 0.0625, 0.125, 0.0625,
408 0.125, 0.25, 0.125,
409 0.0625, 0.125, 0.0625;
410
411 vigra::normalizedConvolveImage(srcImageRange(src), maskImage(mask), destImage(dest), kernel2d(binom));
412 \endcode
413 <b> Required Interface:</b>
414 \code
415 ImageIterator src_ul, src_lr;
416 ImageIterator mul;
417 ImageIterator dest_ul;
418 ImageIterator ik;
419
420 SrcAccessor src_accessor;
421 MaskAccessor mask_accessor;
422 DestAccessor dest_accessor;
423 KernelAccessor kernel_accessor;
424
425 NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(src_ul);
426
427 s = s + s;
428 s = kernel_accessor(ik) * s;
429 s -= s;
430
431 if(mask_accessor(mul)) ...;
432
433 dest_accessor.set(
434 NumericTraits<DestAccessor::value_type>::fromRealPromote(s), dest_ul);
435
436 NumericTraits<KernelAccessor::value_type>::RealPromote k = kernel_accessor(ik);
437
438 k += k;
439 k -= k;
440 k = k / k;
441
442 \endcode
443 \deprecatedEnd
444
445 <b> Preconditions:</b>
446
447 <ul>
448 <li> The image must be longer than the kernel radius: <tt>w > std::max(kernel.lowerRight().x, -kernel.upperLeft().x)</tt> and
449 <tt>h > std::max(kernel.lowerRight().y, -kernel.upperLeft().y)</tt>.
450 <li> The sum of kernel elements must be != 0.
451 <li> <tt>border == BORDER_TREATMENT_CLIP || border == BORDER_TREATMENT_AVOID</tt>
452 </ul>
453*/
455
456template <class SrcIterator, class SrcAccessor,
457 class DestIterator, class DestAccessor,
458 class MaskIterator, class MaskAccessor,
459 class KernelIterator, class KernelAccessor>
460void
461normalizedConvolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
462 MaskIterator mul, MaskAccessor am,
463 DestIterator dest_ul, DestAccessor dest_acc,
464 KernelIterator ki, KernelAccessor ak,
465 Diff2D kul, Diff2D klr, BorderTreatmentMode border)
466{
467 vigra_precondition((border == BORDER_TREATMENT_CLIP ||
468 border == BORDER_TREATMENT_AVOID),
469 "normalizedConvolveImage(): "
470 "Border treatment must be BORDER_TREATMENT_CLIP or BORDER_TREATMENT_AVOID.");
471
472 vigra_precondition(kul.x <= 0 && kul.y <= 0,
473 "normalizedConvolveImage(): left borders must be <= 0.");
474 vigra_precondition(klr.x >= 0 && klr.y >= 0,
475 "normalizedConvolveImage(): right borders must be >= 0.");
476
477 // use traits to determine SumType as to prevent possible overflow
478 typedef typename
479 NumericTraits<typename SrcAccessor::value_type>::RealPromote SumType;
480 typedef typename
481 NumericTraits<typename KernelAccessor::value_type>::RealPromote KSumType;
482 typedef
483 NumericTraits<typename DestAccessor::value_type> DestTraits;
484
485 // calculate width and height of the image
486 int w = src_lr.x - src_ul.x;
487 int h = src_lr.y - src_ul.y;
488 int kernel_width = klr.x - kul.x + 1;
489 int kernel_height = klr.y - kul.y + 1;
490
491 int x,y;
492 int ystart = (border == BORDER_TREATMENT_AVOID) ? klr.y : 0;
493 int yend = (border == BORDER_TREATMENT_AVOID) ? h+kul.y : h;
494 int xstart = (border == BORDER_TREATMENT_AVOID) ? klr.x : 0;
495 int xend = (border == BORDER_TREATMENT_AVOID) ? w+kul.x : w;
496
497 // create y iterators
498 DestIterator yd = dest_ul + Diff2D(xstart, ystart);
499 SrcIterator ys = src_ul + Diff2D(xstart, ystart);
500 MaskIterator ym = mul + Diff2D(xstart, ystart);
501
502 KSumType norm = ak(ki);
503 int xx, yy;
504 KernelIterator yk = ki + klr;
505 for(yy=0; yy<kernel_height; ++yy, --yk.y)
506 {
507 KernelIterator xk = yk;
508
509 for(xx=0; xx<kernel_width; ++xx, --xk.x)
510 {
511 norm += ak(xk);
512 }
513 }
514 norm -= ak(ki);
515
516
517 for(y=ystart; y < yend; ++y, ++ys.y, ++yd.y, ++ym.y)
518 {
519 // create x iterators
520 DestIterator xd(yd);
521 SrcIterator xs(ys);
522 MaskIterator xm(ym);
523
524 for(x=xstart; x < xend; ++x, ++xs.x, ++xd.x, ++xm.x)
525 {
526 // how much of the kernel fits into the image ?
527 int x0, y0, x1, y1;
528
529 y0 = (y<klr.y) ? -y : -klr.y;
530 y1 = (h-y-1<-kul.y) ? h-y-1 : -kul.y;
531 x0 = (x<klr.x) ? -x : -klr.x;
532 x1 = (w-x-1<-kul.x) ? w-x-1 : -kul.x;
533
534 bool first = true;
535 // init the sum
536 SumType sum = NumericTraits<SumType>::zero();
537 KSumType ksum = NumericTraits<KSumType>::zero();
538
539 SrcIterator yys = xs + Diff2D(x0, y0);
540 MaskIterator yym = xm + Diff2D(x0, y0);
541 KernelIterator yk = ki - Diff2D(x0, y0);
542
543 int kernel_width, kernel_height;
544 kernel_width = x1 - x0 + 1;
545 kernel_height = y1 - y0 + 1;
546 for(yy=0; yy<kernel_height; ++yy, ++yys.y, --yk.y, ++yym.y)
547 {
548 typename SrcIterator::row_iterator xxs = yys.rowIterator();
549 typename SrcIterator::row_iterator xxend = xxs + kernel_width;
550 typename MaskIterator::row_iterator xxm = yym.rowIterator();
551 typename KernelIterator::row_iterator xk = yk.rowIterator();
552
553 for(xx=0; xxs < xxend; ++xxs, --xk, ++xxm)
554 {
555 if(!am(xxm)) continue;
556
557 if(first)
558 {
559 sum = detail::RequiresExplicitCast<SumType>::cast(ak(xk) * src_acc(xxs));
560 ksum = ak(xk);
561 first = false;
562 }
563 else
564 {
565 sum = detail::RequiresExplicitCast<SumType>::cast(sum + ak(xk) * src_acc(xxs));
566 ksum += ak(xk);
567 }
568 }
569 }
570 // store average in destination pixel
571 if(ksum != NumericTraits<KSumType>::zero())
572 {
573 dest_acc.set(DestTraits::fromRealPromote(
574 detail::RequiresExplicitCast<SumType>::cast((norm / ksum) * sum)), xd);
575 }
576 }
577 }
578}
579
580
581template <class SrcIterator, class SrcAccessor,
582 class DestIterator, class DestAccessor,
583 class MaskIterator, class MaskAccessor,
584 class KernelIterator, class KernelAccessor>
585inline void
586normalizedConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
587 pair<MaskIterator, MaskAccessor> mask,
588 pair<DestIterator, DestAccessor> dest,
589 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
590 BorderTreatmentMode> kernel)
591{
592 normalizedConvolveImage(src.first, src.second, src.third,
593 mask.first, mask.second,
594 dest.first, dest.second,
595 kernel.first, kernel.second, kernel.third,
596 kernel.fourth, kernel.fifth);
597}
598
599template <class T1, class S1,
600 class T2, class S2,
601 class TM, class SM,
602 class T3>
603inline void
604normalizedConvolveImage(MultiArrayView<2, T1, S1> const & src,
605 MultiArrayView<2, TM, SM> const & mask,
606 MultiArrayView<2, T2, S2> dest,
607 Kernel2D<T3> const & kernel)
608{
609 vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.shape(),
610 "normalizedConvolveImage(): shape mismatch between input and output.");
611 normalizedConvolveImage(srcImageRange(src),
612 maskImage(mask),
613 destImage(dest),
614 kernel2d(kernel));
615}
616
617/** \brief Deprecated name of 2-dimensional normalized convolution, i.e. convolution with a mask image.
618
619 See \ref normalizedConvolveImage() for documentation.
620
621 <b> Declarations:</b>
622
623 pass 2D array views:
624 \code
625 namespace vigra {
626 template <class SrcIterator, class SrcAccessor,
627 class MaskIterator, class MaskAccessor,
628 class DestIterator, class DestAccessor,
629 class KernelIterator, class KernelAccessor>
630 void
631 convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
632 MaskIterator mul, MaskAccessor am,
633 DestIterator dest_ul, DestAccessor dest_acc,
634 KernelIterator ki, KernelAccessor ak,
635 Diff2D kul, Diff2D klr, BorderTreatmentMode border);
636 }
637 \endcode
638
639 \deprecatedAPI{convolveImageWithMask}
640 pass \ref ImageIterators and \ref DataAccessors :
641 \code
642 namespace vigra {
643 template <class SrcIterator, class SrcAccessor,
644 class MaskIterator, class MaskAccessor,
645 class DestIterator, class DestAccessor,
646 class KernelIterator, class KernelAccessor>
647 void
648 convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
649 MaskIterator mul, MaskAccessor am,
650 DestIterator dest_ul, DestAccessor dest_acc,
651 KernelIterator ki, KernelAccessor ak,
652 Diff2D kul, Diff2D klr, BorderTreatmentMode border);
653 }
654 \endcode
655 use argument objects in conjunction with \ref ArgumentObjectFactories :
656 \code
657 namespace vigra {
658 template <class SrcIterator, class SrcAccessor,
659 class MaskIterator, class MaskAccessor,
660 class DestIterator, class DestAccessor,
661 class KernelIterator, class KernelAccessor>
662 void convolveImageWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
663 pair<MaskIterator, MaskAccessor> mask,
664 pair<DestIterator, DestAccessor> dest,
665 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
666 BorderTreatmentMode> kernel);
667 }
668 \endcode
669 \deprecatedEnd
670*/
672
673template <class SrcIterator, class SrcAccessor,
674 class DestIterator, class DestAccessor,
675 class MaskIterator, class MaskAccessor,
676 class KernelIterator, class KernelAccessor>
677inline void
678convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
679 MaskIterator mul, MaskAccessor am,
680 DestIterator dest_ul, DestAccessor dest_acc,
681 KernelIterator ki, KernelAccessor ak,
682 Diff2D kul, Diff2D klr, BorderTreatmentMode border)
683{
684 normalizedConvolveImage(src_ul, src_lr, src_acc,
685 mul, am,
686 dest_ul, dest_acc,
687 ki, ak, kul, klr, border);
688}
689
690template <class SrcIterator, class SrcAccessor,
691 class DestIterator, class DestAccessor,
692 class MaskIterator, class MaskAccessor,
693 class KernelIterator, class KernelAccessor>
694inline
696 triple<SrcIterator, SrcIterator, SrcAccessor> src,
697 pair<MaskIterator, MaskAccessor> mask,
698 pair<DestIterator, DestAccessor> dest,
699 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
700 BorderTreatmentMode> kernel)
701{
702 normalizedConvolveImage(src.first, src.second, src.third,
703 mask.first, mask.second,
704 dest.first, dest.second,
705 kernel.first, kernel.second, kernel.third,
706 kernel.fourth, kernel.fifth);
707}
708
709//@}
710
711/********************************************************/
712/* */
713/* Kernel2D */
714/* */
715/********************************************************/
716
717/** \brief Generic 2 dimensional convolution kernel.
718
719 This kernel may be used for convolution of 2 dimensional signals.
720
721 Convolution functions access the kernel via an ImageIterator
722 which they get by calling \ref center(). This iterator
723 points to the center of the kernel. The kernel's size is given by its upperLeft()
724 (upperLeft().x <= 0, upperLeft().y <= 0)
725 and lowerRight() (lowerRight().x >= 0, lowerRight().y >= 0) methods.
726 The desired border treatment mode is returned by borderTreatment().
727
728 The different init functions create a kernel with the specified
729 properties. The requirements for the kernel's value_type depend
730 on the init function used. At least NumericTraits must be defined.
731
732 <b> Usage:</b>
733
734 <b>\#include</b> <vigra/stdconvolution.hxx><br>
735 Namespace: vigra
736
737 \code
738 MultiArray<2, float> src(w,h), dest(w,h);
739 ...
740
741 // define horizontal Sobel filter
742 vigra::Kernel2D<float> sobel;
743 sobel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and lower right
744 0.125, 0.0, -0.125,
745 0.25, 0.0, -0.25,
746 0.125, 0.0, -0.125;
747
748 convolveImage(src, dest, sobel);
749 \endcode
750
751 <b> Required Interface:</b>
752
753 \code
754 value_type v = NumericTraits<value_type>::one();
755 \endcode
756
757 See also the init functions.
758*/
759template <class ARITHTYPE = double>
761{
762public:
763 /** the kernel's value type
764 */
765 typedef ARITHTYPE value_type;
766
767 /** 2D random access iterator over the kernel's values
768 */
770
771 /** const 2D random access iterator over the kernel's values
772 */
774
775 /** the kernel's accessor
776 */
778
779 /** the kernel's const accessor
780 */
782
783 struct InitProxy
784 {
785 typedef typename
787
788 InitProxy(Iterator i, int count, value_type & norm)
789 : iter_(i), base_(i),
790 count_(count), sum_(count),
791 norm_(norm)
792 {}
793
794 ~InitProxy()
795 noexcept(false)
796 {
797 vigra_precondition(count_ == 1 || count_ == sum_,
798 "Kernel2D::initExplicitly(): "
799 "Too few init values.");
800 }
801
802 InitProxy & operator,(value_type const & v)
803 {
804 if(count_ == sum_) norm_ = *iter_;
805
806 --count_;
807 vigra_precondition(count_ > 0,
808 "Kernel2D::initExplicitly(): "
809 "Too many init values.");
810
811 norm_ += v;
812
813 ++iter_;
814 *iter_ = v;
815
816 return *this;
817 }
818
819 Iterator iter_, base_;
820 int count_, sum_;
821 value_type & norm_;
822 };
823
824 static value_type one() { return NumericTraits<value_type>::one(); }
825
826 /** Default constructor.
827 Creates a kernel of size 1x1 which would copy the signal
828 unchanged.
829 */
831 : kernel_(1, 1, one()),
832 left_(0, 0),
833 right_(0, 0),
834 norm_(one()),
835 border_treatment_(BORDER_TREATMENT_REFLECT)
836 {}
837
838 /** Copy constructor.
839 */
841 : kernel_(k.kernel_),
842 left_(k.left_),
843 right_(k.right_),
844 norm_(k.norm_),
845 border_treatment_(k.border_treatment_)
846 {}
847
848 /** Copy assignment.
849 */
851 {
852 if(this != &k)
853 {
854 kernel_ = k.kernel_;
855 left_ = k.left_;
856 right_ = k.right_;
857 norm_ = k.norm_;
858 border_treatment_ = k.border_treatment_;
859 }
860 return *this;
861 }
862
863 /** Initialization.
864 This initializes the kernel with the given constant. The norm becomes
865 v*width()*height().
866
867 Instead of a single value an initializer list of length width()*height()
868 can be used like this:
869
870 \code
871 vigra::Kernel2D<float> binom;
872
873 binom.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) =
874 0.0625, 0.125, 0.0625,
875 0.125, 0.25, 0.125,
876 0.0625, 0.125, 0.0625;
877 \endcode
878
879 In this case, the norm will be set to the sum of the init values.
880 An initializer list of wrong length will result in a run-time error.
881 */
882 InitProxy operator=(value_type const & v)
883 {
884 int size = (right_.x - left_.x + 1) *
885 (right_.y - left_.y + 1);
886 kernel_ = v;
887 norm_ = (double)size*v;
888
889 return InitProxy(kernel_.begin(), size, norm_);
890 }
891
892 /** Destructor.
893 */
895 {}
896
897 /** Init the 2D kernel as the cartesian product of two 1D kernels
898 of type \ref Kernel1D. The norm becomes the product of the two original
899 norms.
900
901 <b> Required Interface:</b>
902
903 The kernel's value_type must be a linear algebra.
904
905 \code
906 vigra::Kernel2D<...>::value_type v;
907 v = v * v;
908 \endcode
909 */
911 Kernel1D<value_type> const & ky)
912 {
913 left_ = Diff2D(kx.left(), ky.left());
914 right_ = Diff2D(kx.right(), ky.right());
915 int w = right_.x - left_.x + 1;
916 int h = right_.y - left_.y + 1;
917 kernel_.resize(w, h);
918
919 norm_ = kx.norm() * ky.norm();
920
921 typedef typename Kernel1D<value_type>::const_iterator KIter;
923
924 KIter kiy = ky.center() + left_.y;
925 Iterator iy = center() + left_;
926
927 for(int y=left_.y; y<=right_.y; ++y, ++kiy, ++iy.y)
928 {
929 KIter kix = kx.center() + left_.x;
930 Iterator ix = iy;
931 for(int x=left_.x; x<=right_.x; ++x, ++kix, ++ix.x)
932 {
933 *ix = ka(kix) * ka(kiy);
934 }
935 }
936 }
937
938 /** Init the 2D kernel as the cartesian product of two 1D kernels
939 given explicitly by iterators and sizes. The norm becomes the
940 sum of the resulting kernel values.
941
942 <b> Required Interface:</b>
943
944 The kernel's value_type must be a linear algebra.
945
946 \code
947 vigra::Kernel2D<...>::value_type v;
948 v = v * v;
949 v += v;
950 \endcode
951
952 <b> Preconditions:</b>
953
954 \code
955 xleft <= 0;
956 xright >= 0;
957 yleft <= 0;
958 yright >= 0;
959 \endcode
960 */
961 template <class KernelIterator>
962 void initSeparable(KernelIterator kxcenter, int xleft, int xright,
963 KernelIterator kycenter, int yleft, int yright)
964 {
965 vigra_precondition(xleft <= 0 && yleft <= 0,
966 "Kernel2D::initSeparable(): left borders must be <= 0.");
967 vigra_precondition(xright >= 0 && yright >= 0,
968 "Kernel2D::initSeparable(): right borders must be >= 0.");
969
970 left_ = Point2D(xleft, yleft);
971 right_ = Point2D(xright, yright);
972
973 int w = right_.x - left_.x + 1;
974 int h = right_.y - left_.y + 1;
975 kernel_.resize(w, h);
976
977 KernelIterator kiy = kycenter + left_.y;
978 Iterator iy = center() + left_;
979
980 for(int y=left_.y; y<=right_.y; ++y, ++kiy, ++iy.y)
981 {
982 KernelIterator kix = kxcenter + left_.x;
983 Iterator ix = iy;
984 for(int x=left_.x; x<=right_.x; ++x, ++kix, ++ix.x)
985 {
986 *ix = *kix * *kiy;
987 }
988 }
989
990 typename BasicImage<value_type>::iterator i = kernel_.begin();
991 typename BasicImage<value_type>::iterator iend = kernel_.end();
992 norm_ = *i;
993 ++i;
994
995 for(; i!= iend; ++i)
996 {
997 norm_ += *i;
998 }
999 }
1000
1001 /** Init as a 2D box filter with given radius.
1002 */
1003 void initAveraging(int radius)
1004 {
1006 avg.initAveraging(radius);
1007 return initSeparable(avg, avg);
1008 }
1009
1010 /** Init as a 2D Gaussian function with given standard deviation and norm.
1011 */
1012 void initGaussian(double std_dev, value_type norm)
1013 {
1015 gauss.initGaussian(std_dev, norm);
1016 return initSeparable(gauss, gauss);
1017 }
1018
1019 /** Init as a 2D Gaussian function with given standard deviation and unit norm.
1020 */
1021 void initGaussian(double std_dev)
1022 {
1023 return initGaussian(std_dev, NumericTraits<value_type>::one());
1024 }
1025
1026 /** Init the 2D kernel as a circular averaging filter. The norm will be
1027 calculated as
1028 <TT>NumericTraits<value_type>::one() / (number of non-zero kernel values)</TT>.
1029 The kernel's value_type must be a linear space.
1030
1031 <b> Required Interface:</b>
1032
1033 \code
1034 value_type v = vigra::NumericTraits<value_type>::one();
1035
1036 double d;
1037 v = d * v;
1038 \endcode
1039
1040 <b> Precondition:</b>
1041
1042 \code
1043 radius > 0;
1044 \endcode
1045 */
1046 void initDisk(int radius)
1047 {
1048 vigra_precondition(radius > 0,
1049 "Kernel2D::initDisk(): radius must be > 0.");
1050
1051 left_ = Point2D(-radius, -radius);
1052 right_ = Point2D(radius, radius);
1053 int w = right_.x - left_.x + 1;
1054 int h = right_.y - left_.y + 1;
1055 kernel_.resize(w, h);
1056 norm_ = NumericTraits<value_type>::one();
1057
1058 kernel_ = NumericTraits<value_type>::zero();
1059 double count = 0.0;
1060
1061 Iterator k = center();
1062 double r2 = (double)radius*radius;
1063
1064 int i;
1065 for(i=0; i<= radius; ++i)
1066 {
1067 double r = (double) i - 0.5;
1068 int w = (int)(VIGRA_CSTD::sqrt(r2 - r*r) + 0.5);
1069 for(int j=-w; j<=w; ++j)
1070 {
1071 k(j, i) = NumericTraits<value_type>::one();
1072 k(j, -i) = NumericTraits<value_type>::one();
1073 count += (i != 0) ? 2.0 : 1.0;
1074 }
1075 }
1076
1077 count = 1.0 / count;
1078
1079 for(int y=-radius; y<=radius; ++y)
1080 {
1081 for(int x=-radius; x<=radius; ++x)
1082 {
1083 k(x,y) = count * k(x,y);
1084 }
1085 }
1086 }
1087
1088 /** Init the kernel by an explicit initializer list.
1089 The upper left and lower right corners (inclusive) of the kernel must be passed
1090 either as <tt>Shape2</tt> or <tt>Diff2D</tt> objects. A comma-separated initializer
1091 list for the kernel's weights is given after the assignment operator like this:
1092
1093 \code
1094 // define horizontal Sobel filter
1095 vigra::Kernel2D<float> sobel;
1096
1097 sobel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) =
1098 0.125, 0.0, -0.125,
1099 0.25, 0.0, -0.25,
1100 0.125, 0.0, -0.125;
1101 \endcode
1102
1103 The norm is set to the sum of the initializer values. If the wrong number of
1104 values is given, a run-time error results. It is, however, possible to give
1105 just one initializer. This creates an averaging filter with the given constant:
1106
1107 \code
1108 vigra::Kernel2D<float> average3x3;
1109
1110 average3x3.initExplicitly(Shape2(-1,-1), Shape2(1,1)) = 1.0/9.0;
1111 \endcode
1112
1113 Here, the norm is set to value*width()*height().
1114
1115 <b> Preconditions:</b>
1116
1117 \code
1118 1. upperleft.x <= 0;
1119 2. upperleft.y <= 0;
1120 3. lowerright.x >= 0;
1121 4. lowerright.y >= 0;
1122 5. the number of values in the initializer list
1123 is 1 or equals the size of the kernel.
1124 \endcode
1125 */
1126 Kernel2D & initExplicitly(Shape2 const & upperleft, Shape2 const & lowerright)
1127 {
1128 vigra_precondition(upperleft[0] <= 0 && upperleft[1] <= 0,
1129 "Kernel2D::initExplicitly(): left borders must be <= 0.");
1130 vigra_precondition(lowerright[0] >= 0 && lowerright[1] >= 0,
1131 "Kernel2D::initExplicitly(): right borders must be >= 0.");
1132
1133 left_ = Point2D(upperleft[0], upperleft[1]);
1134 right_ = Point2D(lowerright[0], lowerright[1]);
1135
1136 int w = right_.x - left_.x + 1;
1137 int h = right_.y - left_.y + 1;
1138 kernel_.resize(w, h);
1139
1140 return *this;
1141 }
1142
1143 Kernel2D & initExplicitly(Diff2D const & upperleft, Diff2D const & lowerright)
1144 {
1145 return initExplicitly(Shape2(upperleft), Shape2(lowerright));
1146 }
1147
1148 /** Init the kernel by providing a BasicImage with the kernel values.
1149
1150 The kernel's origin is placed at the center of the given image.
1151 The norm is set to the sum of the image values.
1152
1153 <b> Preconditions:</b>
1154
1155 odd image width and height;
1156 */
1158 {
1159 vigra_precondition(image.width() % 2 != 0 && image.height() % 2 != 0,
1160 "Kernel2D::initExplicitly(): kernel sizes must be odd.");
1161
1162 left_ = Point2D((image.width() - 1) / -2, (image.height() - 1) / -2);
1163 right_ = Point2D((image.width() - 1) / 2, (image.height() - 1) / 2);
1164
1165 norm_ = 0;
1166 for (auto iter = image.begin(); iter != image.end(); ++iter)
1167 {
1168 norm_ += *iter;
1169 }
1170
1171 kernel_ = image;
1172
1173 return *this;
1174 }
1175
1176 /** Coordinates of the upper left corner of the kernel.
1177 */
1178 Point2D upperLeft() const { return left_; }
1179
1180 /** Coordinates of the lower right corner of the kernel.
1181 */
1182 Point2D lowerRight() const { return right_; }
1183
1184 /** Width of the kernel.
1185 */
1186 int width() const { return right_.x - left_.x + 1; }
1187
1188 /** Height of the kernel.
1189 */
1190 int height() const { return right_.y - left_.y + 1; }
1191
1192 /** ImageIterator that points to the center of the kernel (coordinate (0,0)).
1193 */
1194 Iterator center() { return kernel_.upperLeft() - left_; }
1195
1196 /** ImageIterator that points to the center of the kernel (coordinate (0,0)).
1197 */
1198 ConstIterator center() const { return kernel_.upperLeft() - left_; }
1199
1200 /** Access kernel entry at given position.
1201 */
1202 value_type & operator()(int x, int y)
1203 { return kernel_[Diff2D(x,y) - left_]; }
1204
1205 /** Read kernel entry at given position.
1206 */
1207 value_type operator()(int x, int y) const
1208 { return kernel_[Diff2D(x,y) - left_]; }
1209
1210 /** Access kernel entry at given position.
1211 */
1213 { return kernel_[d - left_]; }
1214
1215 /** Read kernel entry at given position.
1216 */
1218 { return kernel_[d - left_]; }
1219
1220 /** Norm of the kernel (i.e. sum of its elements).
1221 */
1222 value_type norm() const { return norm_; }
1223
1224 /** The kernels default accessor.
1225 */
1227
1228 /** The kernels default const accessor.
1229 */
1231
1232 /** Normalize the kernel to the given value. (The norm is the sum of all kernel
1233 elements.) The kernel's value_type must be a division algebra or
1234 algebraic field.
1235
1236 <b> Required Interface:</b>
1237
1238 \code
1239 value_type v = vigra::NumericTraits<value_type>::one(); // if norm is not
1240 // given explicitly
1241
1242 v += v;
1243 v = v * v;
1244 v = v / v;
1245 \endcode
1246 */
1248 {
1249 typename BasicImage<value_type>::iterator i = kernel_.begin();
1250 typename BasicImage<value_type>::iterator iend = kernel_.end();
1251 typename NumericTraits<value_type>::RealPromote sum = *i;
1252 ++i;
1253
1254 for(; i!= iend; ++i)
1255 {
1256 sum += *i;
1257 }
1258
1259 sum = norm / sum;
1260 i = kernel_.begin();
1261 for(; i != iend; ++i)
1262 {
1263 *i = *i * sum;
1264 }
1265
1266 norm_ = norm;
1267 }
1268
1269 /** Normalize the kernel to norm 1.
1270 */
1272 {
1273 normalize(one());
1274 }
1275
1276 /** current border treatment mode
1277 */
1278 BorderTreatmentMode borderTreatment() const
1279 { return border_treatment_; }
1280
1281 /** Set border treatment mode.
1282 Only <TT>BORDER_TREATMENT_CLIP</TT> and <TT>BORDER_TREATMENT_AVOID</TT> are currently
1283 allowed.
1284 */
1285 void setBorderTreatment( BorderTreatmentMode new_mode)
1286 {
1287 vigra_precondition((new_mode == BORDER_TREATMENT_CLIP ||
1288 new_mode == BORDER_TREATMENT_AVOID ||
1289 new_mode == BORDER_TREATMENT_REFLECT ||
1290 new_mode == BORDER_TREATMENT_REPEAT ||
1291 new_mode == BORDER_TREATMENT_WRAP),
1292 "convolveImage():\n"
1293 " Border treatment must be one of follow treatments:\n"
1294 " - BORDER_TREATMENT_CLIP\n"
1295 " - BORDER_TREATMENT_AVOID\n"
1296 " - BORDER_TREATMENT_REFLECT\n"
1297 " - BORDER_TREATMENT_REPEAT\n"
1298 " - BORDER_TREATMENT_WRAP\n");
1299
1300 border_treatment_ = new_mode;
1301 }
1302
1303
1304private:
1305 BasicImage<value_type> kernel_;
1306 Point2D left_, right_;
1307 value_type norm_;
1308 BorderTreatmentMode border_treatment_;
1309};
1310
1311/**************************************************************/
1312/* */
1313/* Argument object factories for Kernel2D */
1314/* */
1315/* (documentation: see vigra/convolution.hxx) */
1316/* */
1317/**************************************************************/
1318
1319template <class KernelIterator, class KernelAccessor>
1320inline
1321tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D, BorderTreatmentMode>
1322kernel2d(KernelIterator ik, KernelAccessor ak, Diff2D kul, Diff2D klr,
1323 BorderTreatmentMode border)
1324
1325{
1326 return
1327 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D, BorderTreatmentMode> (
1328 ik, ak, kul, klr, border);
1329}
1330
1331template <class T>
1332inline
1333tuple5<typename Kernel2D<T>::ConstIterator,
1335 Diff2D, Diff2D, BorderTreatmentMode>
1336kernel2d(Kernel2D<T> const & k)
1337
1338{
1339 return
1340 tuple5<typename Kernel2D<T>::ConstIterator,
1342 Diff2D, Diff2D, BorderTreatmentMode>(
1343 k.center(),
1344 k.accessor(),
1345 k.upperLeft(), k.lowerRight(),
1346 k.borderTreatment());
1347}
1348
1349template <class T>
1350inline
1351tuple5<typename Kernel2D<T>::ConstIterator,
1353 Diff2D, Diff2D, BorderTreatmentMode>
1354kernel2d(Kernel2D<T> const & k, BorderTreatmentMode border)
1355
1356{
1357 return
1358 tuple5<typename Kernel2D<T>::ConstIterator,
1360 Diff2D, Diff2D, BorderTreatmentMode>(
1361 k.center(),
1362 k.accessor(),
1363 k.upperLeft(), k.lowerRight(),
1364 border);
1365}
1366
1367
1368} // namespace vigra
1369
1370#endif // VIGRA_STDCONVOLUTION_HXX
Fundamental class template for images.
Definition: basicimage.hxx:476
std::ptrdiff_t height() const
Definition: basicimage.hxx:847
void resize(std::ptrdiff_t width, std::ptrdiff_t height)
Definition: basicimage.hxx:778
std::ptrdiff_t width() const
Definition: basicimage.hxx:840
iterator end()
Definition: basicimage.hxx:974
iterator begin()
Definition: basicimage.hxx:965
traverser upperLeft()
Definition: basicimage.hxx:925
Two dimensional difference vector.
Definition: diff2d.hxx:186
int y
Definition: diff2d.hxx:392
int x
Definition: diff2d.hxx:385
Generic 1 dimensional convolution kernel.
Definition: separableconvolution.hxx:1367
int right() const
Definition: separableconvolution.hxx:2153
value_type norm() const
Definition: separableconvolution.hxx:2171
void initGaussian(double std_dev, value_type norm, double windowRatio=0.0)
Definition: separableconvolution.hxx:2249
InternalVector::const_iterator const_iterator
Definition: separableconvolution.hxx:1393
void initAveraging(int radius, value_type norm)
Definition: separableconvolution.hxx:2480
int left() const
Definition: separableconvolution.hxx:2149
iterator center()
Definition: separableconvolution.hxx:2119
Generic 2 dimensional convolution kernel.
Definition: stdconvolution.hxx:761
BasicImage< value_type >::ConstAccessor ConstAccessor
Definition: stdconvolution.hxx:781
Kernel2D & initExplicitly(BasicImage< value_type > const &image)
Definition: stdconvolution.hxx:1157
Kernel2D & operator=(Kernel2D const &k)
Definition: stdconvolution.hxx:850
void initGaussian(double std_dev, value_type norm)
Definition: stdconvolution.hxx:1012
value_type & operator()(int x, int y)
Definition: stdconvolution.hxx:1202
value_type norm() const
Definition: stdconvolution.hxx:1222
value_type operator[](Diff2D const &d) const
Definition: stdconvolution.hxx:1217
InitProxy operator=(value_type const &v)
Definition: stdconvolution.hxx:882
void initSeparable(KernelIterator kxcenter, int xleft, int xright, KernelIterator kycenter, int yleft, int yright)
Definition: stdconvolution.hxx:962
BorderTreatmentMode borderTreatment() const
Definition: stdconvolution.hxx:1278
Point2D upperLeft() const
Definition: stdconvolution.hxx:1178
value_type & operator[](Diff2D const &d)
Definition: stdconvolution.hxx:1212
ConstIterator center() const
Definition: stdconvolution.hxx:1198
void setBorderTreatment(BorderTreatmentMode new_mode)
Definition: stdconvolution.hxx:1285
ConstAccessor accessor() const
Definition: stdconvolution.hxx:1230
void initSeparable(Kernel1D< value_type > const &kx, Kernel1D< value_type > const &ky)
Definition: stdconvolution.hxx:910
Point2D lowerRight() const
Definition: stdconvolution.hxx:1182
~Kernel2D()
Definition: stdconvolution.hxx:894
BasicImage< value_type >::traverser Iterator
Definition: stdconvolution.hxx:769
Kernel2D(Kernel2D const &k)
Definition: stdconvolution.hxx:840
void initAveraging(int radius)
Definition: stdconvolution.hxx:1003
Iterator center()
Definition: stdconvolution.hxx:1194
BasicImage< value_type >::const_traverser ConstIterator
Definition: stdconvolution.hxx:773
void initDisk(int radius)
Definition: stdconvolution.hxx:1046
value_type operator()(int x, int y) const
Definition: stdconvolution.hxx:1207
ARITHTYPE value_type
Definition: stdconvolution.hxx:765
void normalize(value_type norm)
Definition: stdconvolution.hxx:1247
void initGaussian(double std_dev)
Definition: stdconvolution.hxx:1021
Accessor accessor()
Definition: stdconvolution.hxx:1226
void normalize()
Definition: stdconvolution.hxx:1271
int height() const
Definition: stdconvolution.hxx:1190
int width() const
Definition: stdconvolution.hxx:1186
Kernel2D & initExplicitly(Shape2 const &upperleft, Shape2 const &lowerright)
Definition: stdconvolution.hxx:1126
BasicImage< value_type >::Accessor Accessor
Definition: stdconvolution.hxx:777
Kernel2D()
Definition: stdconvolution.hxx:830
Two dimensional point or position.
Definition: diff2d.hxx:593
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:134
void normalizedConvolveImage(...)
Performs a 2-dimensional normalized convolution, i.e. convolution with a mask image.
void mul(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
multiplication with enforced result type.
Definition: fixedpoint.hxx:605
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude)
Definition: fftw3.hxx:1037
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition: tinyvector.hxx:2073
void convolveImageWithMask(...)
Deprecated name of 2-dimensional normalized convolution, i.e. convolution with a mask image.
doxygen_overloaded_function(template<... > void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
void convolveImage(...)
Convolve an image with the given kernel(s).

© 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