ldpk
ldpk_generic_distortion_base.h
Go to the documentation of this file.
1 #ifndef ldpk_generic_distortion_base_sdv
2 #define ldpk_generic_distortion_base_sdv
3 
6 
7 #include <ldpk/ldpk_error.h>
8 #include <cmath>
9 #include <functional>
10 #include <iostream>
11 #include <vector>
12 
13 namespace ldpk
14  {
20  template <class VEC2,class MAT2,int N>
21  class generic_distortion_base:public std::unary_function<VEC2,VEC2>
22  {
23  private:
24  typedef VEC2 vec2_type;
25  typedef MAT2 mat2_type;
26 
27 // For the inverse mapping we have termination conditions
28  double _epsilon;
29 // After n_max_iter we give up. This should not happen.
30  int _n_max_iter;
31 // n_post_iter is the number of iterations we perform after
32 // epsilon is reached.
33  int _n_post_iter;
34 // For debugging: count iterations
35  mutable int _k_iter;
36 // For debugging: maximum number of iterations occured
37  mutable int _k_max_iter;
38 // For debugging: value being compared to _epsilon.
39  mutable double _diff;
40 
41  protected:
43  void check_range(int i) const
44  {
45  if((i < 0) || (i >= N))
46  {
47  throw error_index_out_of_range(i,0,N - 1);
48  }
49  }
50  public:
52  {
53  _epsilon = 1e-6;
54  _n_max_iter = 20;
55  _n_post_iter = 2;
56  }
58  int get_num_parameters() const
59  { return N; }
62  void setup_map_inverse(int n_max_iter,int n_post_iter,double epsilon)
63  {
64  _n_max_iter = n_max_iter;
65  _n_post_iter = n_post_iter;
66  _epsilon = epsilon;
67  }
70  virtual void done()
71  { }
73  virtual double get_coeff(int i) const = 0;
74  virtual void set_coeff(int i,double) = 0;
75 
78  { _k_max_iter = 0; }
81  int get_k_iter() const
82  { return _k_iter; }
85  int get_k_max_iter() const
86  { return _k_iter; }
89  int get_n_max_iter() const
90  { return _n_max_iter; }
93  int get_n_post_iter() const
94  { return _n_post_iter; }
99  double get_diff() const
100  { return _diff; }
102  virtual vec2_type operator()(const vec2_type& p) const = 0;
104  vec2_type eval(const vec2_type& p) const
105  { return (*this)(p); }
109  virtual mat2_type jacobi(const vec2_type& p_dn) const
110  {
111  const double epsilon = 1e-4;
112  return trans(mat2_type((eval(p_dn + vec2_type(epsilon,0)) - eval(p_dn - vec2_type(epsilon,0))) / (2.0 * epsilon),
113  (eval(p_dn + vec2_type(0,epsilon)) - eval(p_dn - vec2_type(0,epsilon))) / (2.0 * epsilon)));
114  }
116  virtual void derive(double* dg,int n_parameters,const vec2_type& p_dn) const
117  {
118  std::cout << "ldpk::generic_distortion_base::derive: not implemented" << std::endl;
119  }
122  virtual vec2_type map_inverse(const vec2_type& q) const
123  {
124  vec2_type p = q - ((*this)(q) - q);
125 // Iterate until |f(p_iter) - q| < epsilon.
126 // We count the iterations for debugging purposes.
127  _k_iter = 0;
128  for(int i = 0;i < _n_max_iter;++i)
129  {
130  vec2_type q_iter = (*this)(p);
131  p = p + q - q_iter;
132  ++_k_iter;
133  _diff = norm2(q_iter - q);
134  if(_diff < _epsilon)
135  {
136  break;
137  }
138  }
139 // We improve precision by post-iterations.
140  for(int i = 0;i < _n_post_iter;++i)
141  {
142  vec2_type q_iter = (*this)(p);
143  p = p + q - q_iter;
144  }
145 // k_max_iter counts the number of iterations for the worst case.
146  if(_k_iter > _k_max_iter)
147  {
148  _k_max_iter = _k_iter;
149  }
150  return p;
151  }
153  vec2_type map_inverse(const vec2_type& q,const vec2_type& p_start) const
154  {
155  vec2_type p = p_start;
156  for(_k_iter = 0;_k_iter < 20;++_k_iter)
157  {
158 // A Newton iteration
159  mat2_type g = jacobi(p);
160  vec2_type q_cmp(eval(p));
161  try
162  {
163  p += invert(g) * (q - q_cmp);
164  }
165  catch(...)
166  {
167  return vec2_type();
168  }
169  if(norm2(q - q_cmp) < 1e-8)
170  {
171  break;
172  }
173  }
174 // k_max_iter counts the number of iterations for the worst case.
175  if(_k_iter > _k_max_iter)
176  {
177  _k_max_iter = _k_iter;
178  }
179  return p;
180  }
184  virtual std::ostream& out(std::ostream& cout) const
185  { return cout; }
186  };
187  }
188 
189 #endif
int get_num_parameters() const
Number of parameters, that is N.
Definition: ldpk_generic_distortion_base.h:58
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_distortion_base.h:89
int get_n_post_iter() const
User-defined number of additional iterations to be applied when the termination condition is fulfille...
Definition: ldpk_generic_distortion_base.h:93
Exception classes for ldpk.
Base class for a distortion model with N parameters. You may find it useful to derive your own distor...
Definition: ldpk_generic_distortion_base.h:21
virtual mat2_type jacobi(const vec2_type &p_dn) const
Jacobi-Matrix. The result is a matrix g_{ij} = d/dp_j f(p)_i, where f represents the undistort-functi...
Definition: ldpk_generic_distortion_base.h:109
Some index was out of range.
Definition: ldpk_error.h:30
void check_range(int i) const
A derived class may check if the index is valid.
Definition: ldpk_generic_distortion_base.h:43
vec2_type map_inverse(const vec2_type &q, const vec2_type &p_start) const
For given q, we are looking for p so that f(p) = q. p_start is near to p.
Definition: ldpk_generic_distortion_base.h:153
vec2_type eval(const vec2_type &p) const
Same as method instead of operator.
Definition: ldpk_generic_distortion_base.h:104
virtual double get_coeff(int i) const =0
There must be methods to address coefficients by one single index i in [0,N[.
virtual void done()
After changing one or more coefficients of the model, call this (future use). The derived class may p...
Definition: ldpk_generic_distortion_base.h:70
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_distortion_base.h:81
virtual vec2_type operator()(const vec2_type &p) const =0
Remove distortion. This method is non-iterative.
virtual void derive(double *dg, int n_parameters, const vec2_type &p_dn) const
Not all distortion functions will support this.
Definition: ldpk_generic_distortion_base.h:116
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_distortion_base.h:85
virtual vec2_type map_inverse(const vec2_type &q) const
Inverse mapping by solving the fixed point equation without providing initial values. Virtual, because the derived class might use some smart data structure for calculating an initial value.
Definition: ldpk_generic_distortion_base.h:122
double get_diff() const
Difference between is-value and should-be-value in map_inverse(). Inverse mapping is implemented as f...
Definition: ldpk_generic_distortion_base.h:99
virtual std::ostream & out(std::ostream &cout) const
The derived class implements a method for printing values inside 3DE4's matrix tool dialog...
Definition: ldpk_generic_distortion_base.h:184
void setup_map_inverse(int n_max_iter, int n_post_iter, double epsilon)
Configure iterative procedure for map_inverse(). Call this, if you don't agree with the default value...
Definition: ldpk_generic_distortion_base.h:62
void reset_k_max_iter()
Reset k_max_iter for debugging purposes.
Definition: ldpk_generic_distortion_base.h:77