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

stdconvolution.hxx VIGRA

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 
49 namespace vigra {
50 
51 template <class ARITHTYPE>
52 class Kernel2D;
53 
54 /** \addtogroup CommonConvolutionFilters
55 */
56 //@{
57 
58  // documentation is in convolution.hxx
59 template <class SrcIterator, class SrcAccessor,
60  class DestIterator, class DestAccessor,
61  class KernelIterator, class KernelAccessor>
62 void 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 
263 template <class SrcIterator, class SrcAccessor,
264  class DestIterator, class DestAccessor,
265  class KernelIterator, class KernelAccessor>
266 inline void
267 convolveImage(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 
278 template <class T1, class S1,
279  class T2, class S2,
280  class T3>
281 inline void
282 convolveImage(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 */
454 doxygen_overloaded_function(template <...> void normalizedConvolveImage)
455 
456 template <class SrcIterator, class SrcAccessor,
457  class DestIterator, class DestAccessor,
458  class MaskIterator, class MaskAccessor,
459  class KernelIterator, class KernelAccessor>
460 void
461 normalizedConvolveImage(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 
581 template <class SrcIterator, class SrcAccessor,
582  class DestIterator, class DestAccessor,
583  class MaskIterator, class MaskAccessor,
584  class KernelIterator, class KernelAccessor>
585 inline void
586 normalizedConvolveImage(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 
599 template <class T1, class S1,
600  class T2, class S2,
601  class TM, class SM,
602  class T3>
603 inline void
604 normalizedConvolveImage(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 */
671 doxygen_overloaded_function(template <...> void convolveImageWithMask)
672 
673 template <class SrcIterator, class SrcAccessor,
674  class DestIterator, class DestAccessor,
675  class MaskIterator, class MaskAccessor,
676  class KernelIterator, class KernelAccessor>
677 inline void
678 convolveImageWithMask(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 
690 template <class SrcIterator, class SrcAccessor,
691  class DestIterator, class DestAccessor,
692  class MaskIterator, class MaskAccessor,
693  class KernelIterator, class KernelAccessor>
694 inline
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 */
759 template <class ARITHTYPE = double>
760 class Kernel2D
761 {
762 public:
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  {
796  vigra_precondition(count_ == 1 || count_ == sum_,
797  "Kernel2D::initExplicitly(): "
798  "Too few init values.");
799  }
800 
801  InitProxy & operator,(value_type const & v)
802  {
803  if(count_ == sum_) norm_ = *iter_;
804 
805  --count_;
806  vigra_precondition(count_ > 0,
807  "Kernel2D::initExplicitly(): "
808  "Too many init values.");
809 
810  norm_ += v;
811 
812  ++iter_;
813  *iter_ = v;
814 
815  return *this;
816  }
817 
818  Iterator iter_, base_;
819  int count_, sum_;
820  value_type & norm_;
821  };
822 
823  static value_type one() { return NumericTraits<value_type>::one(); }
824 
825  /** Default constructor.
826  Creates a kernel of size 1x1 which would copy the signal
827  unchanged.
828  */
830  : kernel_(1, 1, one()),
831  left_(0, 0),
832  right_(0, 0),
833  norm_(one()),
834  border_treatment_(BORDER_TREATMENT_REFLECT)
835  {}
836 
837  /** Copy constructor.
838  */
839  Kernel2D(Kernel2D const & k)
840  : kernel_(k.kernel_),
841  left_(k.left_),
842  right_(k.right_),
843  norm_(k.norm_),
844  border_treatment_(k.border_treatment_)
845  {}
846 
847  /** Copy assignment.
848  */
850  {
851  if(this != &k)
852  {
853  kernel_ = k.kernel_;
854  left_ = k.left_;
855  right_ = k.right_;
856  norm_ = k.norm_;
857  border_treatment_ = k.border_treatment_;
858  }
859  return *this;
860  }
861 
862  /** Initialization.
863  This initializes the kernel with the given constant. The norm becomes
864  v*width()*height().
865 
866  Instead of a single value an initializer list of length width()*height()
867  can be used like this:
868 
869  \code
870  vigra::Kernel2D<float> binom;
871 
872  binom.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) =
873  0.0625, 0.125, 0.0625,
874  0.125, 0.25, 0.125,
875  0.0625, 0.125, 0.0625;
876  \endcode
877 
878  In this case, the norm will be set to the sum of the init values.
879  An initializer list of wrong length will result in a run-time error.
880  */
881  InitProxy operator=(value_type const & v)
882  {
883  int size = (right_.x - left_.x + 1) *
884  (right_.y - left_.y + 1);
885  kernel_ = v;
886  norm_ = (double)size*v;
887 
888  return InitProxy(kernel_.begin(), size, norm_);
889  }
890 
891  /** Destructor.
892  */
894  {}
895 
896  /** Init the 2D kernel as the cartesian product of two 1D kernels
897  of type \ref Kernel1D. The norm becomes the product of the two original
898  norms.
899 
900  <b> Required Interface:</b>
901 
902  The kernel's value_type must be a linear algebra.
903 
904  \code
905  vigra::Kernel2D<...>::value_type v;
906  v = v * v;
907  \endcode
908  */
910  Kernel1D<value_type> const & ky)
911  {
912  left_ = Diff2D(kx.left(), ky.left());
913  right_ = Diff2D(kx.right(), ky.right());
914  int w = right_.x - left_.x + 1;
915  int h = right_.y - left_.y + 1;
916  kernel_.resize(w, h);
917 
918  norm_ = kx.norm() * ky.norm();
919 
920  typedef typename Kernel1D<value_type>::const_iterator KIter;
921  typename Kernel1D<value_type>::Accessor ka;
922 
923  KIter kiy = ky.center() + left_.y;
924  Iterator iy = center() + left_;
925 
926  for(int y=left_.y; y<=right_.y; ++y, ++kiy, ++iy.y)
927  {
928  KIter kix = kx.center() + left_.x;
929  Iterator ix = iy;
930  for(int x=left_.x; x<=right_.x; ++x, ++kix, ++ix.x)
931  {
932  *ix = ka(kix) * ka(kiy);
933  }
934  }
935  }
936 
937  /** Init the 2D kernel as the cartesian product of two 1D kernels
938  given explicitly by iterators and sizes. The norm becomes the
939  sum of the resulting kernel values.
940 
941  <b> Required Interface:</b>
942 
943  The kernel's value_type must be a linear algebra.
944 
945  \code
946  vigra::Kernel2D<...>::value_type v;
947  v = v * v;
948  v += v;
949  \endcode
950 
951  <b> Preconditions:</b>
952 
953  \code
954  xleft <= 0;
955  xright >= 0;
956  yleft <= 0;
957  yright >= 0;
958  \endcode
959  */
960  template <class KernelIterator>
961  void initSeparable(KernelIterator kxcenter, int xleft, int xright,
962  KernelIterator kycenter, int yleft, int yright)
963  {
964  vigra_precondition(xleft <= 0 && yleft <= 0,
965  "Kernel2D::initSeparable(): left borders must be <= 0.");
966  vigra_precondition(xright >= 0 && yright >= 0,
967  "Kernel2D::initSeparable(): right borders must be >= 0.");
968 
969  left_ = Point2D(xleft, yleft);
970  right_ = Point2D(xright, yright);
971 
972  int w = right_.x - left_.x + 1;
973  int h = right_.y - left_.y + 1;
974  kernel_.resize(w, h);
975 
976  KernelIterator kiy = kycenter + left_.y;
977  Iterator iy = center() + left_;
978 
979  for(int y=left_.y; y<=right_.y; ++y, ++kiy, ++iy.y)
980  {
981  KernelIterator kix = kxcenter + left_.x;
982  Iterator ix = iy;
983  for(int x=left_.x; x<=right_.x; ++x, ++kix, ++ix.x)
984  {
985  *ix = *kix * *kiy;
986  }
987  }
988 
989  typename BasicImage<value_type>::iterator i = kernel_.begin();
990  typename BasicImage<value_type>::iterator iend = kernel_.end();
991  norm_ = *i;
992  ++i;
993 
994  for(; i!= iend; ++i)
995  {
996  norm_ += *i;
997  }
998  }
999 
1000  /** \brief Init as a 2D box filter with given radius.
1001 
1002  The function returns a reference to the kernel.
1003  */
1004  void initAveraging(int radius)
1005  {
1007  avg.initAveraging(radius);
1008  return initSeparable(avg, avg);
1009  }
1010 
1011  /** \brief Init as a 2D Gaussian function with given standard deviation and norm.
1012 
1013  The function returns a reference to the kernel.
1014  */
1015  void initGaussian(double std_dev, value_type norm)
1016  {
1017  Kernel1D<value_type> gauss;
1018  gauss.initGaussian(std_dev, norm);
1019  return initSeparable(gauss, gauss);
1020  }
1021 
1022  /** \brief Init as a 2D Gaussian function with given standard deviation and unit norm.
1023 
1024  The function returns a reference to the kernel.
1025  */
1026  void initGaussian(double std_dev)
1027  {
1028  return initGaussian(std_dev, NumericTraits<value_type>::one());
1029  }
1030 
1031  /** Init the 2D kernel as a circular averaging filter. The norm will be
1032  calculated as
1033  <TT>NumericTraits<value_type>::one() / (number of non-zero kernel values)</TT>.
1034  The kernel's value_type must be a linear space.
1035 
1036  <b> Required Interface:</b>
1037 
1038  \code
1039  value_type v = vigra::NumericTraits<value_type>::one();
1040 
1041  double d;
1042  v = d * v;
1043  \endcode
1044 
1045  <b> Precondition:</b>
1046 
1047  \code
1048  radius > 0;
1049  \endcode
1050  */
1051  void initDisk(int radius)
1052  {
1053  vigra_precondition(radius > 0,
1054  "Kernel2D::initDisk(): radius must be > 0.");
1055 
1056  left_ = Point2D(-radius, -radius);
1057  right_ = Point2D(radius, radius);
1058  int w = right_.x - left_.x + 1;
1059  int h = right_.y - left_.y + 1;
1060  kernel_.resize(w, h);
1061  norm_ = NumericTraits<value_type>::one();
1062 
1063  kernel_ = NumericTraits<value_type>::zero();
1064  double count = 0.0;
1065 
1066  Iterator k = center();
1067  double r2 = (double)radius*radius;
1068 
1069  int i;
1070  for(i=0; i<= radius; ++i)
1071  {
1072  double r = (double) i - 0.5;
1073  int w = (int)(VIGRA_CSTD::sqrt(r2 - r*r) + 0.5);
1074  for(int j=-w; j<=w; ++j)
1075  {
1076  k(j, i) = NumericTraits<value_type>::one();
1077  k(j, -i) = NumericTraits<value_type>::one();
1078  count += (i != 0) ? 2.0 : 1.0;
1079  }
1080  }
1081 
1082  count = 1.0 / count;
1083 
1084  for(int y=-radius; y<=radius; ++y)
1085  {
1086  for(int x=-radius; x<=radius; ++x)
1087  {
1088  k(x,y) = count * k(x,y);
1089  }
1090  }
1091  }
1092 
1093  /** Init the kernel by an explicit initializer list.
1094  The upper left and lower right corners (inclusive) of the kernel must be passed
1095  either as <tt>Shape2</tt> or <tt>Diff2D</tt> objects. A comma-separated initializer
1096  list for the kernel's weights is given after the assignment operator like this:
1097 
1098  \code
1099  // define horizontal Sobel filter
1100  vigra::Kernel2D<float> sobel;
1101 
1102  sobel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) =
1103  0.125, 0.0, -0.125,
1104  0.25, 0.0, -0.25,
1105  0.125, 0.0, -0.125;
1106  \endcode
1107 
1108  The norm is set to the sum of the initializer values. If the wrong number of
1109  values is given, a run-time error results. It is, however, possible to give
1110  just one initializer. This creates an averaging filter with the given constant:
1111 
1112  \code
1113  vigra::Kernel2D<float> average3x3;
1114 
1115  average3x3.initExplicitly(Shape2(-1,-1), Shape2(1,1)) = 1.0/9.0;
1116  \endcode
1117 
1118  Here, the norm is set to value*width()*height().
1119 
1120  <b> Preconditions:</b>
1121 
1122  \code
1123  1. upperleft.x <= 0;
1124  2. upperleft.y <= 0;
1125  3. lowerright.x >= 0;
1126  4. lowerright.y >= 0;
1127  5. the number of values in the initializer list
1128  is 1 or equals the size of the kernel.
1129  \endcode
1130  */
1131  Kernel2D & initExplicitly(Shape2 const & upperleft, Shape2 const & lowerright)
1132  {
1133  vigra_precondition(upperleft[0] <= 0 && upperleft[1] <= 0,
1134  "Kernel2D::initExplicitly(): left borders must be <= 0.");
1135  vigra_precondition(lowerright[0] >= 0 && lowerright[1] >= 0,
1136  "Kernel2D::initExplicitly(): right borders must be >= 0.");
1137 
1138  left_ = Point2D(upperleft[0], upperleft[1]);
1139  right_ = Point2D(lowerright[0], lowerright[1]);
1140 
1141  int w = right_.x - left_.x + 1;
1142  int h = right_.y - left_.y + 1;
1143  kernel_.resize(w, h);
1144 
1145  return *this;
1146  }
1147 
1148  Kernel2D & initExplicitly(Diff2D const & upperleft, Diff2D const & lowerright)
1149  {
1150  return initExplicitly(Shape2(upperleft), Shape2(lowerright));
1151  }
1152 
1153  /** Coordinates of the upper left corner of the kernel.
1154  */
1155  Point2D upperLeft() const { return left_; }
1156 
1157  /** Coordinates of the lower right corner of the kernel.
1158  */
1159  Point2D lowerRight() const { return right_; }
1160 
1161  /** Width of the kernel.
1162  */
1163  int width() const { return right_.x - left_.x + 1; }
1164 
1165  /** Height of the kernel.
1166  */
1167  int height() const { return right_.y - left_.y + 1; }
1168 
1169  /** ImageIterator that points to the center of the kernel (coordinate (0,0)).
1170  */
1171  Iterator center() { return kernel_.upperLeft() - left_; }
1172 
1173  /** ImageIterator that points to the center of the kernel (coordinate (0,0)).
1174  */
1175  ConstIterator center() const { return kernel_.upperLeft() - left_; }
1176 
1177  /** Access kernel entry at given position.
1178  */
1179  value_type & operator()(int x, int y)
1180  { return kernel_[Diff2D(x,y) - left_]; }
1181 
1182  /** Read kernel entry at given position.
1183  */
1184  value_type operator()(int x, int y) const
1185  { return kernel_[Diff2D(x,y) - left_]; }
1186 
1187  /** Access kernel entry at given position.
1188  */
1189  value_type & operator[](Diff2D const & d)
1190  { return kernel_[d - left_]; }
1191 
1192  /** Read kernel entry at given position.
1193  */
1194  value_type operator[](Diff2D const & d) const
1195  { return kernel_[d - left_]; }
1196 
1197  /** Norm of the kernel (i.e. sum of its elements).
1198  */
1199  value_type norm() const { return norm_; }
1200 
1201  /** The kernels default accessor.
1202  */
1203  Accessor accessor() { return Accessor(); }
1204 
1205  /** The kernels default const accessor.
1206  */
1207  ConstAccessor accessor() const { return ConstAccessor(); }
1208 
1209  /** Normalize the kernel to the given value. (The norm is the sum of all kernel
1210  elements.) The kernel's value_type must be a division algebra or
1211  algebraic field.
1212 
1213  <b> Required Interface:</b>
1214 
1215  \code
1216  value_type v = vigra::NumericTraits<value_type>::one(); // if norm is not
1217  // given explicitly
1218 
1219  v += v;
1220  v = v * v;
1221  v = v / v;
1222  \endcode
1223  */
1224  void normalize(value_type norm)
1225  {
1226  typename BasicImage<value_type>::iterator i = kernel_.begin();
1227  typename BasicImage<value_type>::iterator iend = kernel_.end();
1228  typename NumericTraits<value_type>::RealPromote sum = *i;
1229  ++i;
1230 
1231  for(; i!= iend; ++i)
1232  {
1233  sum += *i;
1234  }
1235 
1236  sum = norm / sum;
1237  i = kernel_.begin();
1238  for(; i != iend; ++i)
1239  {
1240  *i = *i * sum;
1241  }
1242 
1243  norm_ = norm;
1244  }
1245 
1246  /** Normalize the kernel to norm 1.
1247  */
1248  void normalize()
1249  {
1250  normalize(one());
1251  }
1252 
1253  /** current border treatment mode
1254  */
1255  BorderTreatmentMode borderTreatment() const
1256  { return border_treatment_; }
1257 
1258  /** Set border treatment mode.
1259  Only <TT>BORDER_TREATMENT_CLIP</TT> and <TT>BORDER_TREATMENT_AVOID</TT> are currently
1260  allowed.
1261  */
1262  void setBorderTreatment( BorderTreatmentMode new_mode)
1263  {
1264  vigra_precondition((new_mode == BORDER_TREATMENT_CLIP ||
1265  new_mode == BORDER_TREATMENT_AVOID ||
1266  new_mode == BORDER_TREATMENT_REFLECT ||
1267  new_mode == BORDER_TREATMENT_REPEAT ||
1268  new_mode == BORDER_TREATMENT_WRAP),
1269  "convolveImage():\n"
1270  " Border treatment must be one of follow treatments:\n"
1271  " - BORDER_TREATMENT_CLIP\n"
1272  " - BORDER_TREATMENT_AVOID\n"
1273  " - BORDER_TREATMENT_REFLECT\n"
1274  " - BORDER_TREATMENT_REPEAT\n"
1275  " - BORDER_TREATMENT_WRAP\n");
1276 
1277  border_treatment_ = new_mode;
1278  }
1279 
1280 
1281 private:
1282  BasicImage<value_type> kernel_;
1283  Point2D left_, right_;
1284  value_type norm_;
1285  BorderTreatmentMode border_treatment_;
1286 };
1287 
1288 /**************************************************************/
1289 /* */
1290 /* Argument object factories for Kernel2D */
1291 /* */
1292 /* (documentation: see vigra/convolution.hxx) */
1293 /* */
1294 /**************************************************************/
1295 
1296 template <class KernelIterator, class KernelAccessor>
1297 inline
1298 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D, BorderTreatmentMode>
1299 kernel2d(KernelIterator ik, KernelAccessor ak, Diff2D kul, Diff2D klr,
1300  BorderTreatmentMode border)
1301 
1302 {
1303  return
1304  tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D, BorderTreatmentMode> (
1305  ik, ak, kul, klr, border);
1306 }
1307 
1308 template <class T>
1309 inline
1310 tuple5<typename Kernel2D<T>::ConstIterator,
1311  typename Kernel2D<T>::ConstAccessor,
1312  Diff2D, Diff2D, BorderTreatmentMode>
1313 kernel2d(Kernel2D<T> const & k)
1314 
1315 {
1316  return
1317  tuple5<typename Kernel2D<T>::ConstIterator,
1318  typename Kernel2D<T>::ConstAccessor,
1319  Diff2D, Diff2D, BorderTreatmentMode>(
1320  k.center(),
1321  k.accessor(),
1322  k.upperLeft(), k.lowerRight(),
1323  k.borderTreatment());
1324 }
1325 
1326 template <class T>
1327 inline
1328 tuple5<typename Kernel2D<T>::ConstIterator,
1329  typename Kernel2D<T>::ConstAccessor,
1330  Diff2D, Diff2D, BorderTreatmentMode>
1331 kernel2d(Kernel2D<T> const & k, BorderTreatmentMode border)
1332 
1333 {
1334  return
1335  tuple5<typename Kernel2D<T>::ConstIterator,
1336  typename Kernel2D<T>::ConstAccessor,
1337  Diff2D, Diff2D, BorderTreatmentMode>(
1338  k.center(),
1339  k.accessor(),
1340  k.upperLeft(), k.lowerRight(),
1341  border);
1342 }
1343 
1344 
1345 } // namespace vigra
1346 
1347 #endif // VIGRA_STDCONVOLUTION_HXX
iterator end()
Definition: basicimage.hxx:972
iterator begin()
Definition: basicimage.hxx:963
Kernel2D & operator=(Kernel2D const &k)
Definition: stdconvolution.hxx:849
value_type norm() const
Definition: separableconvolution.hxx:2173
void initAveraging(int radius, value_type norm)
Definition: separableconvolution.hxx:2482
BasicImage< value_type >::ConstAccessor ConstAccessor
Definition: stdconvolution.hxx:781
Generic 1 dimensional convolution kernel.
Definition: separableconvolution.hxx:52
ARITHTYPE value_type
Definition: stdconvolution.hxx:765
Accessor accessor()
Definition: stdconvolution.hxx:1203
int y
Definition: diff2d.hxx:392
void initGaussian(double std_dev, value_type norm, double windowRatio=0.0)
Definition: separableconvolution.hxx:2251
value_type operator()(int x, int y) const
Definition: stdconvolution.hxx:1184
void initSeparable(KernelIterator kxcenter, int xleft, int xright, KernelIterator kycenter, int yleft, int yright)
Definition: stdconvolution.hxx:961
BorderTreatmentMode borderTreatment() const
Definition: stdconvolution.hxx:1255
Kernel2D()
Definition: stdconvolution.hxx:829
int x
Definition: diff2d.hxx:385
Point2D lowerRight() const
Definition: stdconvolution.hxx:1159
value_type operator[](Diff2D const &d) const
Definition: stdconvolution.hxx:1194
int height() const
Definition: stdconvolution.hxx:1167
Two dimensional difference vector.
Definition: diff2d.hxx:185
BasicImage< value_type >::Accessor Accessor
Definition: stdconvolution.hxx:777
InitProxy operator=(value_type const &v)
Definition: stdconvolution.hxx:881
ConstIterator center() const
Definition: stdconvolution.hxx:1175
Iterator center()
Definition: stdconvolution.hxx:1171
Definition: accessor.hxx:43
int left() const
Definition: separableconvolution.hxx:2151
void initAveraging(int radius)
Init as a 2D box filter with given radius.
Definition: stdconvolution.hxx:1004
Two dimensional point or position.
Definition: diff2d.hxx:592
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude)
Definition: fftw3.hxx:1037
Point2D upperLeft() const
Definition: stdconvolution.hxx:1155
void mul(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
multiplication with enforced result type.
Definition: fixedpoint.hxx:605
void normalize()
Definition: stdconvolution.hxx:1248
value_type & operator[](Diff2D const &d)
Definition: stdconvolution.hxx:1189
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition: tinyvector.hxx:1871
row_iterator rowIterator() const
Definition: diff2d.hxx:431
ConstAccessor accessor() const
Definition: stdconvolution.hxx:1207
void resize(int width, int height)
Definition: basicimage.hxx:776
void initDisk(int radius)
Definition: stdconvolution.hxx:1051
void convolveImage(...)
Convolve an image with the given kernel(s).
void normalize(value_type norm)
Definition: stdconvolution.hxx:1224
value_type norm() const
Definition: stdconvolution.hxx:1199
BasicImage< value_type >::const_traverser ConstIterator
Definition: stdconvolution.hxx:773
void initSeparable(Kernel1D< value_type > const &kx, Kernel1D< value_type > const &ky)
Definition: stdconvolution.hxx:909
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
void normalizedConvolveImage(...)
Performs a 2-dimensional normalized convolution, i.e. convolution with a mask image.
MultiArrayShape< 2 >::type Shape2
shape type for MultiArray<2, T>
Definition: multi_shape.hxx:241
Fundamental class template for images.
Definition: basicimage.hxx:473
Generic 2 dimensional convolution kernel.
Definition: stdconvolution.hxx:52
void convolveImageWithMask(...)
Deprecated name of 2-dimensional normalized convolution, i.e. convolution with a mask image...
void initGaussian(double std_dev, value_type norm)
Init as a 2D Gaussian function with given standard deviation and norm.
Definition: stdconvolution.hxx:1015
int width() const
Definition: stdconvolution.hxx:1163
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
int right() const
Definition: separableconvolution.hxx:2155
void initGaussian(double std_dev)
Init as a 2D Gaussian function with given standard deviation and unit norm.
Definition: stdconvolution.hxx:1026
InternalVector::const_iterator const_iterator
Definition: separableconvolution.hxx:1393
iterator center()
Definition: separableconvolution.hxx:2121
value_type & operator()(int x, int y)
Definition: stdconvolution.hxx:1179
Kernel2D & initExplicitly(Shape2 const &upperleft, Shape2 const &lowerright)
Definition: stdconvolution.hxx:1131
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:133
~Kernel2D()
Definition: stdconvolution.hxx:893
void setBorderTreatment(BorderTreatmentMode new_mode)
Definition: stdconvolution.hxx:1262
BasicImage< value_type >::traverser Iterator
Definition: stdconvolution.hxx:769
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616
traverser upperLeft()
Definition: basicimage.hxx:923
Kernel2D(Kernel2D const &k)
Definition: stdconvolution.hxx:839

© 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.10.0