icub-basic-demos
FastGauss.cpp
Go to the documentation of this file.
1 // -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
2 
3 // Copyright: (C) 2006-2007 Alex Bernardino, ISR-IST
4 // Authors: Alex Bernardino
5 // CopyPolicy: Released under the terms of the GNU GPL v2.0.
6 
17 #include <string.h>
18 #include <iCub/FastGauss.h>
19 #include <iCub/IIRGausDeriv.h>
20 #include <iCub/IIRFilt.h>
21 
22 FastGauss::FastGauss(void)
23 {
24  //Initialization of constants and variables
25  m_i_lines = 0;
26  m_i_cols = 0;
27  stride = 0;
28  m_i_stridepix = 0;
29  temp = NULL;
30  m_scale = 0;
31  filt_poles = NULL;
32  filt_coeffs = NULL;
33  m_bAllocated = false;
34  m_resid_step = NULL;
35  m_resid_ic = NULL;
36 }
37 
38 FastGauss::~FastGauss(void)
39 {
40  FreeResources();
41 }
42 
43 bool FastGauss::IsAllocated()
44 {
45  return m_bAllocated;
46 }
47 long FastGauss::GetLines()
48 {
49  return m_i_lines;
50 }
51 
52 long FastGauss::GetCols()
53 {
54  return m_i_cols;
55 }
56 
57 
58 long FastGauss::GetStridePix()
59 {
60  return m_i_stridepix;
61 }
62 
63 double FastGauss::GetScale()
64 {
65  return m_scale;
66 }
67 
68 bool FastGauss::AllocateResources(long lines, long cols, double scale)
69 {
70  if(IsAllocated())
71  FreeResources();
72 
73  m_i_lines = lines;
74  m_i_cols = cols;
75 
76  if(scale < 0.5)
77  {
78  throw "Scale values lower than 0.5 are not alowed";
79  }
80  if(scale > 100)
81  {
82  throw "Danger: Bad Approximation for scale values higher than 100";
83  }
84  m_scale = scale;
85 
86  //allocation of level structures - filter poles, coefficients, residues
87  filt_poles = new complex<double>[5]; //max 5 complex poles
88  //filt_coeffs = (float*)malloc(6*sizeof(float)); //max 6 coeffs : 1 gain + 5 autoregressive terms
89  filt_coeffs = new float[6]; //max 6 coeffs : 1 gain + 5 autoregressive terms
90  //m_resid_step = (float*)malloc(3*sizeof(float));
91  m_resid_step = new float[3];
92  //m_resid_ic = (float*)malloc(9*sizeof(float));
93  m_resid_ic = new float[9];
94 
95  //allocation of image buffers for computations
96 
97  m_i_stridepix = m_i_cols;
98  stride = m_i_cols*4;
99  //temp = (float*)malloc(m_i_lines*m_i_cols*sizeof(float));
100  temp = new float[m_i_lines*m_i_cols];
101 
102  //compute filter poles, coefficients and boundary gaussian residues for each scale
103  calc_poles(3,m_scale,d0_N3_Linf, filt_poles);
104  calc_coeffs(3, filt_poles, filt_coeffs);
105  _compute_gauss3_resids(filt_poles, filt_coeffs, m_resid_ic, m_resid_step);
106 
107  m_bAllocated = true;
108  return true;
109 }
110 
111 bool FastGauss::FreeResources()
112 {
113  m_bAllocated = false;
114  if(m_resid_step != NULL)
115  {
116  //free(m_resid_step);
117  delete[] m_resid_step;
118  m_resid_step = NULL;
119  }
120 
121  if(m_resid_ic!= NULL)
122  {
123  //free(m_resid_ic);
124  delete[] m_resid_ic;
125  m_resid_ic = NULL;
126  }
127 
128  if(filt_coeffs != NULL)
129  {
130  //free(filt_coeffs);
131  delete[] filt_coeffs;
132  filt_coeffs = NULL;
133  }
134  if(filt_poles != NULL)
135  {
136  delete[] filt_poles;
137  filt_poles = NULL;
138  }
139 
140  if(temp != NULL)
141  //free(temp);
142  delete[] temp;
143 
144  temp = NULL;
145  return true;
146 }
147 
148 void FastGauss::_iir_gaussfilt3_horz(float * in, float * tempbuf, float * out, int width, int height, int stridepix, float *coeffs, float *resid_ic, float *resid_step)
149 {
150 
151  float i0[3]; //initial condition vector - to compute
152  int i,s,bi,bf;
153  float bi_val, bf_val;
154  s = stridepix;
155  //filtering rows
156  for(i = 0; i < height; i++)
157  {
158  bi = i*s;
159  bf = i*s+width-1;
160  bi_val = in[bi];
161  bf_val = in[bf];
162  //causal phase
163  //compute forward initial conditions (response to a step of bi_val amplitude)
164  compute_step_forward_ic(bi_val, coeffs, i0);
165 
166  /*mag = b0/(1+a1+a2+a3);
167  i0[0] = i0[1] = i0[2] = (float)(mag*bi_val);*/
168 
169  iir_filt_forward(in+bi,tempbuf,width,coeffs,i0);
170  //anticausal phase
171  i0[0] = tempbuf[width-1];
172  i0[1] = tempbuf[width-2];
173  i0[2] = tempbuf[width-3];
174 
175  compute_natural_backward_ic(resid_ic,i0);
176  add_step_backward_ic(resid_step,bf_val,i0);
177 
178  iir_filt_backward(tempbuf,out+bi,width,coeffs,i0);
179  }
180 }
181 
182 void FastGauss::_iir_gaussfilt3_vert(float * inout, float *tempbuf, int width, int height, int stridepix, float *coeffs, float *resid_ic, float *resid_step)
183 {
184 
185  //filter coefficients
186  float b0 = coeffs[0];
187  float a1 = coeffs[1];
188  float a2 = coeffs[2];
189  float a3 = coeffs[3];
190 
191  float i0[3]; //initial condition vector - to compute
192  int j,s,bi,bf;
193  float bi_val, bf_val;
194  s = stridepix;
195 
196  //filtering columns
197  for(j = 0; j < width; j++)
198  {
199  bi = j;
200  bf = (height-1)*s+j;
201  bi_val = inout[bi];
202  bf_val = inout[bf];
203  //causal phase
204  //compute forward initial conditions (response to a step of bi_val amplitude)
205  compute_step_forward_ic(bi_val, coeffs, i0);
206 
207  /*mag = b0/(1+a1+a2+a3);
208  i0[0] = i0[1] = i0[2] = (float)(mag*bi_val);*/
209 
210  iir_filt_forward(inout+bi,s,tempbuf,height,coeffs,i0);
211 
212  i0[0] = tempbuf[height-1];
213  i0[1] = tempbuf[height-2];
214  i0[2] = tempbuf[height-3];
215 
216  compute_natural_backward_ic(resid_ic,i0);
217  add_step_backward_ic(resid_step,bf_val,i0);
218 
219  iir_filt_backward(tempbuf,inout+bi,s,height,coeffs,i0);
220  }
221 }
222 
223 void FastGauss::_iir_gaussfilt3(float * in, float * out, float *tempbuf, int width, int height, int stridepix, float *coeffs, float *resid_ic, float *resid_step )
224 {
225  _iir_gaussfilt3_horz(in, tempbuf, out, width, height, stridepix, coeffs, resid_ic, resid_step);
226  _iir_gaussfilt3_vert(out, tempbuf, width, height, stridepix, coeffs, resid_ic, resid_step);
227 }
228 
229 bool FastGauss::GaussFilt(float * in, float * out)
230 {
231  if(!IsAllocated())
232  throw "Resources not allocated";
233 
234  int i;
235 
236  //copy image to internal buffer
237  for( i = 0; i < m_i_lines; i++ )
238  memcpy(in + i*m_i_stridepix, in + m_i_cols*i, m_i_cols*sizeof(float) );
239 
240  //computing the gaussian filtered image
241  _iir_gaussfilt3(in, out, temp, m_i_cols, m_i_lines, m_i_stridepix, filt_coeffs, m_resid_ic, m_resid_step );
242 
243  return true;
244 }
245 
246 void FastGauss::compute_step_forward_ic(float bord_val, float *coeffs, float *i0)
247 {
248  //filter coefficients
249  float b0 = coeffs[0];
250  float a1 = coeffs[1];
251  float a2 = coeffs[2];
252  float a3 = coeffs[3];
253 
254  i0[0] = i0[1] = i0[2] = bord_val*b0/(1+a1+a2+a3);
255 }
256 
257 void FastGauss::compute_natural_backward_ic( float *resid_ic, float *init_cond )
258 {
259  float i0 = init_cond[0];
260  float i1 = init_cond[1];
261  float i2 = init_cond[2];
262 
263  init_cond[0]=i0*resid_ic[0]+i1*resid_ic[1]+i2*resid_ic[2];
264  init_cond[1]=i0*resid_ic[3]+i1*resid_ic[4]+i2*resid_ic[5];
265  init_cond[2]=i0*resid_ic[6]+i1*resid_ic[7]+i2*resid_ic[8];
266 }
267 
268 void FastGauss::add_step_backward_ic( float *resid_step, float val, float *init_cond )
269 {
270  init_cond[0] += val*resid_step[0];
271  init_cond[1] += val*resid_step[1];
272  init_cond[2] += val*resid_step[2];
273 }
274 
275 void FastGauss::_compute_gauss3_resids( complex<double> filt_poles[], float *filt_coeffs, float *resid_ic, float *resid_step )
276 {
277 
278  complex <double> p1, p2, p3, _p1, _p2, _p3;
279  complex <double> p1_1, p1_2, p1_3, p2_1, p2_2, p2_3, p3_1, p3_2, p3_3;
280  double b0, a1, a2, a3;
281 
282  _p1 = filt_poles[0];
283  _p2 = filt_poles[1];
284  _p3 = filt_poles[2];
285  b0 = filt_coeffs[0];
286  a1 = filt_coeffs[1];
287  a2 = filt_coeffs[2];
288  a3 = filt_coeffs[3];
289 
290 
291  p1 = 1.0/_p1;
292  p2 = 1.0/_p2;
293  p3 = 1.0/_p3;
294  p1_1 = _p1;
295  p1_2 = p1_1*_p1;
296  p1_3 = p1_2*_p1;
297  p2_1 = _p2;
298  p2_2 = p2_1*_p2;
299  p2_3 = p2_2*_p2;
300  p3_1 = _p3;
301  p3_2 = p3_1*_p3;
302  p3_3 = p3_2*_p3;
303 
304  complex <double> res1a, res2a, res3a, res1b, res2b, res3b, res1c, res2c, res3c;
305  //a3 = -p1*p2*p3
306  res1a = b0/a3*p1_3/(1.0-p1_2)/(1.0-p1_1*(p2+p2_1)+p1_2)/(1.0-p1_1*(p3+p3_1)+p1_2);
307  res2a = b0/a3*p2_3/(1.0-p2_2)/(1.0-p2_1*(p1+p1_1)+p2_2)/(1.0-p2_1*(p3+p3_1)+p2_2);
308  res3a = b0/a3*p3_3/(1.0-p3_2)/(1.0-p3_1*(p2+p2_1)+p3_2)/(1.0-p3_1*(p1+p1_1)+p3_2);
309  res1b = p1_1*res1a;
310  res2b = p2_1*res2a;
311  res3b = p3_1*res3a;
312  res1c = p1_2*res1a;
313  res2c = p2_2*res2a;
314  res3c = p3_2*res3a;
315 
316  //initial condition residues
317  complex<double> r0, r1, r2, r3, r4, r5, r6, r7, r8;
318 
319  r0 = (-a1*res1a-a2*res1b-a3*res1c);
320  r1 = (-a2*res1a-a3*res1b);
321  r2 = (-a3*res1a);
322  r3 = (-a1*res2a-a2*res2b-a3*res2c);
323  r4 = (-a2*res2a-a3*res2b);
324  r5 = (-a3*res2a);
325  r6 = (-a1*res3a-a2*res3b-a3*res3c);
326  r7 = (-a2*res3a-a3*res3b);
327  r8 = (-a3*res3a);
328 
329  resid_ic[0] = (float)real(r0+r3+r6);
330  resid_ic[1] = (float)real(r1+r4+r7);
331  resid_ic[2] = (float)real(r2+r5+r8);
332  resid_ic[3] = (float)real(r0*p1+r3*p2+r6*p3);
333  resid_ic[4] = (float)real(r1*p1+r4*p2+r7*p3);
334  resid_ic[5] = (float)real(r2*p1+r5*p2+r8*p3);
335  resid_ic[6] = (float)real(r0*p1*p1+r3*p2*p2+r6*p3*p3);
336  resid_ic[7] = (float)real(r1*p1*p1+r4*p2*p2+r7*p3*p3);
337  resid_ic[8] = (float)real(r2*p1*p1+r5*p2*p2+r8*p3*p3);
338 
339  //step residues
340  complex <double> res1, res2, res3, res4;
341 
342  res1 = b0*res1a/(1.0-_p1);
343  res2 = b0*res2a/(1.0-_p2);
344  res3 = b0*res3a/(1.0-_p3);
345  res4 = b0*b0/(1+a1+a2+a3)/(1+a1+a2+a3);
346  resid_step[0] = (float)real(res1+res2+res3+res4);
347  resid_step[1] = (float)real(res1*p1+res2*p2+res3*p3+res4);
348  resid_step[2] = (float)real(res1*p1*p1+res2*p2*p2+res3*p3*p3+res4);
349 }
350 
351 
Implements 3 Tap IIR Gaussian Filtering with Boundary Conditions.
Functions for generic, 3 tap, iir filtering.
void iir_filt_forward(float *in, int stepin, float *out, int stepout, int length, float *coeffs, float *i0)
Functions iir_filt_forward and iir_filt_backward do a 3 tap recursive filtering operation on floating...
Definition: IIRFilt.cpp:19
Coefficients and poles of IIR Gaussian Derivative Filters (order 0, 1 and 2).
void calc_poles(int taps, const double scale, const complex< double > oldpoles[], complex< double > newpoles[])
5 tap second derivative filter with Linf norm approximation
void calc_coeffs(int taps, const complex< double > poles[], const double s, float *coeffs)
Compute the coefficients of the filter for scale s, given the poles at scale 2.
const complex< double > d0_N3_Linf[]
5 tap gaussian filter with L2 norm approximation