ldpk
ldpk_radial_decentered_distortion.h
Go to the documentation of this file.
1 #pragma once
2 
5 
7 #include <iostream>
8 
9 namespace ldpk
10  {
13  template <class VEC2,class MAT2>
15  {
16  public:
18  typedef VEC2 vec2_type;
19  typedef MAT2 mat2_type;
20  private:
21 // union allows to access coefficients by index.
22  union
23  {
24  struct
25  {
26  double _c2,_u2,_v2;
27  double _c4,_u4,_v4;
28  };
29  double _c[6];
30  };
31  public:
33  {
34  _c2 = _u2 = _v2 = 0.0;
35  _c4 = _u4 = _v4 = 0.0;
36  }
38  double get_coeff(int i) const
39  {
41  return _c[i];
42  }
44  void set_coeff(int i,double q)
45  {
47  _c[i] = q;
48  }
50  vec2_type operator()(const vec2_type& p_dn) const
51  {
52  double x_dn,y_dn;
53  double x = p_dn[0];
54  double y = p_dn[1];
55  double x2 = x * x;
56  double y2 = y * y;
57  double xy = x * y;
58  double r2 = x2 + y2;
59  double r4 = r2 * r2;
60  x_dn = x * (1.0 + _c2 * r2 + _c4 * r4)
61  + (r2 + 2.0 * x2) * (_u2 + _u4 * r2)
62  + 2.0 * xy * (_v2 + _v4 * r2);
63 
64  y_dn = y * (1.0 + _c2 * r2 + _c4 * r4)
65  + (r2 + 2.0 * y2) * (_v2 + _v4 * r2)
66  + 2.0 * xy * (_u2 + _u4 * r2);
67  return vec2_type(x_dn,y_dn);
68  }
71  mat2_type jacobi(const vec2_type& p_dn) const
72  {
73  mat2_type m;
74  double x = p_dn[0];
75  double y = p_dn[1];
76  double x2 = x * x;
77  double y2 = y * y;
78  double x3 = x2 * x;
79  double y3 = y2 * y;
80  double xy = x * y;
81  double x2y = xy * x;
82  double xy2 = xy * y;
83  double r2 = x2 + y2;
84 
85 // original implementation as in the document.
86 // m[0][0] = 1 + _c2 * (3.0 * x2 + y2) + _c4 * (5.0 * x2 + y2) * r2
87 // + 6.0 * _u2 * x + _u4 * (8.0 * xy2 + 12.0 * x3)
88 // + 2.0 * _v2 * y + _v4 * (2.0 * y3 + 6.0 * x2y);
89 // m[1][1] = 1 + _c2 * (x2 + 3.0 * y2) + _c4 * (x2 + 5.0 * y2) * r2
90 // + 6.0 * _v2 * y + _v4 * (8.0 * x2y + 12.0 * y3)
91 // + 2.0 * _u2 * x + _u4 * (2.0 * x3 + 6.0 * xy2);
92 //
93 // m[0][1] = 2.0 * _c2 * xy + 4.0 * _c4 * xy * r2
94 // + 2.0 * _u2 * y + _u4 * (8.0 * x2y + 4.0 * y3)
95 // + 2.0 * _v2 * x + _v4 * (2.0 * x3 + 6.0 * xy2);
96 // m[1][0] = 2.0 * _c2 * xy + 4.0 * _c4 * xy * r2
97 // + 2.0 * _u2 * y + _u4 * (6.0 * x2y + 2.0 * y3)
98 // + 2.0 * _v2 * x + _v4 * (4.0 * x3 + 8.0 * xy2);
99 // slightly condensed implementation
100  double u2x = _u2 * x;
101  double v2y = _v2 * y;
102  double c4r2 = _c4 * r2;
103  m[0][0] = 1.0 + _c2 * (3.0 * x2 + y2) + c4r2 * (5.0 * x2 + y2)
104  + 6.0 * u2x + _u4 * (8.0 * xy2 + 12.0 * x3)
105  + 2.0 * v2y + _v4 * (2.0 * y3 + 6.0 * x2y);
106  m[1][1] = 1.0 + _c2 * (x2 + 3.0 * y2) + c4r2 * (x2 + 5.0 * y2)
107  + 6.0 * v2y + _v4 * (8.0 * x2y + 12.0 * y3)
108  + 2.0 * u2x + _u4 * (2.0 * x3 + 6.0 * xy2);
109 
110  double m_off_diag_common = 2.0 * _c2 * xy + 4.0 * _c4 * xy * r2
111  + 2.0 * _u2 * y + 2.0 * _v2 * x;
112  m[0][1] = m_off_diag_common
113  + _u4 * (8.0 * x2y + 4.0 * y3)
114  + _v4 * (2.0 * x3 + 6.0 * xy2);
115  m[1][0] = m_off_diag_common
116  + _u4 * (6.0 * x2y + 2.0 * y3)
117  + _v4 * (4.0 * x3 + 8.0 * xy2);
118 
119  return m;
120  }
123  void derive(double* dg,int n_parameters,const vec2_type& p_dn) const
124  {
125  int size = 2 * n_parameters;
126  double x = p_dn[0];
127  double y = p_dn[1];
128  double x2 = p_dn[0] * p_dn[0];
129  double y2 = p_dn[1] * p_dn[1];
130  double xy = p_dn[0] * p_dn[1];
131  double r2 = x2 + y2;
132  double r4 = r2 * r2;
133 
134  int k = 0;
135 // c2
136  dg[k++] = x * r2;
137  dg[k++] = y * r2;
138  if(k == size) return;
139 // u2
140  dg[k++] = r2 + 2.0 * x2;
141  dg[k++] = 2.0 * xy;
142  if(k == size) return;
143 // v2
144  dg[k++] = 2.0 * xy;
145  dg[k++] = r2 + 2.0 * y2;
146  if(k == size) return;
147 // c4
148  dg[k++] = x * r4;
149  dg[k++] = y * r4;
150  if(k == size) return;
151 // u4
152  dg[k++] = r2 * (r2 + 2.0 * x2);
153  dg[k++] = 2.0 * r2 * xy;
154  if(k == size) return;
155 // v4
156  dg[k++] = 2.0 * r2 * xy;
157  dg[k++] = r2 * (r2 + 2.0 * y2);
158  if(k == size) return;
159 // Unreachable
160  std::cerr << "radial_decentered_distortion: n_parameters out of range" << std::endl;
161  }
162  std::ostream& out(std::ostream& cout) const
163  {
164  int p = int(cout.precision());
165  cout.precision(5);
166  cout << "c2: " << _c2 << std::endl;
167  cout << "u2: " << _u2 << std::endl;
168  cout << "v2: " << _v2 << std::endl;
169  cout << "c4: " << _c4 << std::endl;
170  cout << "u4: " << _u4 << std::endl;
171  cout << "v4: " << _v4 << std::endl;
172  cout.precision(p);
173  return cout;
174  }
175  };
176  }
177 
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
void check_range(int i) const
A derived class may check if the index is valid.
Definition: ldpk_generic_distortion_base.h:36
The namespace of (most of the) things related to the Lens Distortion Plugin Kit.
Definition: ldpk.h:19
Base class for distortion models.
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_radial_decentered_distortion.h:162
void derive(double *dg, int n_parameters, const vec2_type &p_dn) const
Derivative wrt distortion coefficients. dg points to an array with N / 2 Elements.
Definition: ldpk_radial_decentered_distortion.h:123
mat2_type jacobi(const vec2_type &p_dn) const
Analytic version of the Jacobi-matrix, about two times faster than the base class version which uses ...
Definition: ldpk_radial_decentered_distortion.h:71
void set_coeff(int i, double q)
Set coefficient c[i], 0 <= i < 6.
Definition: ldpk_radial_decentered_distortion.h:44
double get_coeff(int i) const
Get coefficient c[i], 0 <= i < 6.
Definition: ldpk_radial_decentered_distortion.h:38
vec2_type operator()(const vec2_type &p_dn) const
Remove distortion. p_dn is a point in diagonally normalized coordinates.
Definition: ldpk_radial_decentered_distortion.h:50
A polynomial radially symmetric model of degree 4 with decentering. This is the distortion model for ...
Definition: ldpk_radial_decentered_distortion.h:14