4#include <cgv/math/fvec.h>
5#include <cgv/math/fmat.h>
6#include <cgv/math/mat.h>
8#include <cgv/math/ftransform.h>
9#include <cgv/math/inv.h>
136bool compute_homography_from_constraint_matrix(
const mat<T>& A, fmat<T,3,3>& H)
138 assert(A.ncols() == 9);
141 if (!svd(A, U, W, V,
true))
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)
159 assert(ui.size() == xi.size());
160 mat<T> A(3*ui.size(), 9);
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();
189 return compute_homography_from_constraint_matrix(A, H);
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)
195 assert(ui.size() == xi.size());
196 mat<T> A(3*ui.size(), 9);
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();
227 return compute_homography_from_constraint_matrix(A, H);
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)
233 assert(lpi.size() == li.size());
234 mat<T> A(3*lpi.size(), 9);
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();
265 return compute_homography_from_constraint_matrix(A, H);
282 pinhole() : w(640), h(480), s(T(500)), c(T(0)) {}
284 template <
typename S>
293 return { s[0], 0.0f, skew, s[1], c[0], c[1] };
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 };
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 };
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]);
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);
308 bool estimate_parameters(
const std::vector<fmat<T, 3, 3>>& Hs,
bool quadratic_pixels =
true,
bool no_skew =
true)
310 assert(Hs.size() >= 3);
311 mat<T> A(2 * Hs.size() + (no_skew ? (1 + (quadratic_pixels ? 1 : 0)) : 0) , 6);
313 size_t j = 2 * Hs.size();
317 if (quadratic_pixels) {
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);
327 A(j,1) = T(2)*(x*y-X*Y);
328 A(j,2) = T(2)*(x*z-X*Z);
330 A(j,4) = T(2)*(y*z-Y*Z);
342 if (!svd(A, U, W, V,
true))
359 a1 = B12*B23 - B13*B22;
360 a2 = B11*B22 - B12*B12;
361 a3 = B12*B13 - B11*B23;
365 l = B33 - (B13*B13 + c(1)*a3)/B11;
366 s(0) = sqrt(l / B11);
367 if (quadratic_pixels)
370 s(1) = sqrt(l*B11/a2);
374 skew = = -sqrt(l*B12*B12/(B11*a2));
393template <
typename T>
inline T distortion_inversion_epsilon() {
return 1e-12; }
395template <>
inline float distortion_inversion_epsilon() {
return 1e-6f; }
409 T max_radius_for_projection = T(10);
412 k[0] = k[1] = k[2] = k[3] = k[4] = k[5] = p[0] = p[1] = T(0);
415 template <
typename S>
419 for (i = 0; i < 6; ++i)
421 for (i = 0; i < 2; ++i)
423 max_radius_for_projection = T(dp.max_radius_for_projection);
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]));
439 if (fabs(v) < epsilon*fabs(u))
440 return distortion_result::division_by_zero;
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];
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]);
454 return distortion_result::success;
472 if (!use_xd_as_initial_guess) {
474 T xd2 = od[0] * od[0];
475 T yd2 = od[1] * od[1];
476 T xyd = od[0] * od[1];
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]);
488 T err_best = std::numeric_limits<T>::max();
490 if (iteration_ptr == 0)
492 for (*iteration_ptr = 0; *iteration_ptr < max_nr_iterations; ++(*iteration_ptr)) {
496 if (dr == distortion_result::division_by_zero) {
498 return distortion_inversion_result::division_by_zero;
500 if (dr == distortion_result::out_of_bounds) {
502 return distortion_inversion_result::out_of_bounds;
507 if (err < epsilon * epsilon)
508 return distortion_inversion_result::convergence;
510 if (err > err_best) {
512 return distortion_inversion_result::divergence;
518 xd += slow_down * dxd;
520 return distortion_inversion_result::max_iterations_reached;
528 template <
typename S>
533 unsigned iterations = 1;
536 for (uint16_t y = 0; y < h; y += sub_sample) {
537 for (uint16_t x = 0; x < w; x += sub_sample) {
541 cgv::math::distorted_pinhole_types::distortion_inversion_result::convergence)
544 map[i] = invalid_point;
563 template <
typename S>
572#include <cgv/config/lib_end.h>
extend distorted pinhole with external calibration stored as a pose matrix
camera()
standard constructor
fmat< T, 3, 4 > pose
external calibration
camera(const camera< S > &cam)
copy constructor
common type declarations used by distorted_pinhole class that are independent of the template paramet...
static unsigned get_standard_max_nr_iterations()
default maximum number of iterations used for inversion of distortion models
distortion_result
possible results of applying distortion model
distortion_inversion_result
possible results of inverting distortion model
pinhole camera including distortion according to Brown-Conrady model
distorted_pinhole(const distorted_pinhole< S > &dp)
copy constructor
static T get_standard_slow_down()
slow down factor [0,1] to decrease step size during inverse Jacobian stepping
distorted_pinhole()
standard constructor initializes to no distortion
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
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...
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...
matrix of fixed size dimensions
A vector with zero based index.
T sqr_length() const
square length of vector
class to store and use a pinhole camera model without distortion but with support for skew and differ...
pinhole(const pinhole< S > &ph)
copy constructor
pinhole()
standard constructor
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