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