X-Boost  2.3.8
IntegralImage.h
1 /* XBoost: Ada-Boost and Friends on Haar/ICF/HOG Features, Library and ToolBox
2  *
3  * Copyright (c) 2008-2014 Paolo Medici <medici@ce.unipr.it>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #ifndef _INTEGRAL_IMAGE_H
22 #define _INTEGRAL_IMAGE_H
23 
29 #include <algorithm>
30 #include <cmath>
31 #include <iostream>
32 #include "Image.h"
33 #include "Types.h"
34 #include "_stdint.h"
35 
37 #include <cmath>
38 #include <limits>
39 #include <stdexcept>
40 
44 template<class T>
46 public:
48  T *data;
50  unsigned int width, height;
51 
52 public:
53  IntegralImageHandle() : data(0), width(0), height(0) { }
54 
57  {
58  data = src.data;
59  width = src.width;
60  height = src.height;
61  }
62 
63  void operator=(const IntegralImageHandle<T> & src)
64  {
65  data = src.data;
66  width = src.width;
67  height = src.height;
68  }
69 
71  }
72 
74  void Release()
75  {
76  delete [] data;
77  data = 0;
78  }
79 
81  void Resize(unsigned int width, unsigned int height)
82  {
83  delete [] data;
84  this->width = width;
85  this->height = height;
86  data = new T[this->width * this->height]; // reserve new memory
87  }
88 
89  T & operator() (int i, int j) {
90  return data[i + j * width];
91  }
92  const T & operator() (int i, int j) const {
93  return data[i + j * width];
94  }
95 
99  T pixel_at(int x, int y) const
100  {
101  // TODO: NDEBUG
102  if(x<0 || y < 0 || x >=(int)this->width || y>=(int)this->height)
103  {
104  std::cerr << "pixel_at(" << x << ',' << y << ")" << std::endl;
105  throw std::runtime_error("pixel_at called with invalid parameters");
106  }
107  uint32_t acc = data[x + y * width];
108  if(x>0 && y>0) acc += data[(x-1) + (y-1) * width];
109  if(x>0) acc -= data[(x-1) + y * width];
110  if(y>0) acc -= data[x + (y-1) * width];
111  return acc;
112  }
113 
115  double interpolated_value_at(double x, double y) const {
116  int ix = (int) (x);
117  double mx = x - (double) ix;
118  int iy = (int) y;
119  double my = y - (double) iy;
120 
121  // clamping
122  if(ix<0) {
123  ix = 0;
124  mx = 0.0;
125  }
126  if(iy<0) {
127  iy = 0;
128  my = 0.0;
129  }
130  if(ix>=(int)width-1)
131  {
132  ix = width-2;
133  mx = 1.0;
134  }
135  if(iy>=(int)height-1)
136  {
137  iy = height-2;
138  my = 1.0;
139  }
140 
141  return data[(ix+1)+(iy+1)*width] * mx * my +
142  data[ix + iy * width] * (1.0 - mx) * (1.0 - my) +
143  data[ix + (iy+1) * width] * (1.0 - mx) * my +
144  data[(ix+1) + iy * width] * mx * (1.0 - my);
145  }
146 
147 
155  template<class D>
156  void Export(D * buf, int x0, int y0, int dst_width, int dst_height) const
157  {
158  for(int j = 0; j<dst_height; ++j)
159  for(int i = 0; i<dst_width; ++i)
160  {
161  T val = pixel_at(x0 + i, y0 + j); // non molto ottimizzato al momento
162  if(val > std::numeric_limits<D>::max() )
163  val = std::numeric_limits<D>::max();
164  if(val < std::numeric_limits<D>::min() )
165  val = std::numeric_limits<D>::min();
166  buf[i + j * dst_width] = val;
167  }
168  }
169 
175  template<class DataType>
176  void ResampleAndExport(DataType * buf, double x0, double y0, double x1, double y1, int dst_width, int dst_height) const
177  {
178  const double dx = (x1 - x0) / (double) dst_width;
179  const double dy = (y1 - y0) / (double) dst_height;
180  const double norm = 1.0 / (dx*dy); // normalization factor
181 
182  // TODO: se non e' un extended_integral_image il codice e' leggermente differente.
183 // x0 += dx - 1.0;
184 // y0 += dy - 1.0;
185 
186  for(int j = 0; j<dst_height; ++j)
187  for(int i = 0; i<dst_width; ++i)
188  {
189  // +1 is added due to extended_integral_image
190  // the point (dx*i,dy*i) is generated by the pixel formed by the previous dx*dy area
191  double A = interpolated_value_at(x0 + i * dx + 1.0, y0 + j * dy + 1.0);
192  double B = interpolated_value_at(x0 + (i-1) * dx + 1.0, y0 + j * dy + 1.0);
193  double C = interpolated_value_at(x0 + i * dx + 1.0, y0 + (j-1) * dy + 1.0);
194  double D = interpolated_value_at(x0 + (i-1) * dx + 1.0, y0 + (j-1) * dy + 1.0);
195 
196  buf[i + j * dst_width] = norm*(A+D-B-C);
197  }
198  }
199 
201  template<class _S>
202  void Build(const _S *src, unsigned int width, unsigned int height, long stride, bool extend = false)
203  {
204  delete [] data; // release previous image
205 
206  if(extend)
207  {
208  this->width = width + 1;
209  this->height = height + 1;
210  }
211  else
212  {
213  this->width = width;
214  this->height = height;
215  }
216 
217  data = new T[this->width * this->height]; // reserve new memory
218 
219  T *i_data = data;
220  // first row only
221  T rs = T(0);
222 
223  if(extend) {
224  // [first row] and [first element] of second row are uninitialized and placed to 0.
225  for(unsigned int j=0; j<width+2; j++)
226  *i_data++ = T(0);
227  }
228 
229  // first row
230  for(unsigned int j=0; j<width; j++)
231  {
232  rs += src[j];
233  *i_data = rs;
234  i_data++;
235  }
236 
237  src += stride;
238  long prev_row = - (long) this->width;
239 
240  // remaining cells are sum above and to the left
241  for(unsigned int i=1; i<height; ++i)
242  {
243  rs = T(0);
244 
245  if(extend) {
246  *i_data++ = T(0);
247  }
248 
249  for(unsigned int j=0; j<width; ++j)
250  {
251  rs += src[j];
252  *i_data = rs + i_data[prev_row];
253  i_data++;
254  }
255 
256  src += stride;
257  }
258  }
259 
261  void Build(const ImageHandle & src, bool extend = false)
262  {
263  if(src.bpp == 1)
264  Build(src.data, src.width, src.height, src.stride, extend);
265  }
266 
267 };
268 
269 
275 template<class T>
276 void Resample(IntegralImageHandle<T> & dst, unsigned int dstWidth, unsigned int dstHeight, const IntegralImageHandle<T> & src, double u0, double v0, double du, double dv)
277 {
278  dst.Resize(dstWidth, dstHeight);
279 
280  double norm = 1.0 / (du*dv);
281 
282 // std::cout << "resample " << dstWidth << 'x' << dstHeight << ' ' << u0 << ' ' << v0 << ' ' <<du << ' ' << dv << std::endl;
283 
284  // equazione magica (believe, funziona!) leggere la documentazione dell'immagine integrale
285  u0 += du - 1.0;
286  v0 += dv - 1.0;
287 
288  const double w0 = 0.5; // TODO
289 
290  // check nel caso in cui du,dv < 1.0
291  int i0 = 0;
292  if(u0 < 0.0)
293  {
294  i0 = (int) ceil(-u0 / du);
295  u0 += i0 * du;
296  }
297 
298  int j0 = 0;
299  if(v0 < 0.0)
300  {
301  j0 = (int) ceil(-v0 / dv);
302  v0 += i0 * dv;
303  }
304 
305  double v = v0;
306 
307  // TODO: ora il bordo e' non inizializzato: usare del codice ad hoc per inizializzarlo
308 
309  for(unsigned int j=j0; j<dstHeight; ++j)
310  {
311  int iv = (int) trunc(v);
312  double mv = v - trunc(v);
313  double u = u0;
314  if(iv+1 < (int) src.height)
315  {
316  for(unsigned int i=i0; i<dstWidth; ++i)
317  {
318  // u = u0 + du *i;
319  int iu = (int) trunc(u);
320  double mu = u - trunc(u);
321 
322  const T *ptr = &src.data[ iu + iv * src.width];
323 
324  double t = norm * ( (double) ptr[0] * (1.0 - mu) * (1.0 - mv) + (double) ptr[1] * (mu) * (1.0 - mv) +
325  (double) ptr[src.width] * (1.0 - mu) * (mv) + (double) ptr[src.width + 1] * (mu) * (mv) );
326 
327  dst.data[i + dst.width *j] = (T) (t + w0);
328 
329  u += du;
330  }
331  }
332  else
333  {
334  // last row, to avoid buffer overflow
335  for(unsigned int i=i0; i<dstWidth; ++i)
336  {
337  // u = u0 + du *i;
338  int iu = (int) trunc(u);
339  double mu = u - trunc(u);
340 
341  const T *ptr = &src.data[ iu + iv * src.width];
342 
343  double t = norm * ( (iu+1 < (int) src.width) ? ( (double) ptr[0] * (1.0 - mu) + (double) ptr[1] * (mu) ) : ptr[0] );
344 
345  dst.data[i + dst.width *j] = (T) (t + w0);
346 
347  u += du;
348  }
349  }
350  v += dv;
351  }
352 
353 }
354 
355 
361 template<class T>
362 void Resample(const IntegralImageHandle<T> & src, IntegralImageHandle<T> & dst, const rect & srcRect, unsigned int dstWidth, unsigned int dstHeight)
363 {
364  double u0 = srcRect.x0;
365  double v0 = srcRect.y0;
366  double du = (double) (srcRect.x1 - srcRect.x0) / (double) dstWidth;
367  double dv = (double) (srcRect.y1 - srcRect.y0) / (double) dstHeight;
368 
369  Resample<T>(dst, dstWidth, dstHeight, src, u0,v0,du,dv);
370 }
371 
372 
374 template<class T>
376 public:
377  IntegralImage() { }
378  ~IntegralImage() {
380  }
381 };
382 
383 
384 #endif
T * data
Definition: IntegralImage.h:48
void Resize(unsigned int width, unsigned int height)
Resize (destructive) of buffer.
Definition: IntegralImage.h:81
Types involved in boosting.
unsigned int bpp
byte per pixel (1 for grayscale image, 2 for 16bit greyscale image, 3 for RGB/YUV/etc color image) ...
Definition: Image.h:37
Definition: Image.h:35
void Build(const ImageHandle &src, bool extend=false)
Build the integral image using an ImageHandle object.
Definition: IntegralImage.h:261
void ResampleAndExport(DataType *buf, double x0, double y0, double x1, double y1, int dst_width, int dst_height) const
Definition: IntegralImage.h:176
Definition: IntegralImage.h:375
void Export(D *buf, int x0, int y0, int dst_width, int dst_height) const
Definition: IntegralImage.h:156
void Resample(ImageHandle &out, const ImageHandle &in, const rect &area)
Crop and Resample an Image using IntegralImage algorithm.
long stride
line stride, the delta offset, in bytes, between two different scanline
Definition: Image.h:41
Definition: IntegralImage.h:45
IntegralImageHandle(const IntegralImageHandle< T > &src)
Definition: IntegralImage.h:56
method to hold an image
unsigned int width
image geometry
Definition: Image.h:39
unsigned int width
Definition: IntegralImage.h:50
double interpolated_value_at(double x, double y) const
recover using interpolation integral-image value in x,y
Definition: IntegralImage.h:115
a rectangle structure
Definition: Types.h:55
void Build(const _S *src, unsigned int width, unsigned int height, long stride, bool extend=false)
Build integral image from buffer.
Definition: IntegralImage.h:202
additional typedef, for portability under win32
T pixel_at(int x, int y) const
Definition: IntegralImage.h:99
void Release()
Definition: IntegralImage.h:74
unsigned char * data
initial address of the first pixel. It must be cast to correct format (uint8, uint16, rgb, etc etc)
Definition: Image.h:43