1 // This is core/vil1/vil1_convolve.h
2 #ifndef vil1_convolve_h_
3 #define vil1_convolve_h_
4 //:
5 // \file
6 // \author fsm
7 
8 #ifdef _MSC_VER
9 #  include <vcl_msvc_warnings.h>
10 #endif
11 #include "vil1_memory_image_of.h"
12 
13 //: Available options for boundary behavior
14 // When convolving a finite signal the boundaries may be
15 // treated in various ways which can often be expressed in terms
16 // of ways to extend the signal outside its original range.
17 enum vil1_convolve_boundary_option {
18   // Do not to extend the signal, but pad with zeros.
19   //     |                               |
20   // K                       ----*-------
21   // in   ... ---------------------------
22   // out  ... --------------------0000000
23   vil1_convolve_no_extend,
24 
25   // Zero-extend the input signal beyond the boundary.
26   //     |                               |
27   // K                              ----*--------
28   // in   ... ---------------------------000000000000...
29   // out  ... ---------------------------
30   vil1_convolve_zero_extend,
31 
32   // Extend the signal to be constant beyond the boundary
33   //     |                               |
34   // K                              ----*--------
35   // in   ... --------------------------aaaaaaaaaaaaa...
36   // out  ... ---------------------------
37   vil1_convolve_constant_extend,
38 
39   // Extend the signal periodically beyond the boundary.
40   //     |                               |
41   // K                              ----*--------
42   // in   abc...-------------------------abc...------..
43   // out  ... ---------------------------
44   vil1_convolve_periodic_extend,
45 
46   // Extend the signal by reflection about the boundary.
47   //     |                               |
48   // K                               ----*--------
49   // in   ... -------------------...edcbabcde...
50   // out  ... ---------------------------
51   vil1_convolve_reflect_extend,
52 
53   // This one is slightly different. The input signal is not
54   // extended in any way, but the kernel is trimmed to allow
55   // convolution to proceed up to the boundary and reweighed
56   // to keep the total area the same.
57   // *** may not work with kernels which take negative values.
58   vil1_convolve_trim
59 };
60 
61 //: Parameters for convolution
62 // These structs exist purely to group the parameters to the
63 // convolution routines. It is not intended that they be
64 // expressive or even useful in any other context.
65 //
66 // Usually, begin <= origin < end. Expect assertion failures
67 // if that is not the case.
68 template <class T>
69 struct vil1_convolve_signal_1d {
70   T *array_;
71   int begin_;
72   int origin_;
73   int end_;
vil1_convolve_signal_1dvil1_convolve_signal_1d74   vil1_convolve_signal_1d(T *a, int b, int o, int e)
75     : array_(a), begin_(b), origin_(o), end_(e) { }
76 };
77 
78 //: Parameters for convolution
79 template <class T>
80 struct vil1_convolve_signal_2d {
81   T * const *array_;
82   int beginx_, originx_, endx_;
83   int beginy_, originy_, endy_;
vil1_convolve_signal_2dvil1_convolve_signal_2d84   vil1_convolve_signal_2d(T * const *a,
85                           int bx, int ox, int ex,
86                           int by, int oy, int ey)
87     : array_(a)
88     , beginx_(bx), originx_(ox), endx_(ex)
89     , beginy_(by), originy_(oy), endy_(ey)
90     { }
91 };
92 
93 // Note. The convolution operation is defined by
94 //    (f*g)(x) = \int f(x-y) g(y) dy,
95 // i.e. one operand is reflected before the integration is performed.
96 // If you don't want this to happen, the behaviour you want is not
97 // called "convolution". So don't break the convolution routines in
98 // that particular way.
99 
100 //: Convolution in x-direction : out(x, y) = \sum_i kernel[i]*in(x-i, y)
101 template <class I1, class I2, class AC, class O>
102 void vil1_convolve_1d_x(vil1_convolve_signal_1d<I1 const> const &kernel,
103                         vil1_convolve_signal_2d<I2 const> const &input,
104                         AC * /*accumulator type*/,
105                         vil1_convolve_signal_2d<O> const &output,
106                         vil1_convolve_boundary_option b,
107                         vil1_convolve_boundary_option e);
108 
109 //: Convolution in y-direction : out(x, y) = \sum_j kernel[j]*in(x, y-j)
110 template <class I1, class I2, class AC, class O>
111 void vil1_convolve_1d_y(vil1_convolve_signal_1d<I1 const> const &kernel,
112                         vil1_convolve_signal_2d<I2 const> const &input,
113                         AC * /*accumulator type*/,
114                         vil1_convolve_signal_2d<O> const &output,
115                         vil1_convolve_boundary_option b,
116                         vil1_convolve_boundary_option e);
117 
118 template <class I1, class I2, class AC, class O>
119 void vil1_convolve_separable(I1 const kernel[], unsigned N,
120                              vil1_memory_image_of<I2>& buf,
121                              vil1_memory_image_of<AC>& tmp,
122                              vil1_memory_image_of<O>& out);
123 
124 template <class I1, class I2, class AC, class O>
125 vil1_image vil1_convolve_separable(vil1_image const& in,
126                                    I1 const* kernel,
127                                    int N, I2*, AC*, O*);
128 
129 // *** the following function is implemented in vil1_convolve_1d_x.hxx
130 
131 //: Convolution in x-direction, using a symmetric kernel.
132 template <class I1, class I2, class AC, class O>
133 void vil1_convolve_1d_x(I1 const *half_kernel, unsigned kernel_size,
134                         vil1_convolve_signal_2d<I2 const> const &input,
135                         AC * /*accumulator type*/,
136                         vil1_convolve_signal_2d<O> const &output,
137                         vil1_convolve_boundary_option b,
138                         vil1_convolve_boundary_option e);
139 
140 // *** the following function is implemented in vil1_convolve_1d_y.hxx
141 
142 //: Convolution in y-direction, using a symmetric kernel.
143 template <class I1, class I2, class AC, class O>
144 void vil1_convolve_1d_y(I1 const *half_kernel, unsigned kernel_size,
145                         vil1_convolve_signal_2d<I2 const> const &input,
146                         AC * /*accumulator type*/,
147                         vil1_convolve_signal_2d<O> const &output,
148                         vil1_convolve_boundary_option b,
149                         vil1_convolve_boundary_option e);
150 
151 #endif // vil1_convolve_h_
152