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  { throw error_index_out_of_range(i,0,N - 1); }
47  }
48  public:
50  {
51  _epsilon = 1e-6;
52  _n_max_iter = 20;
53  _n_post_iter = 2;
54  }
56  int get_num_parameters() const
57  { return N; }
60  void setup_map_inverse(int n_max_iter,int n_post_iter,double epsilon)
61  {
62  _n_max_iter = n_max_iter;
63  _n_post_iter = n_post_iter;
64  _epsilon = epsilon;
65  }
68  virtual void done()
69  { }
71  virtual double get_coeff(int i) const = 0;
72  virtual void set_coeff(int i,double) = 0;
73 
76  { _k_max_iter = 0; }
79  int get_k_iter() const
80  { return _k_iter; }
83  int get_k_max_iter() const
84  { return _k_iter; }
87  int get_n_max_iter() const
88  { return _n_max_iter; }
91  int get_n_post_iter() const
92  { return _n_post_iter; }
97  double get_diff() const
98  { return _diff; }
100  virtual vec2_type operator()(const vec2_type& p) const = 0;
102  vec2_type eval(const vec2_type& p) const
103  { return (*this)(p); }
107  virtual mat2_type jacobi(const vec2_type& p_dn) const
108  {
109  const double epsilon = 1e-4;
110  return trans(mat2_type((eval(p_dn + vec2_type(epsilon,0)) - eval(p_dn - vec2_type(epsilon,0))) / (2.0 * epsilon),
111  (eval(p_dn + vec2_type(0,epsilon)) - eval(p_dn - vec2_type(0,epsilon))) / (2.0 * epsilon)));
112  }
114  virtual void derive(double* dg,int n_parameters,const vec2_type& p_dn) const
115  {
116  std::cout << "ldpk::generic_distortion_base::derive: not implemented" << std::endl;
117  }
120  virtual vec2_type map_inverse(const vec2_type& q) const
121  {
122  vec2_type p = q - ((*this)(q) - q);
123 // Iterate until |f(p_iter) - q| < epsilon.
124 // We count the iterations for debugging purposes.
125  _k_iter = 0;
126  for(int i = 0;i < _n_max_iter;++i)
127  {
128  vec2_type q_iter = (*this)(p);
129  p = p + q - q_iter;
130  ++_k_iter;
131  _diff = norm2(q_iter - q);
132  if(_diff < _epsilon)
133  {
134  break;
135  }
136  }
137 // We improve precision by post-iterations.
138  for(int i = 0;i < _n_post_iter;++i)
139  {
140  vec2_type q_iter = (*this)(p);
141  p = p + q - q_iter;
142  }
143 // k_max_iter counts the number of iterations for the worst case.
144  if(_k_iter > _k_max_iter)
145  {
146  _k_max_iter = _k_iter;
147  }
148  return p;
149  }
151  vec2_type map_inverse(const vec2_type& q,const vec2_type& p_start) const
152  {
153  vec2_type p = p_start;
154  for(_k_iter = 0;_k_iter < _n_max_iter;++_k_iter)
155  {
156 // A Newton iteration
157  mat2_type g = jacobi(p);
158  vec2_type q_cmp(eval(p));
159  try
160  {
161  p += invert(g) * (q - q_cmp);
162  }
163  catch(...)
164  {
165  return vec2_type();
166  }
167  if(norm2(q - q_cmp) < 1e-8)
168  {
169  break;
170  }
171  }
172 // k_max_iter counts the number of iterations for the worst case.
173  if(_k_iter > _k_max_iter)
174  {
175  _k_max_iter = _k_iter;
176  }
177  return p;
178  }
182  virtual std::ostream& out(std::ostream& cout) const
183  { return cout; }
184  };
185  }
186 
187 #endif
int get_num_parameters() const
Number of parameters, that is N.
Definition: ldpk_generic_distortion_base.h:56
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:87
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:91
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:107
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:151
vec2_type eval(const vec2_type &p) const
Same as method instead of operator.
Definition: ldpk_generic_distortion_base.h:102
virtual double get_coeff(int i) const =0
There must be methods to address coefficients by one single index i in [0,N[.
The namespace of (most of the) things related to the Lens Distortion Plugin Kit.
Definition: ldpk.h:19
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:68
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:79
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:114
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:83
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:120
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:97
virtual std::ostream & out(std::ostream &cout) const
The derived class implements a method for printing values inside 3DE4&#39;s matrix tool dialog...
Definition: ldpk_generic_distortion_base.h:182
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&#39;t agree with the default value...
Definition: ldpk_generic_distortion_base.h:60
void reset_k_max_iter()
Reset k_max_iter for debugging purposes.
Definition: ldpk_generic_distortion_base.h:75