ldpk
ldpk_generic_distortion_base.h
Go to the documentation of this file.
1 #pragma once
2 
5 
6 #include <ldpk/ldpk_error.h>
7 #include <cmath>
8 #include <functional>
9 #include <iostream>
10 #include <vector>
11 
12 namespace ldpk
13  {
19  template <class VEC2,class MAT2,int N>
20  class generic_distortion_base:public std::unary_function<VEC2,VEC2>
21  {
22  private:
23  typedef VEC2 vec2_type;
24  typedef MAT2 mat2_type;
25 
26 // For the inverse mapping we have termination conditions
27  double _epsilon;
28 // After n_max_iter we give up. This should not happen.
29  int _n_max_iter;
30 // n_post_iter is the number of iterations we perform after
31 // epsilon is reached.
32  int _n_post_iter;
33 
34  protected:
36  void check_range(int i) const
37  {
38  if((i < 0) || (i >= N))
39  { throw error_index_out_of_range(i,0,N - 1); }
40  }
41  public:
43  {
44  _epsilon = 1e-6;
45  _n_max_iter = 20;
46  _n_post_iter = 2;
47  }
49  int get_num_parameters() const
50  { return N; }
53  void setup_map_inverse(int n_max_iter,int n_post_iter,double epsilon)
54  {
55  _n_max_iter = n_max_iter;
56  _n_post_iter = n_post_iter;
57  _epsilon = epsilon;
58  }
61  virtual void done()
62  { }
64  virtual double get_coeff(int i) const = 0;
65  virtual void set_coeff(int i,double) = 0;
68  int get_n_max_iter() const
69  { return _n_max_iter; }
72  int get_n_post_iter() const
73  { return _n_post_iter; }
75  virtual vec2_type operator()(const vec2_type& p) const = 0;
77  vec2_type eval(const vec2_type& p) const
78  { return (*this)(p); }
82  virtual mat2_type jacobi(const vec2_type& p_dn) const
83  {
84  const double epsilon = 1e-4;
85  return trans(mat2_type((eval(p_dn + vec2_type(epsilon,0)) - eval(p_dn - vec2_type(epsilon,0))) / (2.0 * epsilon),
86  (eval(p_dn + vec2_type(0,epsilon)) - eval(p_dn - vec2_type(0,epsilon))) / (2.0 * epsilon)));
87  }
89  virtual void derive(double* dg,int n_parameters,const vec2_type& p_dn) const
90  {
91  std::cout << "ldpk::generic_distortion_base::derive: not implemented" << std::endl;
92  }
95  virtual vec2_type map_inverse(const vec2_type& q) const
96  {
97  vec2_type p = q - ((*this)(q) - q);
98 // Iterate until |f(p_iter) - q| < epsilon.
99  for(int i = 0;i < _n_max_iter;++i)
100  {
101  vec2_type q_iter = (*this)(p);
102  p = p + q - q_iter;
103  double diff = norm2(q_iter - q);
104  if(diff < _epsilon)
105  { break; }
106  }
107 // We improve precision by a fixed number of post-iterations.
108  for(int i = 0;i < _n_post_iter;++i)
109  {
110  vec2_type q_iter = (*this)(p);
111  p = p + q - q_iter;
112  }
113  return p;
114  }
116  vec2_type map_inverse(const vec2_type& q,const vec2_type& p_start) const
117  {
118  vec2_type p = p_start;
119  for(int i = 0;i < _n_max_iter;++i)
120  {
121 // A Newton iteration
122  mat2_type g = jacobi(p);
123  vec2_type q_cmp(eval(p));
124  try
125  {
126  p += invert(g) * (q - q_cmp);
127  }
128  catch(...)
129  {
130  return vec2_type();
131  }
132  if(norm2(q - q_cmp) < 1e-8)
133  {
134  break;
135  }
136  }
137  return p;
138  }
142  virtual std::ostream& out(std::ostream& cout) const
143  { return cout; }
144  };
145  }
146 
int get_num_parameters() const
Number of parameters, that is N.
Definition: ldpk_generic_distortion_base.h:49
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:68
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:72
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:20
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:82
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:36
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:116
vec2_type eval(const vec2_type &p) const
Same as method instead of operator.
Definition: ldpk_generic_distortion_base.h:77
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:61
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:89
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:95
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:142
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:53