Ocean
Loading...
Searching...
No Matches
FisheyeCamera.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_MATH_FISHEYE_CAMERA_H
9#define META_OCEAN_MATH_FISHEYE_CAMERA_H
10
11#include "ocean/math/Math.h"
12#include "ocean/math/Camera.h"
14#include "ocean/math/Line3.h"
15#include "ocean/math/Numeric.h"
17#include "ocean/math/Vector2.h"
18#include "ocean/math/Vector3.h"
19
20namespace Ocean
21{
22
23// Forward declaration.
24template <typename T> class FisheyeCameraT;
25
26/**
27 * Definition of a FisheyeCamera object using Scalar as data type.
28 * @see FisheyeCameraT
29 * @ingroup math
30 */
32
33/**
34 * Definition of a FisheyeCamera object using 'float' as data type.
35 * @see FisheyeCameraT
36 * @ingroup math
37 */
39
40/**
41 * Definition of a FisheyeCamera object using 'double' as data type.
42 * @see FisheyeCameraT
43 * @ingroup math
44 */
46
47/**
48 * Definition of a typename alias for vectors with FisheyeCameraT objects.
49 * @see FisheyeCameraT
50 * @ingroup math
51 */
52template <typename T>
53using FisheyeCamerasT = std::vector<FisheyeCameraT<T>>;
54
55/**
56 * Definition of a vector holding camera objects.
57 * @ingroup math
58 */
59using FisheyeCameras = std::vector<FisheyeCamera>;
60
61/**
62 * Class representing a fisheye camera.<br>
63 * The class holds the intrinsic and distortion parameters of a camera.<br>
64 * <pre>
65 * The camera holds:
66 *
67 * 1) Width and height of the camera image.
68 *
69 * 2) Intrinsic camera matrix:
70 * | Fx 0 mx |
71 * | 0 Fy my |
72 * | 0 0 1 |
73 * with mx and my as principal point,
74 * and with Fx = f / sx, Fy = f / sy, with focus f and pixel sizes sx and sy.
75 *
76 * 3) Six radial distortion parameters k3, k5, k7, k9, k11, k13
77 *
78 * 4) Two tangential distortion parameters p1 and p2.
79 *
80 * An undistorted image point (x, y), is transformed to the corresponding distorted image point (x', y') as follows:
81 * x' = x_r + x_t
82 * y' = y_r + y_t
83
84 * radial distortion:
85 * x_r = x * (theta + k3 * theta^3 + k5 * theta^5 + k7 * theta^7 + k9 * theta^9 + k11 * theta^11 + k13 * theta^13) / r
86 * y_r = y * (theta + k3 * theta^3 + k5 * theta^5 + k7 * theta^7 + k9 * theta^9 + k11 * theta^11 + k13 * theta^13) / r
87 *
88 * tangential distortion:
89 * x_t = p1 * (2 * x_r^2 + radial^2) + p2 * 2 * x_r * y_r,
90 * y_t = p2 * (2 * y_r^2 + radial^2) + p1 * 2 * x_r * y_r.
91 *
92 * with
93 * r = sqrt(x^2 + y^2)
94 * theta = atan(r)
95 * radial^2 = x_r^2 + y_r^2
96 *
97 * With x, y undistorted normalized coordinates
98 * With x', y' distorted normalized coordinates
99 *
100 * </pre>
101 * @ingroup math
102 * @tparam T The data type of a scalar, 'float' or 'double'
103 */
104template <typename T>
105class FisheyeCameraT : public CameraT<T>
106{
107 template <typename U> friend class FisheyeCameraT;
108
109 public:
110
111 /**
112 * Definition of the used data type.
113 */
114 using Type = T;
115
116 /**
117 * Definition of individual parameter configurations.
118 */
120 {
121 /**
122 * An unknown parameter configuration.
123 */
125
126 /**
127 * 3 parameters with order:
128 * focal length (one identical value for horizontal and vertical direction),
129 * horizontal principal point,
130 * vertical principal point
131 */
133
134 /**
135 * 4 parameters with order:
136 * horizontal focal length,
137 * vertical focal length,
138 * horizontal principal point,
139 * vertical principal point
140 */
142
143 /**
144 * 11 parameters with order:
145 * focal length (one identical value for horizontal and vertical direction),
146 * horizontal principal point,
147 * vertical principal point,
148 * six radial distortion parameters k3, k5, k7, k9, k11, k13
149 * two tangential distortion parameters p1, p2
150 */
152
153 /**
154 * 12 parameters with order:
155 * horizontal focal length,
156 * vertical focal length,
157 * horizontal principal point,
158 * vertical principal point,
159 * six radial distortion parameters k3, k5, k7, k9, k11, k13
160 * two tangential distortion parameters p1, p2
161 */
163 };
164
165 public:
166
167 /**
168 * Default constructor creating an invalid camera object.
169 */
170 FisheyeCameraT() = default;
171
172 /**
173 * Copy constructor.
174 * @param fisheyeCamera The fisheye camera profile to be copied
175 */
177
178 /**
179 * Copy constructor for a fisheye camera with difference element data type than T.
180 * @param fisheyeCamera The fisheye camera profile to be copied
181 * @tparam U The element data type of the given fisheye camera
182 */
183 template <typename U>
185
186 /**
187 * Creates a new camera object with known field of view.
188 * @param width The width of the camera image (in pixel), with range [1, infinity)
189 * @param height The height of the camera image (in pixel), with range [1, infinity)
190 * @param fovX Field of view in x-direction (in radian), with range (0, PI]
191 */
192 inline FisheyeCameraT(const unsigned int width, const unsigned int height, const T fovX);
193
194 /**
195 * Creates a new camera object without distortion parameters.
196 * @param width The width of the camera image (in pixel), with range [1, infinity)
197 * @param height The height of the camera image (in pixel), with range [1, infinity)
198 * @param focalX Focal parameter of the horizontal axis, with range (0, infinity)
199 * @param focalY Focal parameter of the vertical axis, with range (0, infinity)
200 * @param principalX Principal point of the horizontal axis (in pixel)
201 * @param principalY Principal point of the vertical axis (in pixel)
202 */
203 inline FisheyeCameraT(const unsigned int width, const unsigned int height, const T focalX, const T focalY, const T principalX, const T principalY);
204
205 /**
206 * Creates a new camera object with distortion parameters.
207 * @param width The width of the camera image (in pixel), with range [1, infinity)
208 * @param height The height of the camera image (in pixel), with range [1, infinity)
209 * @param focalX Focal parameter of the horizontal axis, with range (0, infinity)
210 * @param focalY Focal parameter of the vertical axis, with range (0, infinity)
211 * @param principalX Principal point of the horizontal axis (in pixel), with range (0, width)
212 * @param principalY Principal point of the vertical axis (in pixel), with range (0, height)
213 * @param radialDistortion Six radial distortion values, with order k3, k5, k7, k9, k11, k13, must be valid
214 * @param tangentialDistortion Two tangential distortion values, with order p1, p2, must be valid
215 * @tparam TParameter The scalar data type in which the intrinsic camera parameters are provided, will be converted to 'T' internally, 'float' or 'double'
216 */
217 template <typename TParameter>
218 inline FisheyeCameraT(const unsigned int width, const unsigned int height, const TParameter focalX, const TParameter focalY, const TParameter principalX, const TParameter principalY, const TParameter* radialDistortion, const TParameter* tangentialDistortion);
219
220 /**
221 * Creates a new camera object with parameters with specific configuration.
222 * @param width The width of the camera image (in pixel), with range [1, infinity)
223 * @param height The height of the camera image (in pixel), with range [1, infinity)
224 * @param parameterConfiguration The configuration of the given parameter, must be valid
225 * @param parameters The parameters matching with the specific configuration, must be valid
226 * @tparam TParameter The scalar data type in which the intrinsic camera parameters are provided, will be converted to 'T' internally, 'float' or 'double'
227 */
228 template <typename TParameter>
229 inline FisheyeCameraT(const unsigned int width, const unsigned int height, const ParameterConfiguration parameterConfiguration, const TParameter* parameters);
230
231 /**
232 * Returns whether this camera object has specified distortion parameters.
233 * @return True, if so
234 */
235 inline bool hasDistortionParameters() const;
236
237 /**
238 * Returns the width of the camera image.
239 * @return Width of the camera image, in pixel, with range [0, infinity)
240 */
241 inline unsigned int width() const;
242
243 /**
244 * Returns the height of the camera image.
245 * @return Height of the camera image, in pixel, with range [0, infinity)
246 */
247 inline unsigned int height() const;
248
249 /**
250 * Returns the coordinate of the principal point of the camera image in the pixel domain.
251 * @return The 2D location of the principal point, with range [0, width)x[0, height)
252 */
254
255 /**
256 * Returns the x-value of the principal point of the camera image in the pixel domain.
257 * @return x-value of the principal point, with range [0, width)
258 */
259 inline T principalPointX() const;
260
261 /**
262 * Returns the y-value of the principal point of the camera image in the pixel domain.
263 * @return y-value of the principal point, with range [0, height)
264 */
265 inline T principalPointY() const;
266
267 /**
268 * Returns the horizontal focal length parameter.
269 * @return Horizontal focal length parameter
270 */
271 inline T focalLengthX() const;
272
273 /**
274 * Returns the vertical focal length parameter.
275 * @return Vertical focal length parameter
276 */
277 inline T focalLengthY() const;
278
279 /**
280 * Returns the inverse horizontal focal length parameter.
281 * @return Inverse horizontal focal length parameter
282 */
283 inline T inverseFocalLengthX() const;
284
285 /**
286 * Returns the inverse vertical focal length parameter.
287 * @return Inverse vertical focal length parameter
288 */
289 inline T inverseFocalLengthY() const;
290
291 /**
292 * Returns the six radial distortion parameters of the camera model.
293 * @return The six radial distortion parameters, with order k3, k5, k7, k9, k11, k13
294 */
295 inline const T* radialDistortion() const;
296
297 /**
298 * Returns the two tangential distortion parameters of the camera model.
299 * @return The two tangential distortion parameters, with order p1, p2
300 */
301 inline const T* tangentialDistortion() const;
302
303 /**
304 * Returns the field of view in x direction of the camera.
305 * The fov is the sum of the left and right part of the camera.
306 * @return Field of view (in radian), with range (0, PI]
307 */
308 T fovX() const;
309
310 /**
311 * Returns the field of view in x direction of the camera.
312 * The fov is the sum of the top and bottom part of the camera.
313 * @return Field of view (in radian), with range (0, PI)
314 */
315 T fovY() const;
316
317 /**
318 * Returns the diagonal field of view of the camera
319 * @return Diagonal field of view (in radian), with range (0, PI]
320 */
321 T fovDiagonal() const;
322
323 /**
324 * Copies the parameters of this camera.
325 * @param width The resulting width of the camera, in pixel, with range [0, infinity)
326 * @param height The resulting height of the camera, in pixel, with range [0, infinity)
327 * @param parameters The resulting parameters of the camera
328 * @param parameterConfiguration The resulting configuration of the resulting parameters
329 */
330 template <typename TParameter>
331 void copyParameters(unsigned int& width, unsigned int& height, std::vector<TParameter>& parameters, ParameterConfiguration& parameterConfiguration) const;
332
333 /**
334 * Returns whether a given 2D image point lies inside the camera frame.
335 * Optional an explicit border can be defined to allow points slightly outside the camera image, or further inside the image.<br>
336 * Defined a negative border size to allow image points outside the camera frame, or a positive border size to prevent points within the camera frame but close to the boundary.
337 * @param imagePoint Image point to be checked, must be valid
338 * @param signedBorder The optional border increasing or decreasing the rectangle in which the image point must be located, in pixels, with range (-infinity, std::min(width() / 2, height() / 2)
339 * @return True, if the image point lies in the ranges [0, width())x[0, height())
340 */
341 inline bool isInside(const VectorT2<T>& imagePoint, const T signedBorder = T(0)) const;
342
343 /**
344 * Returns the normalized distorted position of a given undistorted normalized position.
345 * @param undistortedNormalized Undistorted normalized position to be distorted
346 * @return Resulting distorted normalized position
347 */
349
350 /**
351 * Returns the normalized undistorted position of a given distorted normalized position.
352 * @param distortedNormalized Distorted normalized position to be undistorted
353 * @return Resulting undistorted normalized position
354 */
356
357 /**
358 * Projects a 3D object point into the camera's image of the fisheye camera.
359 * The 3D object point must be defined in relation to the (standard) camera coordinate system.<br>
360 * The default viewing direction of the standard camera is into the negative z-space with x-axis to the right, and y-axis upwards.
361 * @param worldObjectPoint 3D object point which is located in the world
362 * @return Resulting 2D image point within the camera frame
363 * @see projectToImageIF().
364 */
366
367 /**
368 * Projects a 3D object point into the camera's image of the fisheye camera.
369 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates (world from camera).<br>
370 * The default viewing direction of the camera is into the negative z-space with x-axis to the right, and y-axis upwards.
371 * @param world_T_camera The extrinsic camera matrix, must be valid
372 * @param worldObjectPoint 3D object point which is located in the world
373 * @return Resulting 2D image point within the camera frame
374 * @see projectToImageIF().
375 */
377
378 /**
379 * Projects a 3D object point to the 2D image plane of the fisheye camera by a given inverted (and flipped) extrinsic camera matrix.
380 * The inverted (and flipped) extrinsic matrix transforms a 3D point given in 3D world coordinates into 3D (flipped) camera coordinates (flipped camera from world).<br>
381 * The default viewing direction of the flipped camera is into the positive z-space with x-axis to the right, and y-axis downwards.
382 * @param flippedCamera_T_world Inverted and flipped extrinsic camera matrix, must be valid
383 * @param worldObjectPoint 3D object point which is located in the world
384 * @return Resulting 2D image point within the camera frame
385 * @see projectToImage().
386 */
388
389 /**
390 * Projects a 3D object point to the 2D image plane of the fisheye camera.
391 * The 3D object point must be defined in relation to the (flipped) camera coordinate system.<br>
392 * The default viewing direction of the flipped camera is into the positive z-space with x-axis to the right, and y-axis downwards.
393 * @param cameraFlippedObjectPoint 3D object point which is located in the flipped camera coordinate system
394 * @return Resulting 2D image point within the camera frame
395 * @see projectToImage().
396 */
398
399 /**
400 * Returns a vector starting at the camera's center and intersecting a given 2D point in the image.
401 * The vector is determined for the default camera looking into the negative z-space with y-axis up.
402 * @param distortedImagePoint 2D (distorted) position within the image, with range [0, width())x[0, height())
403 * @param makeUnitVector True, to return a vector with length 1; False, to return a vector with any length
404 * @return Unit vector pointing into the negative z-space
405 * @see vectorIF(), ray().
406 */
407 inline VectorT3<T> vector(const VectorT2<T>& distortedImagePoint, const bool makeUnitVector = true) const;
408
409 /**
410 * Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane.
411 * The vector is determined for the default camera looking into the positive z-space with y-axis down.
412 * @param distortedImagePoint 2D (distorted) position within the image, with range [0, width())x[0, height())
413 * @param makeUnitVector True, to return a vector with length 1; False, to return a vector with any length
414 * @return Normalized vector into the negative z-space
415 * @see vector().
416 */
417 inline VectorT3<T> vectorIF(const VectorT2<T>& distortedImagePoint, const bool makeUnitVector = true) const;
418
419 /**
420 * Returns a ray starting at the camera's center and intersecting a given 2D point in the image.
421 * @param distortedImagePoint 2D (distorted) position within the image, with range [0, width())x[0, height())
422 * @param world_T_camera The pose of the camera, the extrinsic camera matrix, must be valid
423 * @return The specified ray with direction pointing into the camera's negative z-space
424 * @see vector().
425 */
427
428 /**
429 * Returns a ray starting at the camera's center and intersecting a given 2D point in the image.
430 * @param distortedImagePoint 2D (distorted) position within the image, with range [0, width())x[0, height())
431 * @return The specified ray with direction pointing into the camera's negative z-space
432 * @see vector().
433 */
435
436 /**
437 * Calculates the 2x3 jacobian matrix for the 3D object point projection into the camera frame.
438 * The resulting jacobian matrix has the following layout:
439 * <pre>
440 * | dfu / dx, dfu / dy, dfu / dz |
441 * | dfv / dx, dfv / dy, dfv / dz |
442 * with projection function
443 * q = f(p)
444 * q_u = fu(p), q_y = fv(p)
445 * with 2D image point q = (q_u, q_v) and 3D object point p = (x, y, z)
446 * </pre>
447 * @param flippedCameraObjectPoint The 3D object point defined in relation to the inverted and flipped camera pose (camera looking into the positive z-space with y-axis pointing down).
448 * @param jx The resulting first row of the Jacobian matrix, must contain three elements, must be valid
449 * @param jy The resulting second row of the Jacobian matrix, must contain three elements, must be valid
450 */
452
453 /**
454 * Returns whether two camera profiles are identical up to a given epsilon.
455 * The image resolution must always be identical.
456 * @param fisheyeCamera The second camera profile to be used for comparison, can be invalid
457 * @param eps The epsilon threshold to be used, with range [0, infinity)
458 * @return True, if so
459 */
460 bool isEqual(const FisheyeCameraT<T>& fisheyeCamera, const T eps = NumericT<T>::eps()) const;
461
462 /**
463 * Returns whether this camera is valid.
464 * @return True, if so
465 */
466 inline bool isValid() const;
467
468 /**
469 * Returns whether two fisheye cameras are identical.
470 * @param fisheyeCamera The second fisheye camera to be check
471 * @return True, if so
472 */
474
475 /**
476 * Returns whether two fisheye cameras are not identical.
477 * @param fisheyeCamera The second fisheye camera to be check
478 * @return True, if so
479 */
480 inline bool operator!=(const FisheyeCameraT<T>& fisheyeCamera) const;
481
482 /**
483 * Copy assignment operator.
484 * @param fisheyeCamera The fisheye camera profile to be copied
485 * @return A reference to this object
486 */
488
489 /**
490 * Returns whether the camera holds valid parameters.
491 * @return True, if so
492 */
493 explicit inline operator bool() const;
494
495 protected:
496
497 /**
498 * Calculates the tangential-free distortion of a normalized (distorted) image point.
499 * @param distortedNormalized The distorted normalized image point from which the tangential distortion will be removed
500 * @return The normalized image point containing radial distortion only
501 */
503
504 /**
505 * Determines the 2x2 Jacobian of distorting a normalized image point in a fisheye camera with radial and tangential distortion.
506 * The resulting jacobian has the following form:
507 * <pre>
508 * | dfx / dx, dfx / dy |
509 * | dfy / dx, dfy / dy |
510 * </pre>
511 * @param x The horizontal coordinate of the normalized image point to be distorted
512 * @param y The vertical coordinate of the normalized image point to be distorted
513 * @param radialDistortion The six radial distortion parameters, must be valid
514 * @param tangentialDistortion The two tangential distortion parameters, must be valid
515 * @param jx First row of the jacobian, with 2 column entries, must be valid
516 * @param jy Second row of the jacobian, with 2 column entries, must be valid
517 */
518 static OCEAN_FORCE_INLINE void jacobianDistortNormalized2x2(const T x, const T y, const T* radialDistortion, const T* tangentialDistortion, T* jx, T* jy);
519
520 protected:
521
522 /// Width of the camera image, in pixel.
523 unsigned int width_ = 0u;
524
525 /// Height of the camera image, in pixel.
526 unsigned int height_ = 0u;
527
528 /// The horizontal focal length of the camera, with range (0, infinity)
530
531 /// The vertical focal length of the camera, with range (0, infinity)
533
534 /// The horizontal inverse focal length of the camera, with range (0, infinity)
536
537 /// The vertical inverse focal length of the camera, with range (0, infinity)
539
540 /// The horizontal principal point of the camera, in pixels, with range [0, width())
542
543 /// The vertical principal point of the camera, in pixels, with range [0, height())
545
546 /// True, if the distortion parameters are defined.
548
549 /// The six radial distortion parameters.
550 T radialDistortion_[6] = {T(0), T(0), T(0), T(0), T(0), T(0)};
551
552 /// The two tangential distortion parameters.
553 T tangentialDistortion_[2] = {T(0), T(0)};
554};
555
556template <typename T>
557template <typename U>
559 width_(fisheyeCamera.width_),
560 height_(fisheyeCamera.height_),
561 focalLengthX_(T(fisheyeCamera.focalLengthX_)),
562 focalLengthY_(T(fisheyeCamera.focalLengthY_)),
563 principalPointX_(T(fisheyeCamera.principalPointX_)),
564 principalPointY_(T(fisheyeCamera.principalPointY_)),
565 hasDistortionParameters_(fisheyeCamera.hasDistortionParameters_)
566{
567 static_assert(sizeof(radialDistortion_) == sizeof(T) * 6, "Invalid parameter");
568 static_assert(sizeof(tangentialDistortion_) == sizeof(T) * 2, "Invalid parameter");
569
572
573 for (unsigned int n = 0u; n < 6u; ++n)
574 {
575 radialDistortion_[n] = T(fisheyeCamera.radialDistortion_[n]);
576 }
577
578 tangentialDistortion_[0] = T(fisheyeCamera.tangentialDistortion_[0]);
579 tangentialDistortion_[1] = T(fisheyeCamera.tangentialDistortion_[1]);
580}
581
582template <typename T>
583inline FisheyeCameraT<T>::FisheyeCameraT(const unsigned int width, const unsigned int height, const T fovX) :
584 width_(width),
585 height_(height),
586 focalLengthX_(0),
587 focalLengthY_(0),
588 invFocalLengthX_(0),
589 invFocalLengthY_(0),
590 principalPointX_(0),
591 principalPointY_(0),
592 hasDistortionParameters_(false)
593{
594 ocean_assert(width_ != 0u && height_ != 0u);
596
597 const T principalX = T(width_) * T(0.5);
598 const T principalY = T(height_) * T(0.5);
599
600 const T focalLength = principalX / NumericT<T>::tan(fovX * T(0.5));
601
604
606 const T invFocalLength = T(1) / focalLength;
609
612
613 for (unsigned int n = 0u; n < 6u; ++n)
614 {
615 radialDistortion_[n] = T(0);
616 }
617
618 tangentialDistortion_[0] = T(0);
619 tangentialDistortion_[1] = T(0);
620}
621
622template <typename T>
623inline FisheyeCameraT<T>::FisheyeCameraT(const unsigned int width, const unsigned int height, const T focalX, const T focalY, const T principalX, const T principalY) :
624 width_(width),
625 height_(height),
626 focalLengthX_(focalX),
627 focalLengthY_(focalY),
628 invFocalLengthX_(0),
629 invFocalLengthY_(0),
630 principalPointX_(principalX),
631 principalPointY_(principalY),
632 hasDistortionParameters_(false)
633{
634 ocean_assert(width_ != 0u && height_ != 0u);
635
640
641 for (unsigned int n = 0u; n < 6u; ++n)
642 {
643 radialDistortion_[n] = T(0);
644 }
645
646 tangentialDistortion_[0] = T(0);
647 tangentialDistortion_[1] = T(0);
648}
649
650template <typename T>
651template <typename TParameter>
652inline FisheyeCameraT<T>::FisheyeCameraT(const unsigned int width, const unsigned int height, const TParameter focalX, const TParameter focalY, const TParameter principalX, const TParameter principalY, const TParameter* radialDistortion, const TParameter* tangentialDistortion) :
653 width_(width),
654 height_(height),
655 focalLengthX_(T(focalX)),
656 focalLengthY_(T(focalY)),
657 invFocalLengthX_(0),
658 invFocalLengthY_(0),
659 principalPointX_(T(principalX)),
660 principalPointY_(T(principalY))
661{
662 static_assert((std::is_same<TParameter, float>::value) || (std::is_same<TParameter, double>::value), "Invalid TParameter, must be 'float' or 'double'!");
663
664 ocean_assert(width_ != 0u && height_ != 0u);
668
669 for (unsigned int n = 0u; n < 6u; ++n)
670 {
672 }
673
676
678
679 for (unsigned int n = 0u; !hasDistortionParameters_ && n < 6u; ++n)
680 {
682 }
683}
684
685template <typename T>
686template <typename TParameter>
687inline FisheyeCameraT<T>::FisheyeCameraT(const unsigned int width, const unsigned int height, const ParameterConfiguration parameterConfiguration, const TParameter* parameters) :
688 width_(width),
689 height_(height),
690 focalLengthX_(0),
691 focalLengthY_(0),
692 invFocalLengthX_(0),
693 invFocalLengthY_(0),
694 principalPointX_(0),
695 principalPointY_(0),
696 hasDistortionParameters_(false)
697{
698 static_assert((std::is_same<TParameter, float>::value) || (std::is_same<TParameter, double>::value), "Invalid TParameter, must be 'float' or 'double'!");
699
700 ocean_assert(width_ != 0u && height_ != 0u);
701 ocean_assert(parameters != nullptr);
702
704 {
706 {
707 focalLengthX_ = T(parameters[0]);
708 focalLengthY_ = T(parameters[0]);
709
710 principalPointX_ = T(parameters[1]);
711 principalPointY_ = T(parameters[2]);
712
713 break;
714 }
715
716 case PC_4_PARAMETERS:
717 {
718 focalLengthX_ = T(parameters[0]);
719 focalLengthY_ = T(parameters[1]);
720
721 principalPointX_ = T(parameters[2]);
722 principalPointY_ = T(parameters[3]);
723
724 break;
725 }
726
728 {
729 focalLengthX_ = T(parameters[0]);
730 focalLengthY_ = T(parameters[0]);
731
732 principalPointX_ = T(parameters[1]);
733 principalPointY_ = T(parameters[2]);
734
735 radialDistortion_[0] = T(parameters[3]);
736 radialDistortion_[1] = T(parameters[4]);
737 radialDistortion_[2] = T(parameters[5]);
738 radialDistortion_[3] = T(parameters[6]);
739 radialDistortion_[4] = T(parameters[7]);
740 radialDistortion_[5] = T(parameters[8]);
741
742 tangentialDistortion_[0] = T(parameters[9]);
743 tangentialDistortion_[1] = T(parameters[10]);
744
745 break;
746 }
747
748 case PC_12_PARAMETERS:
749 {
750 focalLengthX_ = T(parameters[0]);
751 focalLengthY_ = T(parameters[1]);
752
753 principalPointX_ = T(parameters[2]);
754 principalPointY_ = T(parameters[3]);
755
756 radialDistortion_[0] = T(parameters[4]);
757 radialDistortion_[1] = T(parameters[5]);
758 radialDistortion_[2] = T(parameters[6]);
759 radialDistortion_[3] = T(parameters[7]);
760 radialDistortion_[4] = T(parameters[8]);
761 radialDistortion_[5] = T(parameters[9]);
762
763 tangentialDistortion_[0] = T(parameters[10]);
764 tangentialDistortion_[1] = T(parameters[11]);
765
766 break;
767 }
768
769 default:
770 ocean_assert(false && "Invalid parameter configuration!");
771 return;
772 }
773
777
779
780 for (unsigned int n = 0u; !hasDistortionParameters_ && n < 6u; ++n)
781 {
783 }
784}
785
786template <typename T>
788{
789 return hasDistortionParameters_;
790}
791
792template <typename T>
793inline unsigned int FisheyeCameraT<T>::width() const
794{
795 return width_;
796}
797
798template <typename T>
799inline unsigned int FisheyeCameraT<T>::height() const
800{
801 return height_;
802}
803
804template <typename T>
806{
807 return VectorT2<T>(principalPointX(), principalPointY());
808}
809
810template <typename T>
812{
813 return principalPointX_;
814}
815
816template <typename T>
818{
819 return principalPointY_;
820}
821
822template <typename T>
824{
825 return focalLengthX_;
826}
827
828template <typename T>
830{
831 return focalLengthY_;
832}
833
834template <typename T>
836{
837 return invFocalLengthX_;
838}
839
840template <typename T>
842{
843 return invFocalLengthY_;
844}
845
846template <typename T>
848{
849 return radialDistortion_;
850}
851
852template <typename T>
854{
855 return tangentialDistortion_;
856}
857
858template <typename T>
860{
861 ocean_assert(isValid());
862
863 /**
864 * x = Fx * X / Z + mx
865 *
866 * (x - mx) / Fx = X / Z
867 */
868
869 if (NumericT<T>::isEqualEps(focalLengthX()))
870 {
871 return T(0);
872 }
873
874 const T leftAngle = NumericT<T>::abs(NumericT<T>::atan(-principalPointX() * invFocalLengthX_));
875
876 if (T(width_) <= principalPointX())
877 {
878 ocean_assert(false && "Invalid principal point");
879 return T(2) * leftAngle;
880 }
881
882 const T rightAngle = NumericT<T>::atan((T(width_) - principalPointX()) * invFocalLengthX_);
883
884 return leftAngle + rightAngle;
885}
886
887template <typename T>
889{
890 ocean_assert(isValid());
891
892 /**
893 * y = Fy * Y / Z + my
894 *
895 * (y - my) / Fy = Y / Z
896 */
897
898 if (NumericT<T>::isEqualEps(focalLengthY()))
899 {
900 return T(0);
901 }
902
903 const T topAngle = NumericT<T>::abs(NumericT<T>::atan(-principalPointY() * invFocalLengthY_));
904
905 if (T(height_) <= principalPointY())
906 {
907 ocean_assert(false && "Invalid principal point");
908 return T(2) * topAngle;
909 }
910
911 const T bottomAngle = NumericT<T>::atan((T(height_) - principalPointY()) * invFocalLengthY_);
912
913 return topAngle + bottomAngle;
914}
915
916template <typename T>
918{
919 ocean_assert(isValid());
920
921 const VectorT2<T> cornerTopLeft(-principalPointX(), -principalPointY());
922 const VectorT2<T> cornerTopRight(T(width_) - principalPointX(), -principalPointY());
923 const VectorT2<T> cornerBottomLeft(-principalPointX(), T(height_) - principalPointY());
924 const VectorT2<T> cornerBottomRight(T(width_) - principalPointX(), T(height_) - principalPointY());
925
926 const T lengthDiagonalTopLeftBottomRight = cornerTopLeft.length() + cornerBottomRight.length();
927 const T lengthDiagonalBottomLeftTopRight = cornerBottomLeft.length() + cornerTopRight.length();
928
929 const T maxDiagonal = std::max(lengthDiagonalTopLeftBottomRight, lengthDiagonalBottomLeftTopRight);
930
931 const T maxDiagonal_2 = maxDiagonal * T(0.5);
932
933 const T invFocalLength = (invFocalLengthX_ + invFocalLengthY_) * T(0.5);
934
935 return T(2) * NumericT<T>::atan(maxDiagonal_2 * invFocalLength);
936}
937
938template <typename T>
939template <typename TParameter>
940void FisheyeCameraT<T>::copyParameters(unsigned int& width, unsigned int& height, std::vector<TParameter>& parameters, ParameterConfiguration& parameterConfiguration) const
941{
942 if (isValid())
943 {
944 width = width_;
945 height = height_;
946
947 parameters =
948 {
949 TParameter(focalLengthX_),
950 TParameter(focalLengthY_),
951
952 TParameter(principalPointX_),
953 TParameter(principalPointY_),
954
955 TParameter(radialDistortion_[0]),
956 TParameter(radialDistortion_[1]),
957 TParameter(radialDistortion_[2]),
958 TParameter(radialDistortion_[3]),
959 TParameter(radialDistortion_[4]),
960 TParameter(radialDistortion_[5]),
961
962 TParameter(tangentialDistortion_[0]),
963 TParameter(tangentialDistortion_[1]),
964 };
965
966 ocean_assert(parameters.size() == 12);
967
968 parameterConfiguration = PC_12_PARAMETERS;
969 }
970 else
971 {
972 width = 0u;
973 height = 0u;
974
975 parameters.clear();
976
977 parameterConfiguration = PC_UNKNOWN;
978 }
979}
980
981template <typename T>
982inline bool FisheyeCameraT<T>::isInside(const VectorT2<T>& imagePoint, const T signedBorder) const
983{
984 ocean_assert(isValid());
985 ocean_assert(signedBorder < T(std::min(width_ / 2u, height_ / 2u)));
986
987 return imagePoint.x() >= signedBorder && imagePoint.y() >= signedBorder
988 && imagePoint.x() < T(width_) - signedBorder && imagePoint.y() < T(height_) - signedBorder;
989}
990
991template <typename T>
993{
994 ocean_assert(isValid());
995
996 /*
997 * 3) Six radial distortion parameters k3, k5, k7, k9, k11, k13
998 *
999 * 4) Two tangential distortion parameters p1 and p2.
1000 *
1001 * An undistorted image point (x, y), is transformed to the corresponding distorted image point (x', y') as follows:
1002 * x' = x_r + x_t
1003 * y' = y_r + y_t
1004
1005 * radial distortion:
1006 * x_r = x * (theta + k3 * theta^3 + k5 * theta^5 + k7 * theta^7 + k9 * theta^9 + k11 * theta^11 + k13 * theta^13) / r
1007 * y_r = y * (theta + k3 * theta^3 + k5 * theta^5 + k7 * theta^7 + k9 * theta^9 + k11 * theta^11 + k13 * theta^13) / r
1008 *
1009 * tangential distortion:
1010 * x_t = p1 * (2 * x_r^2 + radial^2) + p2 * 2 * x_r * y_r,
1011 * y_t = p2 * (2 * y_r^2 + radial^2) + p1 * 2 * x_r * y_r.
1012 *
1013 * with
1014 * r = sqrt(x^2 + y^2)
1015 * theta = atan(r)
1016 * radial^2 = x_r^2 + y_r^2
1017 *
1018 * With x, y undistorted normalized coordinates
1019 * With x', y' distorted normalized coordinates
1020 */
1021
1022 const T r2 = undistortedNormalized.sqr();
1023 const T r = NumericT<T>::sqrt(r2);
1024
1026 {
1027 return VectorT2<T>(0, 0);
1028 }
1029
1030 const T theta = NumericT<T>::atan(r);
1031
1032 if (hasDistortionParameters_)
1033 {
1034 const T theta2 = theta * theta;
1035 const T theta3 = theta2 * theta;
1036 const T theta5 = theta2 * theta3;
1037 const T theta7 = theta2 * theta5;
1038 const T theta9 = theta2 * theta7;
1039 const T theta11 = theta2 * theta9;
1040 const T theta13 = theta2 * theta11;
1041
1042 const T& k3 = radialDistortion_[0];
1043 const T& k5 = radialDistortion_[1];
1044 const T& k7 = radialDistortion_[2];
1045 const T& k9 = radialDistortion_[3];
1046 const T& k11 = radialDistortion_[4];
1047 const T& k13 = radialDistortion_[5];
1048
1049 const T radialDistortionFactor = (theta + k3 * theta3 + k5 * theta5 + k7 * theta7 + k9 * theta9 + k11 * theta11 + k13 * theta13) / r;
1050
1051 const T x_r = undistortedNormalized.x() * radialDistortionFactor;
1052 const T y_r = undistortedNormalized.y() * radialDistortionFactor;
1053
1054 const T radius_r2 = x_r * x_r + y_r * y_r;
1055
1056 const T& p1 = tangentialDistortion_[0];
1057 const T& p2 = tangentialDistortion_[1];
1058
1059 const T x_t = p1 * (T(2) * x_r * x_r + radius_r2) + p2 * T(2) * x_r * y_r;
1060 const T y_t = p2 * (T(2) * y_r * y_r + radius_r2) + p1 * T(2) * x_r * y_r;
1061
1062 return VectorT2<T>(x_r + x_t, y_r + y_t);
1063 }
1064 else
1065 {
1066 const T scale = theta / r;
1067
1068 return VectorT2<T>(undistortedNormalized.x() * scale, undistortedNormalized.y() * scale);
1069 }
1070}
1071
1072template <typename T>
1074{
1075 ocean_assert(isValid());
1076
1077 const VectorT2<T> distortedTangentialFree = tangentialFreeDistortion(distortedNormalized);
1078
1079 const T& k3 = radialDistortion_[0];
1080 const T& k5 = radialDistortion_[1];
1081 const T& k7 = radialDistortion_[2];
1082 const T& k9 = radialDistortion_[3];
1083 const T& k11 = radialDistortion_[4];
1084 const T& k13 = radialDistortion_[5];
1085
1086 const T r = distortedTangentialFree.length();
1087
1089 {
1090 return VectorT2<T>(0, 0);
1091 }
1092
1093 T theta = NumericT<T>::pow(r, T(0.3333333333333));
1094
1095 for (unsigned int n = 0u; n < 10u; ++n)
1096 {
1097 const T theta2 = theta * theta;
1098 const T theta4 = theta2 * theta2;
1099 const T theta6 = theta4 * theta2;
1100 const T theta8 = theta6 * theta2;
1101 const T theta10 = theta8 * theta2;
1102 const T theta12 = theta10 * theta2;
1103
1104 const T error = theta * (T(1) + k3 * theta2 + k5 * theta4 + k7 * theta6 + k9 * theta8 + k11 * theta10 + k13 * theta12) - r;
1105
1106 const T df = T(1) + T(3) * k3 * theta2 + T(5) * k5 * theta4 + T(7) * k7 * theta6 + T(9) * k9 * theta8 + T(11) * k11 * theta10 + T(13) * k13 * theta12;
1107
1108 if constexpr (std::is_same_v<T, float>)
1109 {
1111 {
1112 break;
1113 }
1114 }
1115 else
1116 {
1118 {
1119 break;
1120 }
1121 }
1122
1123 const T delta = error / df;
1124
1125 if constexpr (std::is_same_v<T, float>)
1126 {
1127 if (NumericT<T>::isNan(delta) || NumericT<T>::isInf(delta) || NumericT<T>::isEqualEps(delta))
1128 {
1129 break;
1130 }
1131 }
1132 else
1133 {
1134 if (NumericT<T>::isEqualEps(delta))
1135 {
1136 break;
1137 }
1138 }
1139
1140 theta -= delta;
1141 }
1142
1143 const T scale = NumericT<T>::tan(theta) / r;
1144
1145 return distortedTangentialFree * scale;
1146}
1147
1148template <typename T>
1149inline VectorT2<T> FisheyeCameraT<T>::projectToImage(const VectorT3<T>& worldObjectPoint) const
1150{
1151 ocean_assert(isValid());
1152
1153 return projectToImageIF(VectorT3<T>(worldObjectPoint.x(), -worldObjectPoint.y(), -worldObjectPoint.z()));
1154}
1155
1156template <typename T>
1157inline VectorT2<T> FisheyeCameraT<T>::projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const VectorT3<T>& worldObjectPoint) const
1158{
1159 ocean_assert(isValid());
1160
1161 ocean_assert(world_T_camera.isValid());
1162 return projectToImageIF(CameraT<T>::standard2InvertedFlipped(world_T_camera), worldObjectPoint);
1163}
1164
1165template <typename T>
1166VectorT2<T> FisheyeCameraT<T>::projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const VectorT3<T>& worldObjectPoint) const
1167{
1168 ocean_assert(isValid());
1169
1170 ocean_assert(flippedCamera_T_world.isValid());
1171 return projectToImageIF(flippedCamera_T_world * worldObjectPoint);
1172}
1173
1174template <typename T>
1176{
1177 ocean_assert(isValid());
1178 ocean_assert(NumericT<T>::isNotEqualEps(cameraFlippedObjectPoint.z()));
1179
1180 const T invZ = T(1) / cameraFlippedObjectPoint.z();
1181
1182 const VectorT2<T> undistortedNormalized(cameraFlippedObjectPoint.x() * invZ, cameraFlippedObjectPoint.y() * invZ);
1183 const VectorT2<T> distortedNormalizedImagePoint = distortNormalized(undistortedNormalized);
1184
1185 return VectorT2<T>(distortedNormalizedImagePoint.x() * focalLengthX() + principalPointX(), distortedNormalizedImagePoint.y() * focalLengthY() + principalPointY());
1186}
1187
1188template <typename T>
1189inline VectorT3<T> FisheyeCameraT<T>::vector(const VectorT2<T>& distortedImagePoint, const bool makeUnitVector) const
1190{
1191 ocean_assert(isValid());
1192
1193 const VectorT2<T> distortedNormalized((distortedImagePoint.x() - principalPointX_) * invFocalLengthX_, (distortedImagePoint.y() - principalPointY_) * invFocalLengthY_);
1194 const VectorT2<T> undistortedNormalized = undistortNormalized(distortedNormalized);
1195
1196 if (makeUnitVector)
1197 {
1198 return VectorT3<T>(undistortedNormalized.x(), -undistortedNormalized.y(), T(-1)).normalized();
1199 }
1200 else
1201 {
1202 return VectorT3<T>(undistortedNormalized.x(), -undistortedNormalized.y(), T(-1));
1203 }
1204}
1205
1206template <typename T>
1207inline VectorT3<T> FisheyeCameraT<T>::vectorIF(const VectorT2<T>& distortedImagePoint, const bool makeUnitVector) const
1208{
1209 ocean_assert(isValid());
1210
1211 const VectorT2<T> distortedNormalized((distortedImagePoint.x() - principalPointX_) * invFocalLengthX_, (distortedImagePoint.y() - principalPointY_) * invFocalLengthY_);
1212 const VectorT2<T> undistortedNormalized = undistortNormalized(distortedNormalized);
1213
1214 if (makeUnitVector)
1215 {
1216 return VectorT3<T>(undistortedNormalized.x(), undistortedNormalized.y(), T(1)).normalized();
1217 }
1218 else
1219 {
1220 return VectorT3<T>(undistortedNormalized.x(), undistortedNormalized.y(), T(1));
1221 }
1222}
1223
1224template <typename T>
1225inline LineT3<T> FisheyeCameraT<T>::ray(const VectorT2<T>& distortedImagePoint, const HomogenousMatrixT4<T>& world_T_camera) const
1226{
1227 ocean_assert(isValid() && world_T_camera.isValid());
1228
1229 return LineT3<T>(world_T_camera.translation(), world_T_camera.rotationMatrix(vector(distortedImagePoint)));
1230}
1231
1232template <typename T>
1233inline LineT3<T> FisheyeCameraT<T>::ray(const VectorT2<T>& distortedImagePoint) const
1234{
1235 ocean_assert(isValid());
1236
1237 return LineT3<T>(VectorT3<T>(0, 0, 0), vector(distortedImagePoint));
1238}
1239
1240template <typename T>
1241inline void FisheyeCameraT<T>::pointJacobian2x3IF(const VectorT3<T>& flippedCameraObjectPoint, T* jx, T* jy) const
1242{
1243 ocean_assert(isValid());
1244 ocean_assert(jx != nullptr && jy != nullptr);
1245
1246 const T fx = focalLengthX();
1247 const T fy = focalLengthY();
1248
1249 const T u = flippedCameraObjectPoint.x();
1250 const T v = flippedCameraObjectPoint.y();
1251 const T w = flippedCameraObjectPoint.z();
1252
1253 ocean_assert(NumericT<T>::isNotEqualEps(w));
1254 const T invW = T(1) / w;
1255
1256 const T u_invW = u * invW;
1257 const T v_invW = v * invW;
1258
1259 T jDistX[2];
1260 T jDistY[2];
1261
1262 jacobianDistortNormalized2x2(u_invW, v_invW, radialDistortion_, tangentialDistortion_, jDistX, jDistY);
1263
1264 const T fx_jDistXx_invW = fx * jDistX[0] * invW;
1265 const T fy_jDistYx_invW = fy * jDistY[0] * invW;
1266
1267 const T fx_jDistXy_invW = fx * jDistX[1] * invW;
1268 const T fy_jDistYy_invW = fy * jDistY[1] * invW;
1269
1270 const T u_fx_jDistXx__ = u_invW * fx_jDistXx_invW + v_invW * fx_jDistXy_invW;
1271 const T u_fy_jDistYx__ = u_invW * fy_jDistYx_invW + v_invW * fy_jDistYy_invW;
1272
1273 jx[0] = fx_jDistXx_invW;
1274 jx[1] = fx_jDistXy_invW;
1275 jx[2] = -u_fx_jDistXx__;
1276
1277 jy[0] = fy_jDistYx_invW;
1278 jy[1] = fy_jDistYy_invW;
1279 jy[2] = -u_fy_jDistYx__;
1280}
1281
1282template <typename T>
1283bool FisheyeCameraT<T>::isEqual(const FisheyeCameraT<T>& fisheyeCamera, const T eps) const
1284{
1285 return width_ == fisheyeCamera.width_ && height_ == fisheyeCamera.height_ && hasDistortionParameters_ == fisheyeCamera.hasDistortionParameters_
1286 && NumericT<T>::isEqual(focalLengthX_, fisheyeCamera.focalLengthX_, eps) && NumericT<T>::isEqual(focalLengthY_, fisheyeCamera.focalLengthY_, eps)
1287 && NumericT<T>::isEqual(principalPointX_, fisheyeCamera.principalPointX_, eps) && NumericT<T>::isEqual(principalPointY_, fisheyeCamera.principalPointY_, eps)
1288 && NumericT<T>::isEqual(radialDistortion_[0], fisheyeCamera.radialDistortion_[0], eps) && NumericT<T>::isEqual(radialDistortion_[1], fisheyeCamera.radialDistortion_[1], eps)
1289 && NumericT<T>::isEqual(radialDistortion_[2], fisheyeCamera.radialDistortion_[2], eps) && NumericT<T>::isEqual(radialDistortion_[3], fisheyeCamera.radialDistortion_[3], eps)
1290 && NumericT<T>::isEqual(radialDistortion_[4], fisheyeCamera.radialDistortion_[4], eps) && NumericT<T>::isEqual(radialDistortion_[5], fisheyeCamera.radialDistortion_[5], eps)
1291 && NumericT<T>::isEqual(tangentialDistortion_[0], fisheyeCamera.tangentialDistortion_[0], eps) && NumericT<T>::isEqual(tangentialDistortion_[1], fisheyeCamera.tangentialDistortion_[1], eps);
1292}
1293
1294template <typename T>
1296{
1297 ocean_assert(NumericT<T>::isEqualEps(focalLengthX_) || NumericT<T>::isEqual(T(1) / focalLengthX_, invFocalLengthX_));
1298 ocean_assert(NumericT<T>::isEqualEps(focalLengthY_) || NumericT<T>::isEqual(T(1) / focalLengthY_, invFocalLengthY_));
1299
1300 return width_ != 0u && height_ != 0u;
1301}
1302
1303template <typename T>
1304bool FisheyeCameraT<T>::operator==(const FisheyeCameraT<T>& fisheyeCamera) const
1305{
1306 return width_ == fisheyeCamera.width_ && height_ == fisheyeCamera.height_
1307 && focalLengthX_ == fisheyeCamera.focalLengthX_ && focalLengthY_ == fisheyeCamera.focalLengthY_
1308 && invFocalLengthX_ == fisheyeCamera.invFocalLengthX_ && invFocalLengthY_ == fisheyeCamera.invFocalLengthY_
1309 && principalPointX_ == fisheyeCamera.principalPointX_ && principalPointY_ == fisheyeCamera.principalPointY_
1310 && hasDistortionParameters_ == fisheyeCamera.hasDistortionParameters_
1311 && memcmp(radialDistortion_, fisheyeCamera.radialDistortion_, sizeof(T) * 6) == 0
1312 && memcmp(tangentialDistortion_, fisheyeCamera.tangentialDistortion_, sizeof(T) * 2) == 0;
1313}
1314
1315template <typename T>
1316inline bool FisheyeCameraT<T>::operator!=(const FisheyeCameraT<T>& fisheyeCamera) const
1317{
1318 return !(*this == fisheyeCamera);
1319}
1320
1321template <typename T>
1323{
1324 return isValid();
1325}
1326
1327template <typename T>
1329{
1330 // x' = x_r + x_t
1331 // y' = y_r + y_t
1332
1333 // x_t = p1 * (2 * x_r^2 + radial^2) + p2 * 2 * x_r * y_r
1334 // y_t = p2 * (2 * y_r^2 + radial^2) + p1 * 2 * x_r * y_r
1335
1336 // newton-based solving for x_r, y_r:
1337 // x' = p1 * (2 * x_r^2 + radial^2) + p2 * 2 * x_r * y_r + x_r
1338 // y' = p2 * (2 * y_r^2 + radial^2) + p1 * 2 * x_r * y_r + y_r
1339
1340 const T& p1 = tangentialDistortion_[0];
1341 const T& p2 = tangentialDistortion_[1];
1342
1344 {
1345 return distortedNormalized;
1346 }
1347
1348 VectorT2<T> distortedTangentialFree(distortedNormalized);
1349
1350 for (unsigned int n = 0u; n < 2u; ++n)
1351 {
1352 const T& x_r = distortedTangentialFree.x();
1353 const T& y_r = distortedTangentialFree.y();
1354
1355 const T resultX = p1 * T(3) * x_r * x_r + p1 * y_r * y_r + T(2) * p2 * x_r * y_r + x_r - distortedNormalized.x();
1356 const T resultY = p2 * T(3) * y_r * y_r + p2 * x_r * x_r + T(2) * p1 * x_r * y_r + y_r - distortedNormalized.y();
1357
1358 const T dxx = p1 * T(6) * x_r + T(2) * p2 * y_r + T(1);
1359 const T dxy = p1 * T(2) * y_r + T(2) * p2 * x_r;
1360
1361 const T& dyx = dxy; // dyx == p2 * T(2) * y_r + T(2) * p1 * x_r;
1362 const T dyy = p2 * T(6) * y_r + T(2) * p1 * x_r + T(1);
1363
1364 VectorT2<T> delta(0, 0);
1365 SquareMatrixT2<T>(dxx, dyx, dxy, dyy).solve(VectorT2<T>(resultX, resultY), delta);
1366
1367 distortedTangentialFree -= delta;
1368
1369 if (delta.sqr() < NumericT<T>::eps())
1370 {
1371 break;
1372 }
1373 }
1374
1375 return distortedTangentialFree;
1376}
1377
1378template <typename T>
1379OCEAN_FORCE_INLINE void FisheyeCameraT<T>::jacobianDistortNormalized2x2(const T x, const T y, const T* radialDistortion, const T* tangentialDistortion, T* jx, T* jy)
1380{
1381 ocean_assert(jx != nullptr && jy != nullptr);
1382 ocean_assert(radialDistortion != nullptr && tangentialDistortion != nullptr);
1383
1384 const T& k3 = radialDistortion[0];
1385 const T& k5 = radialDistortion[1];
1386 const T& k7 = radialDistortion[2];
1387 const T& k9 = radialDistortion[3];
1388 const T& k11 = radialDistortion[4];
1389 const T& k13 = radialDistortion[5];
1390
1391 const T& p1 = tangentialDistortion[0];
1392 const T& p2 = tangentialDistortion[1];
1393
1394 const T x2 = x * x;
1395 const T y2 = y * y;
1396
1397 const T xy2 = x2 + y2;
1398
1399 const T r = NumericT<T>::sqrt(xy2);
1400 const T r3 = r * r * r;
1401
1402 const T t = NumericT<T>::atan(r);
1403 const T t2 = t * t;
1404 const T t3 = t2 * t;
1405 const T t4 = t3 * t;
1406 const T t5 = t4 * t;
1407 const T t6 = t5 * t;
1408 const T t7 = t6 * t;
1409 const T t8 = t7 * t;
1410 const T t9 = t8 * t;
1411 const T t10 = t9 * t;
1412 const T t11 = t10 * t;
1413 const T t12 = t11 * t;
1414 const T t13 = t12 * t;
1415
1416 const T term0 = k13 * t13 + k11 * t11 + k9 * t9 + k7 * t7 + k5 * t5 + k3 * t3 + t;
1417 const T term1 = 13 * k13 * t12 + 11 * k11 * t10 + 9 * k9 * t8 + 7 * k7 * t6 + 5 * k5 * t4 + 3 * k3 * t2 + 1;
1418
1419 const T term2 = (xy2 + 1) * term0;
1420 const T term3 = r3 * (xy2 + 1);
1421 const T invTerm3 = T(1) / term3;
1422
1423 const T xDistortion_dx = (xy2 * term2 - x2 * term2 + x2 * r * term1) * invTerm3;
1424 const T xDistortion_dy = (x * term1 * y) / (xy2 * (xy2 + 1)) - (x * y * term0) / r3;
1425
1426 //const T yDistortion_dx = (y * term1 * x) / (xy2 * (xy2 + 1)) - (y * x * term0) / r3; == xDistortion_dy
1427 const T& yDistortion_dx = xDistortion_dy;
1428 const T yDistortion_dy = (xy2 * term2 - y2 * term2 + y2 * r * term1) * invTerm3;
1429
1430 const T radialDistortionFactor = term0 / r;
1431
1432 const T rx = x * radialDistortionFactor;
1433 const T ry = y * radialDistortionFactor;
1434
1435 const T xTangential_dx = 6 * p1 * rx + 2 * p2 * ry + 1;
1436 const T xTangential_dy = 2 * p1 * ry + 2 * p2 * rx;
1437
1438 // const T yTangential_dx = 2 * p2 * rx + 2 * p1 * ry; // == xTangential_dx
1439 const T& yTangential_dx = xTangential_dy;
1440 const T yTangential_dy = 6 * p2 * ry + 2 * p1 * rx + 1;
1441
1442 // chain rule
1443 // | xTangential_dx xTangential_dy | | xDistortion_dx xDistortion_dy |
1444 // | yTangential_dx yTangential_dy | * | yDistortion_dx yDistortion_dy |
1445
1446 jx[0] = xTangential_dx * xDistortion_dx + xTangential_dy * yDistortion_dx;
1447 jx[1] = xTangential_dx * xDistortion_dy + xTangential_dy * yDistortion_dy;
1448
1449 jy[0] = yTangential_dx * xDistortion_dx + yTangential_dy * yDistortion_dx;
1450 jy[1] = yTangential_dx * xDistortion_dy + yTangential_dy * yDistortion_dy;
1451}
1452
1453}
1454
1455#endif // META_OCEAN_MATH_FISHEYE_CAMERA_H
This class implements the base class for all cameras.
Definition Camera.h:98
bool isValid() const
Returns whether this camera is valid.
Definition FisheyeCamera.h:1295
FisheyeCameraT(const unsigned int width, const unsigned int height, const T fovX)
Creates a new camera object with known field of view.
Definition FisheyeCamera.h:583
const T * radialDistortion() const
Returns the six radial distortion parameters of the camera model.
Definition FisheyeCamera.h:847
T invFocalLengthX_
The horizontal inverse focal length of the camera, with range (0, infinity)
Definition FisheyeCamera.h:535
VectorT2< T > undistortNormalized(const VectorT2< T > &distortedNormalized) const
Returns the normalized undistorted position of a given distorted normalized position.
Definition FisheyeCamera.h:1073
T principalPointX() const
Returns the x-value of the principal point of the camera image in the pixel domain.
Definition FisheyeCamera.h:811
bool operator!=(const FisheyeCameraT< T > &fisheyeCamera) const
Returns whether two fisheye cameras are not identical.
Definition FisheyeCamera.h:1316
FisheyeCameraT(const FisheyeCameraT< T > &fisheyeCamera)=default
Copy constructor.
unsigned int height() const
Returns the height of the camera image.
Definition FisheyeCamera.h:799
void pointJacobian2x3IF(const VectorT3< T > &flippedCameraObjectPoint, T *jx, T *jy) const
Calculates the 2x3 jacobian matrix for the 3D object point projection into the camera frame.
Definition FisheyeCamera.h:1241
VectorT2< T > principalPoint() const
Returns the coordinate of the principal point of the camera image in the pixel domain.
Definition FisheyeCamera.h:805
unsigned int height_
Height of the camera image, in pixel.
Definition FisheyeCamera.h:526
FisheyeCameraT(const unsigned int width, const unsigned int height, const ParameterConfiguration parameterConfiguration, const TParameter *parameters)
Creates a new camera object with parameters with specific configuration.
Definition FisheyeCamera.h:687
VectorT2< T > projectToImage(const HomogenousMatrixT4< T > &world_T_camera, const VectorT3< T > &worldObjectPoint) const
Projects a 3D object point into the camera's image of the fisheye camera.
Definition FisheyeCamera.h:1157
T fovY() const
Returns the field of view in x direction of the camera.
Definition FisheyeCamera.h:888
VectorT2< T > projectToImageIF(const VectorT3< T > &cameraFlippedObjectPoint) const
Projects a 3D object point to the 2D image plane of the fisheye camera.
Definition FisheyeCamera.h:1175
T Type
Definition of the used data type.
Definition FisheyeCamera.h:114
const T * tangentialDistortion() const
Returns the two tangential distortion parameters of the camera model.
Definition FisheyeCamera.h:853
T focalLengthY_
The vertical focal length of the camera, with range (0, infinity)
Definition FisheyeCamera.h:532
T principalPointX_
The horizontal principal point of the camera, in pixels, with range [0, width())
Definition FisheyeCamera.h:541
T fovX() const
Returns the field of view in x direction of the camera.
Definition FisheyeCamera.h:859
friend class FisheyeCameraT
Definition FisheyeCamera.h:107
VectorT2< T > projectToImage(const VectorT3< T > &worldObjectPoint) const
Projects a 3D object point into the camera's image of the fisheye camera.
Definition FisheyeCamera.h:1149
VectorT3< T > vector(const VectorT2< T > &distortedImagePoint, const bool makeUnitVector=true) const
Returns a vector starting at the camera's center and intersecting a given 2D point in the image.
Definition FisheyeCamera.h:1189
T focalLengthX_
The horizontal focal length of the camera, with range (0, infinity)
Definition FisheyeCamera.h:529
T radialDistortion_[6]
The six radial distortion parameters.
Definition FisheyeCamera.h:550
T inverseFocalLengthX() const
Returns the inverse horizontal focal length parameter.
Definition FisheyeCamera.h:835
bool hasDistortionParameters() const
Returns whether this camera object has specified distortion parameters.
Definition FisheyeCamera.h:787
T tangentialDistortion_[2]
The two tangential distortion parameters.
Definition FisheyeCamera.h:553
T principalPointY_
The vertical principal point of the camera, in pixels, with range [0, height())
Definition FisheyeCamera.h:544
T invFocalLengthY_
The vertical inverse focal length of the camera, with range (0, infinity)
Definition FisheyeCamera.h:538
bool operator==(const FisheyeCameraT< T > &fisheyeCamera) const
Returns whether two fisheye cameras are identical.
Definition FisheyeCamera.h:1304
FisheyeCameraT(const unsigned int width, const unsigned int height, const T focalX, const T focalY, const T principalX, const T principalY)
Creates a new camera object without distortion parameters.
Definition FisheyeCamera.h:623
unsigned int width_
Width of the camera image, in pixel.
Definition FisheyeCamera.h:523
T focalLengthX() const
Returns the horizontal focal length parameter.
Definition FisheyeCamera.h:823
void copyParameters(unsigned int &width, unsigned int &height, std::vector< TParameter > &parameters, ParameterConfiguration &parameterConfiguration) const
Copies the parameters of this camera.
Definition FisheyeCamera.h:940
FisheyeCameraT(const unsigned int width, const unsigned int height, const TParameter focalX, const TParameter focalY, const TParameter principalX, const TParameter principalY, const TParameter *radialDistortion, const TParameter *tangentialDistortion)
Creates a new camera object with distortion parameters.
Definition FisheyeCamera.h:652
FisheyeCameraT< T > & operator=(const FisheyeCameraT< T > &fisheyeCamera)=default
Copy assignment operator.
FisheyeCameraT()=default
Default constructor creating an invalid camera object.
VectorT2< T > distortNormalized(const VectorT2< T > &undistortedNormalized) const
Returns the normalized distorted position of a given undistorted normalized position.
Definition FisheyeCamera.h:992
ParameterConfiguration
Definition of individual parameter configurations.
Definition FisheyeCamera.h:120
@ PC_12_PARAMETERS
12 parameters with order: horizontal focal length, vertical focal length, horizontal principal point,...
Definition FisheyeCamera.h:162
@ PC_11_PARAMETERS_ONE_FOCAL_LENGTH
11 parameters with order: focal length (one identical value for horizontal and vertical direction),...
Definition FisheyeCamera.h:151
@ PC_3_PARAMETERS_ONE_FOCAL_LENGTH
3 parameters with order: focal length (one identical value for horizontal and vertical direction),...
Definition FisheyeCamera.h:132
@ PC_4_PARAMETERS
4 parameters with order: horizontal focal length, vertical focal length, horizontal principal point,...
Definition FisheyeCamera.h:141
@ PC_UNKNOWN
An unknown parameter configuration.
Definition FisheyeCamera.h:124
bool isEqual(const FisheyeCameraT< T > &fisheyeCamera, const T eps=NumericT< T >::eps()) const
Returns whether two camera profiles are identical up to a given epsilon.
Definition FisheyeCamera.h:1283
unsigned int width() const
Returns the width of the camera image.
Definition FisheyeCamera.h:793
T fovDiagonal() const
Returns the diagonal field of view of the camera.
Definition FisheyeCamera.h:917
T focalLengthY() const
Returns the vertical focal length parameter.
Definition FisheyeCamera.h:829
LineT3< T > ray(const VectorT2< T > &distortedImagePoint) const
Returns a ray starting at the camera's center and intersecting a given 2D point in the image.
Definition FisheyeCamera.h:1233
static OCEAN_FORCE_INLINE void jacobianDistortNormalized2x2(const T x, const T y, const T *radialDistortion, const T *tangentialDistortion, T *jx, T *jy)
Determines the 2x2 Jacobian of distorting a normalized image point in a fisheye camera with radial an...
Definition FisheyeCamera.h:1379
VectorT2< T > projectToImageIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const VectorT3< T > &worldObjectPoint) const
Projects a 3D object point to the 2D image plane of the fisheye camera by a given inverted (and flipp...
Definition FisheyeCamera.h:1166
FisheyeCameraT(const FisheyeCameraT< U > &fisheyeCamera)
Copy constructor for a fisheye camera with difference element data type than T.
Definition FisheyeCamera.h:558
bool hasDistortionParameters_
True, if the distortion parameters are defined.
Definition FisheyeCamera.h:547
VectorT2< T > tangentialFreeDistortion(const VectorT2< T > &distortedNormalized) const
Calculates the tangential-free distortion of a normalized (distorted) image point.
Definition FisheyeCamera.h:1328
bool isInside(const VectorT2< T > &imagePoint, const T signedBorder=T(0)) const
Returns whether a given 2D image point lies inside the camera frame.
Definition FisheyeCamera.h:982
T inverseFocalLengthY() const
Returns the inverse vertical focal length parameter.
Definition FisheyeCamera.h:841
VectorT3< T > vectorIF(const VectorT2< T > &distortedImagePoint, const bool makeUnitVector=true) const
Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane...
Definition FisheyeCamera.h:1207
T principalPointY() const
Returns the y-value of the principal point of the camera image in the pixel domain.
Definition FisheyeCamera.h:817
LineT3< T > ray(const VectorT2< T > &distortedImagePoint, const HomogenousMatrixT4< T > &world_T_camera) const
Returns a ray starting at the camera's center and intersecting a given 2D point in the image.
Definition FisheyeCamera.h:1225
This class implements a 4x4 homogeneous transformation matrix using floating point values with the pr...
Definition HomogenousMatrix4.h:110
SquareMatrixT3< T > rotationMatrix() const
Returns the rotation matrix of the transformation.
Definition HomogenousMatrix4.h:1493
VectorT3< T > translation() const
Returns the translation of the transformation.
Definition HomogenousMatrix4.h:1381
bool isValid() const
Returns whether this matrix is a valid homogeneous transformation.
Definition HomogenousMatrix4.h:1806
This class implements an infinite line in 3D space.
Definition Line3.h:68
This class provides basic numeric functionalities.
Definition Numeric.h:57
static T atan(const T value)
Returns the arctangent of a given value.
Definition Numeric.h:1620
static bool isInf(const T value)
Returns whether a given value is positive or negative infinity.
Definition Numeric.h:3120
static T pow(const T x, const T y)
Returns x raised to the power of y.
Definition Numeric.h:1866
static T abs(const T value)
Returns the absolute value of a given value.
Definition Numeric.h:1220
static T sqrt(const T value)
Returns the square root of a given value.
Definition Numeric.h:1537
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition Numeric.h:2395
static T tan(const T value)
Returns the tangent of a given value.
Definition Numeric.h:1604
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2096
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2246
This class implements a 2x2 square matrix.
Definition SquareMatrix2.h:73
bool solve(const VectorT2< T > &b, VectorT2< T > &x) const
Solve a simple 2x2 system of linear equations: Ax = b Beware: The system of linear equations is assum...
Definition SquareMatrix2.h:761
This class implements a vector with two elements.
Definition Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
T sqr() const
Returns the square of the vector length.
Definition Vector2.h:633
T length() const
Returns the length of the vector.
Definition Vector2.h:627
This class implements a vector with three elements.
Definition Vector3.h:97
const T & y() const noexcept
Returns the y value.
Definition Vector3.h:824
const T & x() const noexcept
Returns the x value.
Definition Vector3.h:812
VectorT3< T > normalized() const
Returns the normalized vector.
Definition Vector3.h:617
const T & z() const noexcept
Returns the z value.
Definition Vector3.h:836
std::vector< FisheyeCamera > FisheyeCameras
Definition of a vector holding camera objects.
Definition FisheyeCamera.h:59
std::vector< FisheyeCameraT< T > > FisheyeCamerasT
Definition of a typename alias for vectors with FisheyeCameraT objects.
Definition FisheyeCamera.h:53
The namespace covering the entire Ocean framework.
Definition Accessor.h:15