cgv
Loading...
Searching...
No Matches
camera.h
1#pragma once
2
3#include <vector>
4#include <cgv/math/fvec.h>
5#include <cgv/math/fmat.h>
6#include <cgv/math/mat.h>
7#include <cgv/math/pose.h>
8#include <cgv/math/ftransform.h>
9#include <cgv/math/inv.h>
10#include "lib_begin.h"
11
12namespace cgv {
13 namespace math {
14/*
15point constraint: (u,v,1) <-> (x,y,1)
16 -x h_4 - y h_5 - h_6 + v*x h_7 + v*y h_8 + v h_9,
17 x h_1 + y h_2 + h_3 - u*x h_7 - u*y h_8 - u h_9,
18-v*x h_1 - v*y h_2 - v h_3 + u*x h_4 + u*y h_5 + u h_6
19
20Input to Algebra System:
21{ {h_1, h_2,h_3}, {h_4, h_5,h_6}, {h_7, h_8,h_9} } . {x, y, z}
22{u,v,w} cross (x h_1 + y h_2 + z h_3, x h_4 + y h_5 + z h_6, x h_7 + y h_8 + z h_9)
23point constraint: (u,v,w) <-> (x,y,z)
24 -w*x h_4 -w*y h_5 -w*z h_6 +v*x h_7 +v*y h_8 +v*z h_9
25 w*x h_1 w*y h_2 +w*z h_3 -u*x h_7 -u*y h_8 -u*z h_9
26-v*x h_1 -v*y h_2 -v*z h_3 +u*x h_4 +u*y h_5 +u*z h_6
27
28line constraint: (d,e,f) <-> (a,b,c)
29 - c*d h_2 + b*d h_3 - c*e h_5 + b*e h_6 - c*f h_8 + b*f h_9
30 c*d h_1 - a*d h_3 + c*e h_4 - a*e h_6 + c*f h_7 - a*f h_9
31-b*d h_1 + a*d h_2 - b*e h_4 + a*e h_5 - b*f h_7 + a*f h_8
32
33point constraint: (u,v,1) <-> (x,y,1)
34 0, 0, 0, -x, -y,-1, v*x, v*y, v
35 x, y, 1, 0, 0, 0,-u*x,-u*y,-u
36-v*x,-v*y,-v,u*x,u*y, u, 0, 0, 0
37
38point constraint: (u,v,w) <-> (x,y,z)
39 0, 0, 0,-w*x,-w*y,-w*z, v*x, v*y, v*z
40 w*x, w*y, w*z, 0, 0, 0,-u*x,-u*y,-u*z
41-v*x,-v*y,-v*z, u*x, u*y, u*z, 0, 0, 0
42
43line constraint: (d,e,f) <-> (a,b,c)
44 0,-c*d, b*d, 0,-c*e, b*e, 0,-c*f, b*f
45 c*d, 0,-a*d, c*e, 0,-a*e, c*f, 0,-a*f
46-b*d, a*d, 0,-b*e, a*e, 0,-b*f, a*f, 0
47
48check of formula in Zhang's paper
49KC = {{S,H,X},{0,T,Y},{0,0,1}}
50KC = {{s,h,x},{0,t,y},{0,0,a}}={{a S,a H,a X},{0,a T,a Y},{0,0,a}}
51KC^(-1)={{1/s,-h/(s t)),(h y-t x)/(s t a)},{0,1/t,-y/(t a)}, {0,0,1/a}}
52B = l*KC^(-T)*KC^(-1) with l=a^(-2)
53
54B11 = s^(-2)
55B12 = -(h/(s^2 t))
56B13 = (-(t x) + h y)/(a s^2 t)
57B22 = t^(-2) + (h^2)/(s^2 t^2)
58B23 = -(y/(a t^2)) - (h (-(t x) + h y))/(a s^2 t^2)
59B33 = a^(-2) + (y^2)/(a^2 t^2) + ((-(t x) + h y)^2)/(a^2 s^2 t^2)
60
61a1 = x/(a s^2 t^2) = B12 B23 - B13 B22 = (-(h/(s^2 t)))(-(y/(a t^2)) - (h (-(t x) + h y))/(a s^2 t^2))-((-(t x) + h y)/(a s^2 t))(t^(-2) + (h^2)/(s^2 t^2))
62a2 = 1/(s^2 t^2) = B11 B22 - B12^2 = (s^(-2))(t^(-2) + (h^2)/(s^2 t^2))-(-(h/(s^2 t)))^2
63a3 = y/(a s^2 t^2) = B12 B13 - B11 B23 = (-(h/(s^2 t)))((-(t x) + h y)/(a s^2 t))-(s^(-2))(-(y/(a t^2)) - (h (-(t x) + h y))/(a s^2 t^2))
64
65X = x/a = a1/a2
66Y = y/a = a3/a2
67l = 1/a^2 = B33 - (B13^2+Y*a3)/B11 = a^(-2) + (y^2)/(a^2 t^2) + ((-(t x) + h y)^2)/(a^2 s^2 t^2) - (((-(t x) + h y)/(a s^2 t))^2 + (y/a)(y/(a s^2 t^2)))/(s^(-2))
68S = s/a = sqrt(l/B11) = sqrt(a^(-2) s^2)
69T = t/a = sqrt(l*B11/a2) = sqrt(a^(-2) s^(-2) s^2 t^2)
70H = h/a = -sqrt(l B12^2/(B11 a2)) = sqrt(a^(-2) h^2 s^(-4) t^(-2) s^2 s^2 t^2) = -+h/a
71
72special case S=T:
73KC = {{s,h,x},{0,t,y},{0,0,a}}
74KC^(-1)={{1/s,-h/(s^2),(h y-s x)/(s^2 a)},{0,1/s,-y/(s a)},{0,0,1/a}}
75B11=s^(-2)
76B12=-(h/s^3)
77B13=(-(s x) + h y)/(a s^3)
78B22=h^2/s^4 + s^(-2)
79B23=-(y/(a s^2)) - (h (-(s x) + h y))/(a s^4)
80B33=a^(-2) + y^2/(a^2 s^2) + (-(s x) + h y)^2/(a^2 s^4)
81
82a1 = x/(a s^4) = B12 B23 - B13 B22
83a2 = 1/(s^4) = B11 B22 - B12^2
84a3 = y/(a s^4) = B12 B13 - B11 B23
85
86X = x/a = a1/a2
87Y = y/a = a3/a2
88l = 1/a^2 = B33 - (B13^2+Y*a3)/B11 = a^(-2) + (y^2)/(a^2 t^2) + ((-(t x) + h y)^2)/(a^2 s^2 t^2) - (((-(t x) + h y)/(a s^2 t))^2 + (y/a)(y/(a s^2 t^2)))/(s^(-2))
89S = s/a = sqrt(l/B11) = sqrt(a^(-2) s^2)
90T = t/a = sqrt(l*B11/a2) = sqrt(a^(-2) s^(-2) s^2 t^2)
91H = h/a = -sqrt(l B12^2/(B11 a2)) = sqrt(a^(-2) h^2 s^(-4) t^(-2) s^2 s^2 t^2) = -+h/a
92
93special case h=0:
94KC^(-1)={{1/s,0,(-x)/(s a)},{0,1/t,-y/(t a)}, {0,0,1/a}}
95B11=s^(-2)
96B12=0
97B13=-(x/(a s^2))
98B22=t^(-2)
99B23=-(y/(a t^2))
100B33=a^(-2) + x^2/(a^2 s^2) + y^2/(a^2 t^2)}}
101
102a1 = x/(a s^2 t^2) = - B13 B22 = x/(a s^2 t^2)
103a2 = 1/(s^2 t^2) = B11 B22 = (s^(-2))(t^(-2))
104a3 = y/(a s^2 t^2) = - B11 B23 = x/(a s^2 t^2)
105
106X = x/a = a1/a2
107Y = y/a = a3/a2
108l = 1/a^2 = B33 - (B13^2+Y*a3)/B11
109S = s/a = sqrt(l/B11) = sqrt(a^(-2) s^2)
110T = t/a = sqrt(l*B11/a2) = sqrt(a^(-2) s^(-2) s^2 t^2)
111H = h/a = 0
112
113special case h=0 and S=T:
114KC^(-1)={{1/s,0,(-x)/(s a)},{0,1/s,-y/(s a)}, {0,0,1/a}}
115B11=s^(-2)
116B12=0
117B13=-(x/(a s^2))
118B22=s^(-2)
119B23=-(y/(a s^2))
120B33=a^(-2) + x^2/(a^2 s^2) + y^2/(a^2 s^2)}}
121
122a1 = x/(a s^4) = - B13 B22 = x/(a s^2 t^2)
123a2 = 1/(s^4) = B11 B22 = (s^(-2))(t^(-2))
124a3 = y/(a s^4) = - B11 B23 = x/(a s^2 t^2)
125
126X = x/a = a1/a2
127Y = y/a = a3/a2
128l = 1/a^2 = B33 - (B13^2+Y*a3)/B11
129S = s/a = sqrt(l/B11) = sqrt(a^(-2) s^2)
130T = t/a = sqrt(l*B11/a2) = sqrt(a^(-2) s^(-2) s^2 t^2)
131H = h/a = 0
132*/
133
134// compute homography from point to point correspondences and return whether this was possible
135template <typename T>
136bool compute_homography_from_constraint_matrix(const mat<T>& A, fmat<T,3,3>& H)
137{
138 assert(A.ncols() == 9);
139 mat<T> U, V;
140 diag_mat<T> W;
141 if (!svd(A, U, W, V, true))
142 return false;
143 vec<T> v = V.col(8);
144 H(0,0) = v(0);
145 H(0,1) = v(1);
146 H(0,2) = v(2);
147 H(1,0) = v(3);
148 H(1,1) = v(4);
149 H(1,2) = v(5);
150 H(2,0) = v(6);
151 H(2,1) = v(7);
152 H(2,2) = v(8);
153 return true;
154}
155// compute homography from pixel \c ui to 2D point \c xi correspondences and return whether this was possible
156template <typename T>
157bool compute_homography_from_2D_point_correspondences(const std::vector<fvec<T, 2>>& ui, const std::vector<fvec<T, 2>>& xi, fmat<T, 3, 3>& H)
158{
159 assert(ui.size() == xi.size());
160 mat<T> A(3*ui.size(), 9);
161 A.zeros();
162 for (size_t i = 0; i < ui.size(); ++i) {
163 const T& u = ui[i].x();
164 const T& v = ui[i].y();
165 const T& x = xi[i].x();
166 const T& y = xi[i].y();
167 size_t j=3*i;
168 A(j,3) = -x;
169 A(j,4) = -y;
170 A(j,5) = T(-1);
171 A(j,6) = v * x;
172 A(j,7) = v * y;
173 A(j,8) = v;
174 ++j;
175 A(j,0) = x;
176 A(j,1) = y;
177 A(j,2) = T(1);
178 A(j,6) = -u * x;
179 A(j,7) = -u * y;
180 A(j,8) = -u;
181 ++j;
182 A(j,0) = -v*x;
183 A(j,1) = -v*y;
184 A(j,2) = -v;
185 A(j,3) = u * x;
186 A(j,4) = u * y;
187 A(j,5) = u;
188 }
189 return compute_homography_from_constraint_matrix(A, H);
190}
191// compute homography from 3D homogenous pixels \c ui to 3D point \c xi correspondences and return whether this was possible
192template <typename T>
193bool compute_homography_from_3D_point_correspondences(const std::vector<fvec<T,3>>& ui, const std::vector<fvec<T,3>>& xi, fmat<T,3,3>& H)
194{
195 assert(ui.size() == xi.size());
196 mat<T> A(3*ui.size(), 9);
197 A.zeros();
198 for (size_t i = 0; i < ui.size(); ++i) {
199 const T& u = ui[i].x();
200 const T& v = ui[i].y();
201 const T& w = ui[i].y();
202 const T& x = xi[i].x();
203 const T& y = xi[i].y();
204 const T& z = xi[i].z();
205 size_t j=3*i;
206 A(j,3) = -w*x;
207 A(j,4) = -w*y;
208 A(j,5) = -w*z;
209 A(j,6) = v*x;
210 A(j,7) = v*y;
211 A(j,8) = v*z;
212 ++j;
213 A(j,0) = w*x;
214 A(j,1) = w*y;
215 A(j,2) = w*z;
216 A(j,6) = -u*x;
217 A(j,7) = -u*y;
218 A(j,8) = -u*z;
219 ++j;
220 A(j,0) = -v*x;
221 A(j,1) = -v*y;
222 A(j,2) = -v*z;
223 A(j,3) = u*x;
224 A(j,4) = u*y;
225 A(j,5) = u*z;
226 }
227 return compute_homography_from_constraint_matrix(A, H);
228}
229// compute homography from 2D lines in pixel coords \c lpi to 2D lines \c li correspondences and return whether this was possible
230template <typename T>
231bool compute_homography_from_2D_line_correspondences(const std::vector<fvec<T, 3>>& lpi, const std::vector<fvec<T, 3>>& li, fmat<T,3,3>& H)
232{
233 assert(lpi.size() == li.size());
234 mat<T> A(3*lpi.size(), 9);
235 A.zeros();
236 for (size_t i = 0; i < lpi.size(); ++i) {
237 const T& d = lpi[i].x();
238 const T& e = lpi[i].y();
239 const T& f = lpi[i].y();
240 const T& a = li[i].x();
241 const T& b = li[i].y();
242 const T& c = li[i].z();
243 size_t j = 3*i;
244 A(j,1) = -c*d;
245 A(j,2) = b*d;
246 A(j,4) = -c*e;
247 A(j,5) = b*e;
248 A(j,7) = -c*f;
249 A(j,8) = b*f;
250 ++j;
251 A(j, 0) = c*d;
252 A(j, 2) = -a*d;
253 A(j, 3) = c*e;
254 A(j, 5) = -a*e;
255 A(j, 6) = c*f;
256 A(j, 8) = -a*f;
257 ++j;
258 A(j, 0) = -b*d;
259 A(j, 1) = a*d;
260 A(j, 3) = -b*e;
261 A(j, 4) = a*e;
262 A(j, 6) = -b*f;
263 A(j, 7) = a*f;
264 }
265 return compute_homography_from_constraint_matrix(A, H);
266}
267
269template <typename T>
271{
272public:
273 // extent in pixels
274 unsigned w, h;
275 // focal length in pixel units for x and y
276 fvec<T,2> s;
277 // optical center in pixel units
278 fvec<T,2> c;
279 // skew strength;
280 T skew = 0.0f;
282 pinhole() : w(640), h(480), s(T(500)), c(T(0)) {}
284 template <typename S>
285 pinhole(const pinhole<S>& ph) {
286 w = ph.w;
287 h = ph.h;
288 s = ph.s;
289 c = ph.c;
290 skew = T(ph.skew);
291 }
292 fmat<T,2,3> get_camera_matrix() const {
293 return { s[0], 0.0f, skew, s[1], c[0], c[1] };
294 }
295 fmat<T,3,3> get_squared_camera_matrix() const {
296 return { s[0], 0.0f, 0.0f, skew, s[1], 0.0f, c[0], c[1], 1.0f };
297 }
298 fmat<T,4,4> get_homogeneous_camera_matrix() const {
299 return { s[0], 0.0f, 0.0f, 0.0f, skew, s[1], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, c[0], c[1], 0.0f, 1.0f };
300 }
301 fvec<T,2> image_to_pixel_coordinates(const fvec<T,2>& x) const {
302 return fvec<T,2>(s[0] * x[0] + skew * x[1] + c[0], s[1] * x[1] + c[1]);
303 }
304 fvec<T,2> pixel_to_image_coordinates(const fvec<T,2>& p) const {
305 T y = (p[1] - c[1]) / s[1]; return fvec<T, 2>((p[0] - c[0] - skew*y)/s[0], y);
306 }
307 // estimate pinhole parameters from at least 3 homographies
308 bool estimate_parameters(const std::vector<fmat<T, 3, 3>>& Hs, bool quadratic_pixels = true, bool no_skew = true)
309 {
310 assert(Hs.size() >= 3);
311 mat<T> A(2 * Hs.size() + (no_skew ? (1 + (quadratic_pixels ? 1 : 0)) : 0) , 6);
312 A.zeros();
313 size_t j = 2 * Hs.size();
314 if (no_skew) {
315 A(j, 1) = 1;
316 ++j;
317 if (quadratic_pixels) {
318 A(j, 0) = 1;
319 A(j, 3) = -1;
320 }
321 }
322 for (size_t i = 0; i < Hs.size(); ++i) {
323 vec<T> h1 = Hs[i].col(0);
324 vec<T> h2 = Hs[i].col(1);
325 size_t j = 2*i;
326 A(j,0) = x*x-X*X;
327 A(j,1) = T(2)*(x*y-X*Y);
328 A(j,2) = T(2)*(x*z-X*Z);
329 A(j,3) = y*y-Y*Y;
330 A(j,4) = T(2)*(y*z-Y*Z);
331 A(j,5) = z*z-Z*Z;
332 ++j;
333 A(j,0) = x*X;
334 A(j,1) = x*Y+X*y;
335 A(j,2) = x*Z+X*z;
336 A(j,3) = y*Y;
337 A(j,4) = y*Z+Y*z;
338 A(j,5) = z*Z;
339 }
340 mat<T> U, V;
341 diag_mat<T> W;
342 if (!svd(A, U, W, V, true))
343 return false;
344 vec<T> v = V.col(5);
345 T B11 = v(0);
346 T B12 = v(1);
347 T B13 = v(2);
348 T B22 = v(3);
349 T B23 = v(4);
350 T B33 = v(5);
351
352 T a1, a2, a3, l;
353 if (no_skew) {
354 a1 = - B13 * B22;
355 a2 = B11 * B22;
356 a3 = - B11 * B23;
357 }
358 else {
359 a1 = B12*B23 - B13*B22;
360 a2 = B11*B22 - B12*B12;
361 a3 = B12*B13 - B11*B23;
362 }
363 c(0) = a1/a2;
364 c(1) = a3/a2;
365 l = B33 - (B13*B13 + c(1)*a3)/B11;
366 s(0) = sqrt(l / B11);
367 if (quadratic_pixels)
368 s(1) = s(0);
369 else
370 s(1) = sqrt(l*B11/a2);
371 if (no_skew)
372 skew = 0;
373 else
374 skew = = -sqrt(l*B12*B12/(B11*a2));
375 return true;
376 }
377 // todo: minimize reprojection error
378};
379
382{
383public:
385 enum class distortion_result { success, out_of_bounds, division_by_zero };
387 enum class distortion_inversion_result { convergence, max_iterations_reached, divergence, out_of_bounds, division_by_zero };
389 static unsigned get_standard_max_nr_iterations() { return 20; }
390};
391
393template <typename T> inline T distortion_inversion_epsilon() { return 1e-12; }
395template <> inline float distortion_inversion_epsilon() { return 1e-6f; }
396
398template <typename T>
400{
401public:
403 static T get_standard_slow_down() { return T(1); }
404 // distortion center
405 fvec<T,2> dc;
406 // internal calibration
407 T k[6], p[2];
408 // maximum radius allowed for projection
409 T max_radius_for_projection = T(10);
411 distorted_pinhole() : dc(T(0)) {
412 k[0] = k[1] = k[2] = k[3] = k[4] = k[5] = p[0] = p[1] = T(0);
413 }
415 template <typename S>
417 dc = dp.dc;
418 unsigned i;
419 for (i = 0; i < 6; ++i)
420 k[i] = T(dp.k[i]);
421 for (i = 0; i < 2; ++i)
422 p[i] = T(dp.p[i]);
423 max_radius_for_projection = T(dp.max_radius_for_projection);
424 }
426
427 distortion_result apply_distortion_model(const fvec<T, 2>& xd, fvec<T, 2>& xu, fmat<T, 2, 2>* J_ptr = 0, T epsilon = distortion_inversion_epsilon<T>()) const {
428 fvec<T,2> od = xd - dc;
429 T xd2 = od[0]*od[0];
430 T yd2 = od[1]*od[1];
431 T xyd = od[0]*od[1];
432 T rd2 = xd2 + yd2;
433 // ensure to be within valid projection radius
434 if (rd2 > max_radius_for_projection * max_radius_for_projection)
435 return distortion_result::out_of_bounds;
436 T v = T(1) + rd2 * (k[3] + rd2 * (k[4] + rd2 * k[5]));
437 T u = T(1) + rd2 * (k[0] + rd2 * (k[1] + rd2 * k[2]));
438 // check for division by very small number or zero
439 if (fabs(v) < epsilon*fabs(u))
440 return distortion_result::division_by_zero;
441 T inv_v = T(1) / v;
442 T f = u * inv_v;
443 xu[0] = f*od[0] + T(2)*xyd*p[0] + (T(3)*xd2 + yd2)*p[1];
444 xu[1] = f*od[1] + T(2)*xyd*p[1] + (xd2 + T(3)*yd2)*p[0];
445 if (J_ptr) {
446 fmat<T,2,2>& J = *J_ptr;
447 T du = k[0] + rd2*(T(2)*k[1] + T(3)*rd2*k[2]);
448 T dv = k[3] + rd2*(T(2)*k[4] + T(3)*rd2*k[5]);
449 T df = (du*v - dv*u)*inv_v*inv_v;
450 J(0, 0) = f + T(2)*(df*xd2 + od[1]*p[0] + T(3)*od[0]*p[1]);
451 J(1, 1) = f + T(2)*(df*yd2 + T(3)*od[1]*p[0] + od[0]*p[1]);
452 J(1, 0) = J(0, 1) = T(2)*(df*xyd + od[0]*p[0] + od[1]*p[1]);
453 }
454 return distortion_result::success;
455 }
469 distortion_inversion_result invert_distortion_model(const fvec<T,2>& xu, fvec<T,2>& xd, bool use_xd_as_initial_guess = false,
470 unsigned* iteration_ptr = 0, T epsilon = distortion_inversion_epsilon<T>(), unsigned max_nr_iterations = get_standard_max_nr_iterations(), T slow_down = get_standard_slow_down()) const {
471 // start with approximate inversion
472 if (!use_xd_as_initial_guess) {
473 fvec<T, 2> od = xu - dc;
474 T xd2 = od[0] * od[0];
475 T yd2 = od[1] * od[1];
476 T xyd = od[0] * od[1];
477 T rd2 = xd2 + yd2;
478 T inverse_radial = 1.0f + rd2 * (k[3] + rd2 * (k[4] + rd2 * k[5]));
479 T enumerator = 1.0f + rd2 * (k[0] + rd2 * (k[1] + rd2 * k[2]));
480 if (fabs(enumerator) >= epsilon)
481 inverse_radial /= enumerator;
482 od *= inverse_radial;
483 od -= fvec<T, 2>((yd2 + 3 * xd2) * p[1] + 2 * xyd * p[0], (xd2 + 3 * yd2) * p[0] + 2 * xyd * p[1]);
484 xd = od + dc;
485 }
486 // iteratively improve approximation
487 fvec<T,2> xd_best = xd;
488 T err_best = std::numeric_limits<T>::max();
489 unsigned i;
490 if (iteration_ptr == 0)
491 iteration_ptr = &i;
492 for (*iteration_ptr = 0; *iteration_ptr < max_nr_iterations; ++(*iteration_ptr)) {
493 fmat<T,2,2> J;
494 fvec<T,2> xu_i;
495 distortion_result dr = apply_distortion_model(xd, xu_i, &J, epsilon);
496 if (dr == distortion_result::division_by_zero) {
497 xd = xd_best;
498 return distortion_inversion_result::division_by_zero;
499 }
500 if (dr == distortion_result::out_of_bounds) {
501 xd = xd_best;
502 return distortion_inversion_result::out_of_bounds;
503 }
504 // check for convergence
505 fvec<T,2> dxu = xu - xu_i;
506 T err = dxu.sqr_length();
507 if (err < epsilon * epsilon)
508 return distortion_inversion_result::convergence;
509 // check for divergence
510 if (err > err_best) {
511 xd = xd_best;
512 return distortion_inversion_result::divergence;
513 }
514 // improve approximation before the last iteration
515 xd_best = xd;
516 err_best = err;
517 fvec<T, 2> dxd = inv(J) * dxu;
518 xd += slow_down * dxd;
519 }
520 return distortion_inversion_result::max_iterations_reached;
521 }
523
528 template <typename S>
529 void compute_distortion_map(std::vector<cgv::math::fvec<S, 2>>& map, unsigned sub_sample = 1,
530 const cgv::math::fvec<S, 2>& invalid_point = cgv::math::fvec<S, 2>(S(-10000)),
531 T epsilon = distortion_inversion_epsilon<T>(), unsigned max_nr_iterations = get_standard_max_nr_iterations(), T slow_down = get_standard_slow_down()) const
532 {
533 unsigned iterations = 1;
534 map.resize(w*h);
535 size_t i = 0;
536 for (uint16_t y = 0; y < h; y += sub_sample) {
537 for (uint16_t x = 0; x < w; x += sub_sample) {
538 fvec<T, 2> xu = pixel_to_image_coordinates(fvec<T, 2>(x, y));
539 fvec<T, 2> xd = xu;
540 if (invert_distortion_model(xu, xd, true, &iterations, epsilon, max_nr_iterations, slow_down) ==
541 cgv::math::distorted_pinhole_types::distortion_inversion_result::convergence)
542 map[i] = cgv::math::fvec<S, 2>(xd);
543 else
544 map[i] = invalid_point;
545 ++i;
546 }
547 }
548 }
549};
550
552template <typename T>
553class camera : public distorted_pinhole<T>
554{
555public:
560 pose = pose_construct(identity3<T>(), fvec<T, 3>(T(0)));
561 }
563 template <typename S>
564 camera(const camera<S>& cam) : distorted_pinhole<T>(cam) {
565 pose = cam.pose;
566 }
567};
568
569 }
570}
571
572#include <cgv/config/lib_end.h>
extend distorted pinhole with external calibration stored as a pose matrix
Definition camera.h:554
camera()
standard constructor
Definition camera.h:559
fmat< T, 3, 4 > pose
external calibration
Definition camera.h:557
camera(const camera< S > &cam)
copy constructor
Definition camera.h:564
common type declarations used by distorted_pinhole class that are independent of the template paramet...
Definition camera.h:382
static unsigned get_standard_max_nr_iterations()
default maximum number of iterations used for inversion of distortion models
Definition camera.h:389
distortion_result
possible results of applying distortion model
Definition camera.h:385
distortion_inversion_result
possible results of inverting distortion model
Definition camera.h:387
pinhole camera including distortion according to Brown-Conrady model
Definition camera.h:400
distorted_pinhole(const distorted_pinhole< S > &dp)
copy constructor
Definition camera.h:416
static T get_standard_slow_down()
slow down factor [0,1] to decrease step size during inverse Jacobian stepping
Definition camera.h:403
distorted_pinhole()
standard constructor initializes to no distortion
Definition camera.h:411
distortion_inversion_result invert_distortion_model(const fvec< T, 2 > &xu, fvec< T, 2 > &xd, bool use_xd_as_initial_guess=false, unsigned *iteration_ptr=0, T epsilon=distortion_inversion_epsilon< T >(), unsigned max_nr_iterations=get_standard_max_nr_iterations(), T slow_down=get_standard_slow_down()) const
invert model for image coordinate inversion
Definition camera.h:469
void compute_distortion_map(std::vector< cgv::math::fvec< S, 2 > > &map, unsigned sub_sample=1, const cgv::math::fvec< S, 2 > &invalid_point=cgv::math::fvec< S, 2 >(S(-10000)), T epsilon=distortion_inversion_epsilon< T >(), unsigned max_nr_iterations=get_standard_max_nr_iterations(), T slow_down=get_standard_slow_down()) const
compute for all pixels the distorted image coordinates with the invert_distortion_model() function an...
Definition camera.h:529
distortion_result apply_distortion_model(const fvec< T, 2 > &xd, fvec< T, 2 > &xu, fmat< T, 2, 2 > *J_ptr=0, T epsilon=distortion_inversion_epsilon< T >()) const
apply distortion model from distorted to undistorted image coordinates used in projection direction a...
Definition camera.h:427
matrix of fixed size dimensions
Definition fmat.h:23
A vector with zero based index.
Definition fvec.h:26
T sqr_length() const
square length of vector
Definition fvec.h:294
class to store and use a pinhole camera model without distortion but with support for skew and differ...
Definition camera.h:271
pinhole(const pinhole< S > &ph)
copy constructor
Definition camera.h:285
pinhole()
standard constructor
Definition camera.h:282
the cgv namespace
Definition print.h:11
helper functions to work with poses that can be represented with 3x4 matrix or quaternion plus vector
fmat< T, 3, 4 > pose_construct(const fmat< T, 3, 3 > &orientation, const fvec< T, 3 > &position)
construct pose from rotation matrix and position vector
Definition pose.h:42