vil_correlate_1d.h
Go to the documentation of this file.
1 // This is core/vil/algo/vil_correlate_1d.h
2 #ifndef vil_correlate_1d_h_
3 #define vil_correlate_1d_h_
4 //:
5 // \file
6 // \brief 1D Convolution with cunning boundary options
7 // \author Tim Cootes (based on work by fsm)
8 
9 #include <algorithm>
10 #include <cstring>
11 #include <iostream>
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 #include <cassert>
16 #include <vil/vil_image_view.h>
17 #include <vil/vil_image_resource.h>
18 #include <vil/vil_property.h>
20 
21 //: Correlate kernel[x] (x in [k_lo,k_hi]) with srcT
22 // Assumes dest and src same size (nx)
23 template <class srcT, class destT, class kernelT, class accumT>
24 inline void vil_correlate_1d(const srcT* src0, unsigned nx, std::ptrdiff_t s_step,
25  destT* dest0, std::ptrdiff_t d_step,
26  const kernelT* kernel,
27  std::ptrdiff_t k_lo, std::ptrdiff_t k_hi,
28  accumT ac,
29  vil_convolve_boundary_option start_option,
31 {
32  // Deal with start (fill elements 0..1-k_lo of dest)
33  vil_convolve_edge_1d(src0,nx,s_step,dest0,d_step,kernel,-k_hi,-k_lo,-1,ac,start_option);
34 
35  const kernelT* k_begin = kernel+k_lo;
36  const kernelT* k_end = kernel+k_hi+1;
37  const srcT* src = src0;
38 
39  destT* end_dest = dest0 + d_step*(int(nx)-k_hi);
40  for (destT* dest = dest0-d_step*k_lo;dest!=end_dest;dest+=d_step,src+=s_step)
41  {
42  accumT sum = 0;
43  const srcT* s= src;
44  for (const kernelT *k = k_begin;k!=k_end; ++k,s+=s_step) sum+= (accumT)((*k)*(*s));
45  *dest = destT(sum);
46  }
47 
48  // Deal with end (reflect data and kernel!)
49  vil_convolve_edge_1d(src0+(nx-1)*s_step,nx,-s_step,
50  dest0+(nx-1)*d_step,-d_step,
51  kernel,k_lo,k_hi,1,ac,end_option);
52 }
53 
54 //: correlate kernel[i] (i in [k_lo,k_hi]) with srcT in i-direction
55 // On exit dest_im(i,j) = sum src(i+x,j)*kernel(x) (x=k_lo..k_hi)
56 // \note This function does not reverse the kernel. If you want the
57 // kernel reversed, use vil_convolve_1d instead.
58 // \param kernel should point to tap 0.
59 // \param dest_im will be resized to size of src_im.
60 // \relatesalso vil_image_view
61 template <class srcT, class destT, class kernelT, class accumT>
62 inline void vil_correlate_1d(const vil_image_view<srcT>& src_im,
63  vil_image_view<destT>& dest_im,
64  const kernelT* kernel,
65  std::ptrdiff_t k_lo, std::ptrdiff_t k_hi,
66  accumT ac,
67  vil_convolve_boundary_option start_option,
69 {
70  unsigned ni = src_im.ni();
71  unsigned nj = src_im.nj();
72  std::ptrdiff_t s_istep = src_im.istep(), s_jstep = src_im.jstep();
73 
74  dest_im.set_size(ni,nj,src_im.nplanes());
75  std::ptrdiff_t d_istep = dest_im.istep(),d_jstep = dest_im.jstep();
76 
77  for (unsigned int p=0;p<src_im.nplanes();++p)
78  {
79  // Select first row of p-th plane
80  const srcT* src_row = src_im.top_left_ptr()+p*src_im.planestep();
81  destT* dest_row = dest_im.top_left_ptr()+p*dest_im.planestep();
82 
83  // Apply convolution to each row in turn
84  // First check if either istep is 1 for speed optimisation.
85  if (s_istep == 1)
86  {
87  if (d_istep == 1)
88  for (unsigned int j=0;j<nj;++j,src_row+=s_jstep,dest_row+=d_jstep)
89  vil_correlate_1d(src_row,ni,1, dest_row,1,
90  kernel,k_lo,k_hi,ac,start_option,end_option);
91  else
92  for (unsigned int j=0;j<nj;++j,src_row+=s_jstep,dest_row+=d_jstep)
93  vil_correlate_1d(src_row,ni,1, dest_row,d_istep,
94  kernel,k_lo,k_hi,ac,start_option,end_option);
95  }
96  else
97  {
98  if (d_istep == 1)
99  for (unsigned int j=0;j<nj;++j,src_row+=s_jstep,dest_row+=d_jstep)
100  vil_correlate_1d(src_row,ni,s_istep, dest_row,1,
101  kernel,k_lo,k_hi,ac,start_option,end_option);
102  else
103  for (unsigned int j=0;j<nj;++j,src_row+=s_jstep,dest_row+=d_jstep)
104  vil_correlate_1d(src_row,ni,s_istep, dest_row,d_istep,
105  kernel,k_lo,k_hi,ac,start_option,end_option);
106  }
107  }
108 }
109 
110 template <class destT, class kernelT, class accumT>
112  const vil_image_resource_sptr& src_im,
113  const destT dt,
114  const kernelT* kernel, std::ptrdiff_t k_lo, std::ptrdiff_t k_hi,
115  const accumT ac,
116  vil_convolve_boundary_option start_option,
117  vil_convolve_boundary_option end_option);
118 
119 //: A resource adaptor that behaves like a correlated version of its input
120 template <class kernelT, class accumT, class destT>
122 {
123  public:
124  //: Construct a correlate filter.
125  // You can't create one of these directly, use vil_correlate_1d instead
127  const kernelT* kernel, std::ptrdiff_t k_lo, std::ptrdiff_t k_hi,
128  vil_convolve_boundary_option start_option,
129  vil_convolve_boundary_option end_option) :
130  src_(src), kernel_(kernel), klo_(k_lo), khi_(k_hi),
131  start_option_(start_option), end_option_(end_option)
132  {
133  // Can't do period extension yet.
134  assert (start_option != vil_convolve_periodic_extend ||
135  end_option != vil_convolve_periodic_extend);
136  }
137 
138  friend vil_image_resource_sptr vil_correlate_1d <> (
139  const vil_image_resource_sptr& src_im, const destT dt, const kernelT* kernel,
140  std::ptrdiff_t k_lo, std::ptrdiff_t k_hi, const accumT ac,
141  vil_convolve_boundary_option start_option,
142  vil_convolve_boundary_option end_option);
143 
144  public:
146  unsigned j0, unsigned nj) const override
147  {
148  if (i0 + ni > src_->ni() || j0 + nj > src_->nj()) return nullptr;
149  const unsigned lsrc = (unsigned)std::max(0,int(i0+klo_)); // lhs of input window
150  const unsigned hsrc = std::min(src_->ni(),(unsigned int)(i0+ni-klo_+khi_)); // 1+rhs of input window.
151  const unsigned lboundary = std::min((unsigned) -klo_, i0); // width of lhs boundary area.
152  assert (hsrc > lsrc);
153  vil_image_view_base_sptr vs = src_->get_view(lsrc, hsrc-lsrc, j0, nj);
154  vil_image_view<destT> dest(vs->ni(), vs->nj(), vs->nplanes());
155  switch (vs->pixel_format())
156  {
157 #define macro( F , T ) \
158  case F : \
159  vil_correlate_1d(static_cast<vil_image_view<T >&>(*vs),dest, \
160  kernel_, klo_, khi_, accumT(), start_option_, end_option_); \
161  return new vil_image_view<destT>(vil_crop(dest, lboundary, ni, 0, nj));
162 
163  macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
164  macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
165  macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
166  macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
167  macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
168  macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
170  macro(VIL_PIXEL_FORMAT_FLOAT , float )
171  macro(VIL_PIXEL_FORMAT_DOUBLE , double )
172 // complex<float> should work - but causes all manner of compiler template errors.
173 // maybe need a better compiler, maybe there is a code fix - IMS
174 #undef macro
175  default:
176  return nullptr;
177  }
178  }
179 
180  unsigned nplanes() const override { return src_->nplanes(); }
181  unsigned ni() const override { return src_->ni(); }
182  unsigned nj() const override { return src_->nj(); }
183 
184  enum vil_pixel_format pixel_format() const override
185  { return vil_pixel_format_of(accumT()); }
186 
187 
188  //: Put the data in this view back into the image source.
189  bool put_view(const vil_image_view_base& /*im*/, unsigned /*i0*/, unsigned /*j0*/) override
190  {
191  std::cerr << "WARNING: vil_correlate_1d_resource::put_back\n"
192  << "\tYou can't push data back into a correlate filter.\n";
193  return false;
194  }
195 
196  //: Extra property information
197  bool get_property(char const* tag, void* property_value = nullptr) const override
198  {
199  if (0==std::strcmp(tag, vil_property_read_only))
200  return property_value ? (*static_cast<bool*>(property_value)) = true : true;
201 
202  return src_->get_property(tag, property_value);
203  }
204 
205  protected:
207  const kernelT* kernel_;
208  std::ptrdiff_t klo_, khi_;
210 };
211 
212 //: Create an image_resource object which correlate kernel[x] x in [k_lo,k_hi] with srcT
213 // \note This function does not reverse the kernel. If you want the
214 // kernel reversed, use vil_convolve_1d instead.
215 // \param kernel should point to tap 0.
216 // \relatesalso vil_image_resource
217 template <class destT, class kernelT, class accumT>
219  const vil_image_resource_sptr& src_im,
220  const destT /*dt*/,
221  const kernelT* kernel, std::ptrdiff_t k_lo, std::ptrdiff_t k_hi,
222  const accumT,
223  vil_convolve_boundary_option start_option,
224  vil_convolve_boundary_option end_option)
225 {
226  return new vil_correlate_1d_resource<kernelT, accumT, destT>(src_im, kernel, k_lo, k_hi, start_option, end_option);
227 }
228 
229 #endif // vil_correlate_1d_h_
An abstract base class of smart pointers to actual image data in memory.
vil_pixel_format
Describes the type of the concrete data.
enum vil_pixel_format pixel_format() const override
Pixel Format.
vil_correlate_1d_resource(const vil_image_resource_sptr &src, const kernelT *kernel, std::ptrdiff_t k_lo, std::ptrdiff_t k_hi, vil_convolve_boundary_option start_option, vil_convolve_boundary_option end_option)
Construct a correlate filter.
Extend the signal periodically beyond the boundary.
Concrete view of image data of type T held in memory.
Definition: vil_fwd.h:13
void set_size(unsigned ni, unsigned nj) override
resize current planes to ni x nj.
unsigned ni() const override
Dimensions: Planes x ni x nj.
vil_image_view_base_sptr get_copy_view(unsigned i0, unsigned ni, unsigned j0, unsigned nj) const override
Create a read/write view of a copy of this data.
void vil_convolve_edge_1d(const srcT *src, unsigned n, std::ptrdiff_t s_step, destT *dest, std::ptrdiff_t d_step, const kernelT *kernel, std::ptrdiff_t k_lo, std::ptrdiff_t k_hi, std::ptrdiff_t kstep, accumT, vil_convolve_boundary_option option)
Convolve edge with kernel[x*kstep] x in [k_lo,k_hi] (k_hi>=0).
bool put_view(const vil_image_view_base &, unsigned, unsigned) override
Put the data in this view back into the image source.
A resource adaptor that behaves like a correlated version of its input.
std::ptrdiff_t jstep() const
Add this to your pixel pointer to get next j pixel.
vil_convolve_boundary_option
Available options for boundary behavior.
unsigned ni() const
Width.
unsigned nj() const
Height.
std::ptrdiff_t planestep() const
Add this to your pixel pointer to get pixel on next plane.
vil_image_resource_sptr src_
Abstract representation of an image source or image destination.
void vil_correlate_1d(const vil_image_view< srcT > &src_im, vil_image_view< destT > &dest_im, const kernelT *kernel, std::ptrdiff_t k_lo, std::ptrdiff_t k_hi, accumT ac, vil_convolve_boundary_option start_option, vil_convolve_boundary_option end_option)
correlate kernel[i] (i in [k_lo,k_hi]) with srcT in i-direction.
vil_convolve_boundary_option end_option_
A base class reference-counting view of some image data.
There is no class or function called vil_property.
unsigned nplanes() const override
Dimensions: Planes x ni x nj.
T * top_left_ptr()
Pointer to the first (top left in plane 0) pixel.
bool get_property(char const *tag, void *property_value=nullptr) const override
Extra property information.
vil_convolve_boundary_option start_option_
unsigned nplanes() const
Number of planes.
Representation of a generic image source or destination.
std::ptrdiff_t istep() const
Add this to your pixel pointer to get next i pixel.
vil_pixel_format vil_pixel_format_of(T)
The pixel format enumeration corresponding to the C++ type.
#define macro(F, T)
#define vil_property_read_only
Indicate that you can't call put_view on this image.
Definition: vil_property.h:47
unsigned nj() const override
Dimensions: Planes x ni x nj.
1D Convolution with cunning boundary options