libcvd
image_interpolate.h
1 #ifndef CVD_IMAGE_INTERPOLATE_H
2 #define CVD_IMAGE_INTERPOLATE_H
3 
4 #include <TooN/TooN.h>
5 #include <cvd/image.h>
6 #include <cvd/internal/pixel_operations.h>
7 #include <cvd/internal/rgb_components.h>
8 #include <cvd/vector_image_ref.h>
9 #include <math.h>
10 
11 namespace CVD
12 {
16 namespace Interpolate
17 {
25  {
26  };
27 
45  class Bilinear
46  {
47  };
48 
61  class Bicubic
62  {
63  };
64 };
65 
66 #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
67 template <class I, class P>
74 {
75  public:
79 
82  bool in_image(const TooN::Vector<2>& pos) const;
83 
87  float_type operator[](const TooN::Vector<2>& pos) const;
88 
90  TooN::Vector<2> min() const;
92  TooN::Vector<2> max() const;
93 };
94 #endif
95 
96 #ifndef DOXYGEN_IGNORE_INTERNAL
97 
98 template <class I, class C>
100 
101 //Zero order (nearest neighbour)
102 
103 template <class C>
104 class image_interpolate<Interpolate::NearestNeighbour, C>
105 {
106  private:
107  const BasicImage<C>* im;
108 
109  int round(double d) const
110  {
111  if(d < 0)
112  return (int)ceil(d - .5);
113  else
114  return (int)floor(d + .5);
115  }
116 
117  ImageRef to_ir(const TooN::Vector<2>& v) const
118  {
119  return ImageRef(round(v[0]), round(v[1]));
120  }
121 
122  typedef typename Pixel::traits<C>::float_type FT;
123 
124  public:
126  : im(&i)
127  {
128  }
129 
130  bool in_image(const TooN::Vector<2>& pos) const
131  {
132  return im->in_image(to_ir(pos));
133  }
134 
135  FT operator[](const TooN::Vector<2>& pos) const
136  {
137  return (*im)[to_ir(pos)];
138  }
139 
140  TooN::Vector<2> min() const
141  {
142  return TooN::makeVector(0, 0);
143  }
144 
145  TooN::Vector<2> max() const
146  {
147  return vec(im->size());
148  }
149 };
150 
151 template <class T>
152 class image_interpolate<Interpolate::Bilinear, T>
153 {
154  private:
155  const BasicImage<T>* im;
156 
157  TooN::Vector<2> floor(const TooN::Vector<2>& v) const
158  {
159  return TooN::makeVector(::floor(v[0]), ::floor(v[1]));
160  }
161 
162  TooN::Vector<2> ceil(const TooN::Vector<2>& v) const
163  {
164  return TooN::makeVector(::ceil(v[0]), ::ceil(v[1]));
165  }
166 
167  typedef typename Pixel::traits<T>::float_type FT;
168 
169  public:
171  : im(&i)
172  {
173  }
174 
175  bool in_image(const TooN::Vector<2>& pos) const
176  {
177  return im->in_image(ir(floor(pos))) && im->in_image(ir(ceil(pos)));
178  }
179 
180  FT operator[](const TooN::Vector<2>& pos) const
181  {
182  TooN::Vector<2> delta = pos - floor(pos);
183 
184  ImageRef p = ir(floor(pos));
185 
186  double x = delta[0];
187  double y = delta[1];
188 
189  FT ret;
190 
191  for(unsigned int i = 0; i < Pixel::Component<T>::count; i++)
192  {
193  float a, b = 0, c = 0, d = 0;
194 
195  a = Pixel::Component<T>::get((*im)[p + ImageRef(0, 0)], i) * (1 - x) * (1 - y);
196 
197  if(x != 0)
198  b = Pixel::Component<T>::get((*im)[p + ImageRef(1, 0)], i) * x * (1 - y);
199 
200  if(y != 0)
201  c = Pixel::Component<T>::get((*im)[p + ImageRef(0, 1)], i) * (1 - x) * y;
202 
203  if(x != 0 && y != 0)
204  d = Pixel::Component<T>::get((*im)[p + ImageRef(1, 1)], i) * x * y;
205 
206  Pixel::Component<FT>::get(ret, i) = a + b + c + d;
207  }
208 
209  return ret;
210  }
211 
212  TooN::Vector<2> min() const
213  {
214  return TooN::makeVector(0, 0);
215  }
216 
217  TooN::Vector<2> max() const
218  {
219  return vec(im->size());
220  }
221 };
222 
223 template <class T>
224 class image_interpolate<Interpolate::Bicubic, T>
225 {
226  private:
227  const BasicImage<T>* im;
228 
229  float p(float f) const
230  {
231  return f < 0 ? 0 : f;
232  }
233 
234  float r(float x) const
235  {
236  return (pow(p(x + 2), 3) - 4 * pow(p(x + 1), 3) + 6 * pow(p(x), 3) - 4 * pow(p(x - 1), 3)) / 6;
237  }
238 
239  typedef typename Pixel::traits<T>::float_type FT;
240 
241  public:
243  : im(&i)
244  {
245  }
246 
247  bool in_image(const TooN::Vector<2>& pos) const
248  {
249  return pos[0] >= 1 && pos[1] >= 1 && pos[0] < im->size().x - 2 && pos[1] < im->size().y - 2;
250  }
251 
252  FT operator[](const TooN::Vector<2>& pos) const
253  {
254  int x = (int)floor(pos[0]);
255  int y = (int)floor(pos[1]);
256  float dx = pos[0] - x;
257  float dy = pos[1] - y;
258 
259  //Algorithm as described in http://astronomy.swin.edu.au/~pbourke/colour/bicubic/
260  FT ret;
261  for(unsigned int i = 0; i < Pixel::Component<T>::count; i++)
262  {
263  float s = 0;
264 
265  for(int m = -1; m < 3; m++)
266  for(int n = -1; n < 3; n++)
267  s += Pixel::Component<T>::get((*im)[y + n][x + m], i) * r(m - dx) * r(dy - n);
268 
269  Pixel::Component<FT>::get(ret, i) = s;
270  }
271 
272  return ret;
273  }
274 
275  TooN::Vector<2> min() const
276  {
277  return TooN::makeVector(1, 1);
278  }
279 
280  TooN::Vector<2> max() const
281  {
282  return TooN::makeVector(im->size().x - 2, im->size().y - 2);
283  }
284 };
285 #endif
286 
287 }
288 
289 #endif
ImageRef ir(const TooN::Vector< 2 > &v)
Convert a Vector into an image co-ordinate.
Definition: vector_image_ref.h:24
All classes and functions are within the CVD namespace.
Definition: argb.h:6
ImageRef size() const
What is the size of this image?
Definition: image.h:557
Definition: image_interpolate.h:99
TooN::Vector< 2 > vec(const ImageRef &ir)
Convert an image co-ordinate into a Vector.
Definition: vector_image_ref.h:13
This does not interpolate: it uses the nearest neighbour.
Definition: image_interpolate.h:24
This class is for bicubic (not bicubic spline) interpolation.
Definition: image_interpolate.h:61
Definition: image_ref.h:29
This class is for bilinear interpolation.
Definition: image_interpolate.h:45
A generic image class to manage a block of arbitrarily padded data as an image.
Definition: image.h:273
Definition: builtin_components.h:38