ldpk
ldpk_generic_radial_distortion_1d.h
Go to the documentation of this file.
1 #pragma once
2 
5 
6 #include <functional>
7 #include <ldpk/ldpk_error.h>
8 #include <ldpk/ldpk_power_ct.h>
9 #include <iostream>
10 #include <cmath>
11 
12 namespace ldpk
13  {
17  template <int N>
18  class generic_radial_distortion_1d:public std::unary_function<double,double>
19  {
20  public:
21  private:
22 // The coefficients
23  double _c[N];
24 // For the inverse mapping we have termination conditions
25  double _epsilon;
26 // After n_max_iter we give up. This should not happen.
27  int _n_max_iter;
28 // n_post_iter is the number of iterations we perform after epsilon is reached.
29  int _n_post_iter;
30 // For debugging: count iterations
31  mutable int _k_iter;
32 // For debugging: maximum number of iterations occured
33  mutable int _k_max_iter;
34 
35  void check_range(int i) const
36  {
37  if((i < 0) || (i >= N))
38  { throw error_index_out_of_range(i,0,N - 1); }
39  }
40  public:
42  {
43  _epsilon = 1e-6;
44  _n_max_iter = 20;
45  _n_post_iter = 2;
46  _k_iter = 0;
47  _k_max_iter = 0;
48 
49  for(int i = 0;i < N;++i)
50  { _c[i] = 0.0; }
51  }
53  double get_coeff(int i) const
54  {
55  check_range(i);
56  return _c[i];
57  }
59  void set_coeff(int i,double q)
60  {
61  check_range(i);
62  _c[i] = q;
63  }
66  { _k_max_iter = 0; }
69  int get_k_iter() const
70  { return _k_iter; }
73  int get_k_max_iter() const
74  { return _k_iter; }
77  int get_n_max_iter() const
78  { return _n_max_iter; }
81  int get_n_post_iter() const
82  { return _n_post_iter; }
84  double operator()(double r_dn) const
85  {
86 // Compute powers of r^2: 1,r^2,r^4,...,r^(2N)
87  double r2pow[N + 1];
88  double q(1.0),r2 = r_dn * r_dn;
89  power_ct<double,N + 1>().build(r2,r2pow);
90 
91  for(int i = 0;i < N;++i)
92  { q += _c[i] * r2pow[i + 1]; }
93  return r_dn * q;
94  }
96  double map_inverse(double q) const
97  {
98  double p = q - ((*this)(q) - q);
99 // Iterate until |f(p_iter) - q| < epsilon.
100 // We count the iterations for debugging purposes.
101  _k_iter = 0;
102  for(int i = 0;i < _n_max_iter;++i)
103  {
104  double q_iter = (*this)(p);
105  p = p + q - q_iter;
106  ++_k_iter;
107  double diff = ::fabs(q_iter - q);
108  if(diff < _epsilon)
109  { break; }
110  }
111 // We improve precision by post-iterations.
112  for(int i = 0;i < _n_post_iter;++i)
113  {
114  double q_iter = (*this)(p);
115  p = p + q - q_iter;
116  }
117 // k_max_iter counts the number of iterations for the worst case.
118  if(_k_iter > _k_max_iter)
119  { _k_max_iter = _k_iter; }
120  return p;
121  }
124  double map_inverse(double q,double p_start) const
125  {
126  double p = p_start;
127  for(_k_iter = 0;_k_iter < _n_max_iter;++_k_iter)
128  {
129 // A Newton iteration
130  double g = jacobi(p);
131  double q_cmp = (*this)(p);
132  p += (q - q_cmp) / g;
133  if(::fabs(q - q_cmp) < _epsilon)
134  { break; }
135  }
136 // We improve precision by post-iterations.
137  for(int i = 0;i < _n_post_iter;++i)
138  {
139 // A Newton iteration
140  double g = jacobi(p);
141  double q_cmp = (*this)(p);
142  p += (q - q_cmp) / g;
143  }
144 // k_max_iter counts the number of iterations for the worst case.
145  if(_k_iter > _k_max_iter)
146  { _k_max_iter = _k_iter; }
147  return p;
148  }
150  double jacobi(double r_dn) const
151  {
152 // Compute powers of r^2: 1,r^2,r^4,...,r^(2N)
153  double r2pow[N + 1];
154  double r2 = r_dn * r_dn;
155  power_ct<double,N + 1>().build(r2,r2pow);
156 
157  double qa(1.0),qb(0.0);
158  for(int i = 0;i < N;++i)
159  {
160  qa += _c[i] * r2pow[i + 1];
161  qb += _c[i] * (2 * i + 2) * r2pow[i];
162  }
163  return qa + r2 * qb;
164  }
165  std::ostream& out(std::ostream& cout) const
166  {
167  int p = cout.precision();
168  cout.precision(5);
169  for(int i = 0;i < N;++i)
170  { cout << " C(" << 2 * i + 2 << "): " << std::right << std::fixed << _c[i] << "\n"; }
171  cout.precision(p);
172  return cout;
173  }
174  };
175  }
176 
double map_inverse(double q) const
Inverse mapping by solving the fixed point equation without providing initial values.
Definition: ldpk_generic_radial_distortion_1d.h:96
void set_coeff(int i, double q)
Set coefficient c[i], 0 <= i < N.
Definition: ldpk_generic_radial_distortion_1d.h:59
Exception classes for ldpk.
Some index was out of range.
Definition: ldpk_error.h:30
int get_n_max_iter() const
User-defined maximum number of iterations applied in map_inverse in order to fulfill the termination ...
Definition: ldpk_generic_radial_distortion_1d.h:77
int get_k_iter() const
Number of iterations until epsilon was reached. This value is reset at the beginning of each iterativ...
Definition: ldpk_generic_radial_distortion_1d.h:69
A polynomial model with N coefficients for radially symmetric lenses. This class contains the model f...
Definition: ldpk_generic_radial_distortion_1d.h:18
The namespace of (most of the) things related to the Lens Distortion Plugin Kit.
Definition: ldpk.h:19
int get_n_post_iter() const
User-defined number of additional iterations to be applied when the termination condition is fulfille...
Definition: ldpk_generic_radial_distortion_1d.h:81
double operator()(double r_dn) const
Remove distortion. r_dn is a point (distance from center) in diagonally normalized coordinates...
Definition: ldpk_generic_radial_distortion_1d.h:84
Computing N powers of a given number, where N is a compile-time constant.
Definition: ldpk_power_ct.h:33
double jacobi(double r_dn) const
Jacobian. For the pure radial polynomial it&#39;s simply the derivative.
Definition: ldpk_generic_radial_distortion_1d.h:150
void reset_k_max_iter()
Reset k_max_iter for debugging purposes.
Definition: ldpk_generic_radial_distortion_1d.h:65
int get_k_max_iter() const
By this value you can check how much iterations per pixel were required to warp an entire image or se...
Definition: ldpk_generic_radial_distortion_1d.h:73
double get_coeff(int i) const
Get coefficient c[i], 0 <= i < N (i.e. coefficient power r^(2i))
Definition: ldpk_generic_radial_distortion_1d.h:53
double map_inverse(double q, double p_start) const
We expect that usually p_start=q is sufficient as starting value, since coefficients are low...
Definition: ldpk_generic_radial_distortion_1d.h:124