Ocean
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/Numeric.h"
17 #include "ocean/math/Vector2.h"
18 #include "ocean/math/Vector3.h"
19 
20 namespace Ocean
21 {
22 
23 // Forward declaration.
24 template <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  */
52 template <typename T>
53 using FisheyeCamerasT = std::vector<FisheyeCameraT<T>>;
54 
55 /**
56  * Definition of a vector holding camera objects.
57  * @ingroup math
58  */
59 typedef std::vector<FisheyeCamera> FisheyeCameras;
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  */
104 template <typename T>
105 class 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  typedef T Type;
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  */
176  FisheyeCameraT(const FisheyeCameraT<T>& fisheyeCamera) = default;
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>
184  explicit inline FisheyeCameraT(const FisheyeCameraT<U>& fisheyeCamera);
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, 13, 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  */
253  inline VectorT2<T> principalPoint() const;
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  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
348  */
349  template <bool tUseDistortionParameters = true>
350  VectorT2<T> distortNormalized(const VectorT2<T>& undistortedNormalized) const;
351 
352  /**
353  * Returns the normalized undistorted position of a given distorted normalized position.
354  * @param distortedNormalized Distorted normalized position to be undistorted
355  * @return Resulting undistorted normalized position
356  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
357  */
358  template <bool tUseDistortionParameters = true>
359  VectorT2<T> undistortNormalized(const VectorT2<T>& distortedNormalized) const;
360 
361  /**
362  * Projects a 3D object point into the camera's image of the fisheye camera.
363  * The 3D object point must be defined in relation to the (standard) camera coordinate system.<br>
364  * The default viewing direction of the standard camera is into the negative z-space with x-axis to the right, and y-axis upwards.
365  * @param worldObjectPoint 3D object point which is located in the world
366  * @return Resulting 2D image point within the camera frame
367  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
368  * @see projectToImageIF().
369  */
370  template <bool tUseDistortionParameters = true>
371  inline VectorT2<T> projectToImage(const VectorT3<T>& worldObjectPoint) const;
372 
373  /**
374  * Projects a 3D object point into the camera's image of the fisheye camera.
375  * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates (world from camera).<br>
376  * The default viewing direction of the camera is into the negative z-space with x-axis to the right, and y-axis upwards.
377  * @param world_T_camera The extrinsic camera matrix, must be valid
378  * @param worldObjectPoint 3D object point which is located in the world
379  * @return Resulting 2D image point within the camera frame
380  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
381  * @see projectToImageIF().
382  */
383  template <bool tUseDistortionParameters = true>
384  inline VectorT2<T> projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const VectorT3<T>& worldObjectPoint) const;
385 
386  /**
387  * Projects a 3D object point to the 2D image plane of the fisheye camera by a given inverted (and flipped) extrinsic camera matrix.
388  * 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>
389  * The default viewing direction of the flipped camera is into the positive z-space with x-axis to the right, and y-axis downwards.
390  * @param flippedCamera_T_world Inverted and flipped extrinsic camera matrix, must be valid
391  * @param worldObjectPoint 3D object point which is located in the world
392  * @return Resulting 2D image point within the camera frame
393  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
394  * @see projectToImage().
395  */
396  template <bool tUseDistortionParameters = true>
397  VectorT2<T> projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const VectorT3<T>& worldObjectPoint) const;
398 
399  /**
400  * Projects a 3D object point to the 2D image plane of the fisheye camera.
401  * The 3D object point must be defined in relation to the (flipped) camera coordinate system.<br>
402  * The default viewing direction of the flipped camera is into the positive z-space with x-axis to the right, and y-axis downwards.
403  * @param cameraFlippedObjectPoint 3D object point which is located in the flipped camera coordinate system
404  * @return Resulting 2D image point within the camera frame
405  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
406  * @see projectToImage().
407  */
408  template <bool tUseDistortionParameters = true>
409  VectorT2<T> projectToImageIF(const VectorT3<T>& cameraFlippedObjectPoint) const;
410 
411  /**
412  * Returns a unit vector (with length 1) starting at the camera's center and intersecting a given 2D point in the image.
413  * The vector is determined for the default camera looking into the negative z-space with y-axis up.
414  * @param distortedImagePoint 2D (distorted) position within the image, with range [0, width())x[0, height())
415  * @param makeUnitVector True, to return a vector with length 1; False, to return a vector with any length
416  * @return Unit vector pointing into the negative z-space
417  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
418  * @see vectorIF(), ray().
419  */
420  template <bool tUseDistortionParameters = true>
421  inline VectorT3<T> vector(const VectorT2<T>& distortedImagePoint, const bool makeUnitVector = true) const;
422 
423  /**
424  * Returns a normalized vector (with length 1) starting at the camera's center and intersecting a given 2D point on the image plane.
425  * The vector is determined for the default camera looking into the positive z-space with y-axis down.
426  * @param distortedImagePoint 2D (distorted) position within the image, with range [0, width())x[0, height())
427  * @param makeUnitVector True, to return a vector with length 1; False, to return a vector with any length
428  * @return Normalized vector into the negative z-space
429  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
430  * @see vector().
431  */
432  template <bool tUseDistortionParameters = true>
433  inline VectorT3<T> vectorIF(const VectorT2<T>& distortedImagePoint, const bool makeUnitVector = true) const;
434 
435  /**
436  * Returns a ray starting at the camera's center and intersecting a given 2D point in the image.
437  * @param distortedImagePoint 2D (distorted) position within the image, with range [0, width())x[0, height())
438  * @param world_T_camera The pose of the camera, the extrinsic camera matrix, must be valid
439  * @return The specified ray with direction pointing into the camera's negative z-space
440  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
441  * @see vector().
442  */
443  template <bool tUseDistortionParameters = true>
444  inline LineT3<T> ray(const VectorT2<T>& distortedImagePoint, const HomogenousMatrixT4<T>& world_T_camera) const;
445 
446  /**
447  * Returns a ray starting at the camera's center and intersecting a given 2D point in the image.
448  * @param distortedImagePoint 2D (distorted) position within the image, with range [0, width())x[0, height())
449  * @return The specified ray with direction pointing into the camera's negative z-space
450  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
451  * @see vector().
452  */
453  template <bool tUseDistortionParameters = true>
454  inline LineT3<T> ray(const VectorT2<T>& distortedImagePoint) const;
455 
456  /**
457  * Calculates the 2x3 jacobian matrix for the 3D object point projection into the camera frame.
458  * The resulting jacobian matrix has the following layout:
459  * <pre>
460  * | dfu / dx, dfu / dy, dfu / dz |
461  * | dfv / dx, dfv / dy, dfv / dz |
462  * with projection function
463  * q = f(p)
464  * q_u = fu(p), q_y = fv(p)
465  * with 2D image point q = (q_u, q_v) and 3D object point p = (x, y, z)
466  * </pre>
467  * @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).
468  * @param jx The resulting first row of the Jacobian matrix, must contain three elements, must be valid
469  * @param jy The resulting second row of the Jacobian matrix, must contain three elements, must be valid
470  * @tparam tUseDistortionParameters True, to use the camera's distortion parameter; False, to just scale the normalized image due to theta
471  */
472  template <bool tUseDistortionParameters = true>
473  inline void pointJacobian2x3IF(const VectorT3<T>& flippedCameraObjectPoint, T* jx, T* jy) const;
474 
475  /**
476  * Returns whether two camera profiles are identical up to a given epsilon.
477  * The image resolution must always be identical.
478  * @param fisheyeCamera The second camera profile to be used for comparison, can be invalid
479  * @param eps The epsilon threshold to be used, with range [0, infinity)
480  * @return True, if so
481  */
482  bool isEqual(const FisheyeCameraT<T>& fisheyeCamera, const T eps = NumericT<T>::eps()) const;
483 
484  /**
485  * Returns whether this camera is valid.
486  * @return True, if so
487  */
488  inline bool isValid() const;
489 
490  /**
491  * Returns whether two fisheye cameras are identical.
492  * @param fisheyeCamera The second fisheye camera to be check
493  * @return True, if so
494  */
495  bool operator==(const FisheyeCameraT<T>& fisheyeCamera) const;
496 
497  /**
498  * Returns whether two fisheye cameras are not identical.
499  * @param fisheyeCamera The second fisheye camera to be check
500  * @return True, if so
501  */
502  inline bool operator!=(const FisheyeCameraT<T>& fisheyeCamera) const;
503 
504  /**
505  * Copy assignment operator.
506  * @param fisheyeCamera The fisheye camera profile to be copied
507  * @return A reference to this object
508  */
509  FisheyeCameraT<T>& operator=(const FisheyeCameraT<T>& fisheyeCamera) = default;
510 
511  /**
512  * Returns whether the camera holds valid parameters.
513  * @return True, if so
514  */
515  explicit inline operator bool() const;
516 
517  protected:
518 
519  /**
520  * Calculates the tangential-free distortion of a normalized (distorted) image point.
521  * @param distortedNormalized The distorted normalized image point from which the tangential distortion will be removed
522  * @return The normalized image point containing radial distortion only
523  */
524  VectorT2<T> tangentialFreeDistortion(const VectorT2<T>& distortedNormalized) const;
525 
526  /**
527  * Determines the 2x2 Jacobian of distorting a normalized image point in a fisheye camera with radial and tangential distortion.
528  * The resulting jacobian has the following form:
529  * <pre>
530  * | dfx / dx, dfx / dy |
531  * | dfy / dx, dfy / dy |
532  * </pre>
533  * @param x The horizontal coordinate of the normalized image point to be distorted
534  * @param y The vertical coordinate of the normalized image point to be distorted
535  * @param radialDistortion The six radial distortion parameters, must be valid
536  * @param tangentialDistortion The two radial distortion parameters, must be valid
537  * @param jx First row of the jacobian, with 2 column entries, must be valid
538  * @param jy Second row of the jacobian, with 2 column entries, must be valid
539  */
540  static OCEAN_FORCE_INLINE void jacobianDistortNormalized2x2(const T x, const T y, const T* radialDistortion, const T* tangentialDistortion, T* jx, T* jy);
541 
542  protected:
543 
544  /// Width of the camera image, in pixel.
545  unsigned int cameraWidth_ = 0u;
546 
547  /// Height of the camera image, in pixel.
548  unsigned int cameraHeight_ = 0u;
549 
550  /// The horizontal focal length of the camera, with range (0, infinity)
551  T focalLengthX_ = T(0);
552 
553  /// The vertical focal length of the camera, with range (0, infinity)
554  T focalLengthY_ = T(0);
555 
556  /// The horizontal inverse focal length of the camera, with range (0, infinity)
558 
559  /// The vertical inverse focal length of the camera, with range (0, infinity)
561 
562  /// The horizontal principal point of the camera, in pixels, with range [0, width())
564 
565  /// The vertical principal point of the camera, in pixels, with range [0, width())
567 
568  /// True, if the distortion parameters are defined.
570 
571  /// The six radial distortion parameters.
572  T radialDistortion_[6] = {T(0), T(0), T(0), T(0), T(0), T(0)};
573 
574  /// The two tangential distortion parameters.
575  T tangentialDistortion_[2] = {T(0), T(0)};
576 };
577 
578 template <typename T>
579 template <typename U>
581  cameraWidth_(fisheyeCamera.cameraWidth_),
582  cameraHeight_(fisheyeCamera.cameraHeight_),
583  focalLengthX_(T(fisheyeCamera.focalLengthX_)),
584  focalLengthY_(T(fisheyeCamera.focalLengthY_)),
585  principalPointX_(T(fisheyeCamera.principalPointX_)),
586  principalPointY_(T(fisheyeCamera.principalPointY_)),
587  hasDistortionParameters_(fisheyeCamera.hasDistortionParameters_)
588 {
589  static_assert(sizeof(radialDistortion_) / 6u == sizeof(T), "Invalid parameter");
590  static_assert(sizeof(tangentialDistortion_) / 2u == sizeof(T), "Invalid parameter");
591 
594 
595  for (unsigned int n = 0u; n < 6u; ++n)
596  {
597  radialDistortion_[n] = T(fisheyeCamera.radialDistortion_[n]);
598  }
599 
600  tangentialDistortion_[0] = T(fisheyeCamera.tangentialDistortion_[0]);
601  tangentialDistortion_[1] = T(fisheyeCamera.tangentialDistortion_[1]);
602 }
603 
604 template <typename T>
605 inline FisheyeCameraT<T>::FisheyeCameraT(const unsigned int width, const unsigned int height, const T fovX) :
606  cameraWidth_(width),
607  cameraHeight_(height),
608  focalLengthX_(0),
609  focalLengthY_(0),
610  invFocalLengthX_(0),
611  invFocalLengthY_(0),
612  principalPointX_(0),
613  principalPointY_(0),
614  hasDistortionParameters_(false)
615 {
616  ocean_assert(cameraWidth_ != 0u && cameraHeight_ != 0u);
617  ocean_assert(fovX > NumericT<T>::eps() && fovX <= NumericT<T>::pi());
618 
619  const T principalX = T(cameraWidth_) * T(0.5);
620  const T principalY = T(cameraHeight_) * T(0.5);
621 
622  const T focalLength = principalX / NumericT<T>::tan(fovX * T(0.5));
623 
624  focalLengthX_ = focalLength;
625  focalLengthY_ = focalLength;
626 
627  ocean_assert(NumericT<T>::isNotEqualEps(focalLength));
628  const T invFocalLength = T(1) / focalLength;
629  invFocalLengthX_ = invFocalLength;
630  invFocalLengthY_ = invFocalLength;
631 
632  principalPointX_ = principalX;
633  principalPointY_ = principalY;
634 
635  for (unsigned int n = 0u; n < 6u; ++n)
636  {
637  radialDistortion_[n] = T(0);
638  }
639 
640  tangentialDistortion_[0] = T(0);
641  tangentialDistortion_[1] = T(0);
642 }
643 
644 template <typename T>
645 inline FisheyeCameraT<T>::FisheyeCameraT(const unsigned int width, const unsigned int height, const T focalX, const T focalY, const T principalX, const T principalY) :
646  cameraWidth_(width),
647  cameraHeight_(height),
648  focalLengthX_(focalX),
649  focalLengthY_(focalY),
650  invFocalLengthX_(0),
651  invFocalLengthY_(0),
652  principalPointX_(principalX),
653  principalPointY_(principalY),
654  hasDistortionParameters_(false)
655 {
656  ocean_assert(cameraWidth_ != 0u && cameraHeight_ != 0u);
657 
661  ocean_assert(fovX() > NumericT<T>::eps() && fovX() <= NumericT<T>::pi());
662 
663  for (unsigned int n = 0u; n < 6u; ++n)
664  {
665  radialDistortion_[n] = T(0);
666  }
667 
668  tangentialDistortion_[0] = T(0);
669  tangentialDistortion_[1] = T(0);
670 }
671 
672 template <typename T>
673 template <typename TParameter>
674 inline 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) :
675  cameraWidth_(width),
676  cameraHeight_(height),
677  focalLengthX_(T(focalX)),
678  focalLengthY_(T(focalY)),
679  invFocalLengthX_(0),
680  invFocalLengthY_(0),
681  principalPointX_(T(principalX)),
682  principalPointY_(T(principalY)),
683  hasDistortionParameters_(true)
684 {
685  static_assert((std::is_same<TParameter, float>::value) || (std::is_same<TParameter, double>::value), "Invalid TParameter, must be 'float' or 'double'!");
686 
687  ocean_assert(cameraWidth_ != 0u && cameraHeight_ != 0u);
691 
692  for (unsigned int n = 0u; n < 6u; ++n)
693  {
695  }
696 
699 }
700 
701 template <typename T>
702 template <typename TParameter>
703 inline FisheyeCameraT<T>::FisheyeCameraT(const unsigned int width, const unsigned int height, const ParameterConfiguration parameterConfiguration, const TParameter* parameters) :
704  cameraWidth_(width),
705  cameraHeight_(height),
706  focalLengthX_(0),
707  focalLengthY_(0),
708  invFocalLengthX_(0),
709  invFocalLengthY_(0),
710  principalPointX_(0),
711  principalPointY_(0),
712  hasDistortionParameters_(false)
713 {
714  static_assert((std::is_same<TParameter, float>::value) || (std::is_same<TParameter, double>::value), "Invalid TParameter, must be 'float' or 'double'!");
715 
716  ocean_assert(cameraWidth_ != 0u && cameraHeight_ != 0u);
717  ocean_assert(parameters != nullptr);
718 
719  switch (parameterConfiguration)
720  {
722  {
723  focalLengthX_ = T(parameters[0]);
724  focalLengthY_ = T(parameters[0]);
725 
726  principalPointX_ = T(parameters[1]);
727  principalPointY_ = T(parameters[2]);
728 
729  hasDistortionParameters_ = false;
730 
731  break;
732  }
733 
734  case PC_4_PARAMETERS:
735  {
736  focalLengthX_ = T(parameters[0]);
737  focalLengthY_ = T(parameters[1]);
738 
739  principalPointX_ = T(parameters[2]);
740  principalPointY_ = T(parameters[3]);
741 
742  hasDistortionParameters_ = false;
743 
744  break;
745  }
746 
748  {
749  focalLengthX_ = T(parameters[0]);
750  focalLengthY_ = T(parameters[0]);
751 
752  principalPointX_ = T(parameters[1]);
753  principalPointY_ = T(parameters[2]);
754 
755  radialDistortion_[0] = T(parameters[3]);
756  radialDistortion_[1] = T(parameters[4]);
757  radialDistortion_[2] = T(parameters[5]);
758  radialDistortion_[3] = T(parameters[6]);
759  radialDistortion_[4] = T(parameters[7]);
760  radialDistortion_[5] = T(parameters[8]);
761 
762  tangentialDistortion_[0] = T(parameters[9]);
763  tangentialDistortion_[1] = T(parameters[10]);
764 
766 
767  break;
768  }
769 
770  case PC_12_PARAMETERS:
771  {
772  focalLengthX_ = T(parameters[0]);
773  focalLengthY_ = T(parameters[1]);
774 
775  principalPointX_ = T(parameters[2]);
776  principalPointY_ = T(parameters[3]);
777 
778  radialDistortion_[0] = T(parameters[4]);
779  radialDistortion_[1] = T(parameters[5]);
780  radialDistortion_[2] = T(parameters[6]);
781  radialDistortion_[3] = T(parameters[7]);
782  radialDistortion_[4] = T(parameters[8]);
783  radialDistortion_[5] = T(parameters[9]);
784 
785  tangentialDistortion_[0] = T(parameters[10]);
786  tangentialDistortion_[1] = T(parameters[11]);
787 
789 
790  break;
791  }
792 
793  default:
794  ocean_assert(false && "Invalid parameter configuration!");
795  return;
796  }
797 
801 }
802 
803 template <typename T>
805 {
806  return hasDistortionParameters_;
807 }
808 
809 template <typename T>
810 inline unsigned int FisheyeCameraT<T>::width() const
811 {
812  return cameraWidth_;
813 }
814 
815 template <typename T>
816 inline unsigned int FisheyeCameraT<T>::height() const
817 {
818  return cameraHeight_;
819 }
820 
821 template <typename T>
823 {
824  return VectorT2<T>(principalPointX(), principalPointY());
825 }
826 
827 template <typename T>
829 {
830  return principalPointX_;
831 }
832 
833 template <typename T>
835 {
836  return principalPointY_;
837 }
838 
839 template <typename T>
841 {
842  return focalLengthX_;
843 }
844 
845 template <typename T>
847 {
848  return focalLengthY_;
849 }
850 
851 template <typename T>
853 {
854  return invFocalLengthX_;
855 }
856 
857 template <typename T>
859 {
860  return invFocalLengthY_;
861 }
862 
863 template <typename T>
864 inline const T* FisheyeCameraT<T>::radialDistortion() const
865 {
866  return radialDistortion_;
867 }
868 
869 template <typename T>
871 {
872  return tangentialDistortion_;
873 }
874 
875 template <typename T>
877 {
878  ocean_assert(isValid());
879 
880  /**
881  * x = Fx * X / Z + mx
882  *
883  * (x - mx) / Fx = X / Z
884  */
885 
886  if (NumericT<T>::isEqualEps(focalLengthX()))
887  {
888  return T(0);
889  }
890 
891  const T leftAngle = NumericT<T>::abs(NumericT<T>::atan(-principalPointX() * invFocalLengthX_));
892 
893  if (T(cameraWidth_) <= principalPointX())
894  {
895  ocean_assert(false && "Invalid principal point");
896  return T(2) * leftAngle;
897  }
898 
899  const T rightAngle = NumericT<T>::atan((T(cameraWidth_) - principalPointX()) * invFocalLengthX_);
900 
901  return leftAngle + rightAngle;
902 }
903 
904 template <typename T>
906 {
907  ocean_assert(isValid());
908 
909  /**
910  * y = Fy * Y / Z + my
911  *
912  * (y - my) / Fy = Y / Z
913  */
914 
915  if (NumericT<T>::isEqualEps(focalLengthY()))
916  {
917  return T(0);
918  }
919 
920  const T topAngle = NumericT<T>::abs(NumericT<T>::atan(-principalPointY() * invFocalLengthY_));
921 
922  if (T(cameraHeight_) <= principalPointY())
923  {
924  ocean_assert(false && "Invalid principal point");
925  return T(2) * topAngle;
926  }
927 
928  const T bottomAngle = NumericT<T>::atan((T(cameraHeight_) - principalPointY()) * invFocalLengthY_);
929 
930  return topAngle + bottomAngle;
931 }
932 
933 template <typename T>
935 {
936  const VectorT2<T> topLeft(-principalPointX(), -principalPointY());
937  const VectorT2<T> bottomRight(principalPointX(), principalPointY());
938 
939  const T diagonal = (topLeft - bottomRight).length();
940  const T halfDiagonal = diagonal * T(0.5);
941 
942  const T invFocalLength = (invFocalLengthX_ + invFocalLengthY_) * T(0.5);
943 
944  return T(2) * NumericT<T>::abs(NumericT<T>::atan(halfDiagonal * invFocalLength));
945 }
946 
947 template <typename T>
948 template <typename TParameter>
949 void FisheyeCameraT<T>::copyParameters(unsigned int& width, unsigned int& height, std::vector<TParameter>& parameters, ParameterConfiguration& parameterConfiguration) const
950 {
951  if (isValid())
952  {
953  width = cameraWidth_;
954  height = cameraHeight_;
955 
956  parameters =
957  {
958  TParameter(focalLengthX_),
959  TParameter(focalLengthY_),
960 
961  TParameter(principalPointX_),
962  TParameter(principalPointY_),
963 
964  TParameter(radialDistortion_[0]),
965  TParameter(radialDistortion_[1]),
966  TParameter(radialDistortion_[2]),
967  TParameter(radialDistortion_[3]),
968  TParameter(radialDistortion_[4]),
969  TParameter(radialDistortion_[5]),
970 
971  TParameter(tangentialDistortion_[0]),
972  TParameter(tangentialDistortion_[1]),
973  };
974 
975  ocean_assert(parameters.size() == 12);
976 
977  parameterConfiguration = PC_12_PARAMETERS;
978  }
979  else
980  {
981  width = 0u;
982  height = 0u;
983 
984  parameters.clear();
985 
986  parameterConfiguration = PC_UNKNOWN;
987  }
988 }
989 
990 template <typename T>
991 inline bool FisheyeCameraT<T>::isInside(const VectorT2<T>& imagePoint, const T signedBorder) const
992 {
993  ocean_assert(isValid());
994  ocean_assert(signedBorder < T(std::min(cameraWidth_ / 2u, cameraHeight_ / 2u)));
995 
996  return imagePoint.x() >= signedBorder && imagePoint.y() >= signedBorder
997  && imagePoint.x() < T(cameraWidth_) - signedBorder && imagePoint.y() < T(cameraHeight_) - signedBorder;
998 }
999 
1000 template <typename T>
1001 template <bool tUseDistortionParameters>
1003 {
1004  ocean_assert(isValid());
1005 
1006  /*
1007  * 3) Two radial distortion parameters k3, k5, k7, k9, k11, k13
1008  *
1009  * 4) Two tangential distortion parameters p1 and p2.
1010  *
1011  * An undistorted image point (x, y), is transformed to the corresponding distorted image point (x', y') as follows:
1012  * x' = x_r + x_t
1013  * y' = y_r + y_t
1014 
1015  * radial distortion:
1016  * x_r = x * (theta + k3 * theta^3 + k5 * theta^5 + k7 * theta^7 + k9 * theta^9 + k11 * theta^11 + k13 * theta^13) / r
1017  * y_r = y * (theta + k3 * theta^3 + k5 * theta^5 + k7 * theta^7 + k9 * theta^9 + k11 * theta^11 + k13 * theta^13) / r
1018  *
1019  * tangential distortion:
1020  * x_t = p1 * (2 * x_r^2 + radial^2) + p2 * 2 * x_r * y_r,
1021  * y_t = p2 * (2 * y_r^2 + radial^2) + p1 * 2 * x_r * y_r.
1022  *
1023  * with
1024  * r = sqrt(x^2 + y^2)
1025  * theta = atan(r)
1026  * radial^2 = x_r^2 + y_r^2
1027  *
1028  * With x, y undistorted normalized coordinates
1029  * With x', y' distorted normalized coordinates
1030  */
1031 
1032  const T r2 = undistortedNormalized.sqr();
1033  const T r = NumericT<T>::sqrt(r2);
1034 
1035  if (NumericT<T>::isEqualEps(r))
1036  {
1037  return VectorT2<T>(0, 0);
1038  }
1039 
1040  const T theta = NumericT<T>::atan(r);
1041 
1042  if (tUseDistortionParameters && hasDistortionParameters_)
1043  {
1044  const T theta2 = theta * theta;
1045  const T theta3 = theta2 * theta;
1046  const T theta5 = theta2 * theta3;
1047  const T theta7 = theta2 * theta5;
1048  const T theta9 = theta2 * theta7;
1049  const T theta11 = theta2 * theta9;
1050  const T theta13 = theta2 * theta11;
1051 
1052  const T& k3 = radialDistortion_[0];
1053  const T& k5 = radialDistortion_[1];
1054  const T& k7 = radialDistortion_[2];
1055  const T& k9 = radialDistortion_[3];
1056  const T& k11 = radialDistortion_[4];
1057  const T& k13 = radialDistortion_[5];
1058 
1059  const T radialDistortionFactor = (theta + k3 * theta3 + k5 * theta5 + k7 * theta7 + k9 * theta9 + k11 * theta11 + k13 * theta13) / r;
1060 
1061  const T x_r = undistortedNormalized.x() * radialDistortionFactor;
1062  const T y_r = undistortedNormalized.y() * radialDistortionFactor;
1063 
1064  const T radius_r2 = x_r * x_r + y_r * y_r;
1065 
1066  const T& p1 = tangentialDistortion_[0];
1067  const T& p2 = tangentialDistortion_[1];
1068 
1069  const T x_t = p1 * (T(2) * x_r * x_r + radius_r2) + p2 * T(2) * x_r * y_r;
1070  const T y_t = p2 * (T(2) * y_r * y_r + radius_r2) + p1 * T(2) * x_r * y_r;
1071 
1072  return VectorT2<T>(x_r + x_t, y_r + y_t);
1073  }
1074  else
1075  {
1076  const T scale = theta / r;
1077 
1078  return VectorT2<T>(undistortedNormalized.x() * scale, undistortedNormalized.y() * scale);
1079  }
1080 }
1081 
1082 template <typename T>
1083 template <bool tUseDistortionParameters>
1085 {
1086  ocean_assert(isValid());
1087 
1088  if constexpr (tUseDistortionParameters)
1089  {
1090  const VectorT2<T> distortedTangentialFree = tangentialFreeDistortion(distortedNormalized);
1091 
1092  const T& k3 = radialDistortion_[0];
1093  const T& k5 = radialDistortion_[1];
1094  const T& k7 = radialDistortion_[2];
1095  const T& k9 = radialDistortion_[3];
1096  const T& k11 = radialDistortion_[4];
1097  const T& k13 = radialDistortion_[5];
1098 
1099  const T r = distortedTangentialFree.length();
1100 
1101  if (NumericT<T>::isEqualEps(r))
1102  {
1103  return VectorT2<T>(0, 0);
1104  }
1105 
1106  T theta = NumericT<T>::pow(r, T(0.3333333333333));
1107 
1108  for (unsigned int n = 0u; n < 10u; ++n)
1109  {
1110  const T theta2 = theta * theta;
1111  const T theta4 = theta2 * theta2;
1112  const T theta6 = theta4 * theta2;
1113  const T theta8 = theta6 * theta2;
1114  const T theta10 = theta8 * theta2;
1115  const T theta12 = theta10 * theta2;
1116 
1117  const T error = theta * (T(1) + k3 * theta2 + k5 * theta4 + k7 * theta6 + k9 * theta8 + k11 * theta10 + k13 * theta12) - r;
1118 
1119  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;
1120 
1121  if (NumericT<T>::isEqualEps(df))
1122  {
1123  break;
1124  }
1125 
1126  const T delta = error / df;
1127 
1128  theta -= delta;
1129 
1130  if (NumericT<T>::isEqualEps(delta))
1131  {
1132  break;
1133  }
1134  }
1135 
1136  const T scale = NumericT<T>::tan(theta) / r;
1137 
1138  return distortedTangentialFree * scale;
1139  }
1140  else
1141  {
1142  const T r = distortedNormalized.length();
1143 
1144  if (NumericT<T>::isEqualEps(r))
1145  {
1146  return VectorT2<T>(0, 0);
1147  }
1148 
1149  const T scale = NumericT<T>::tan(r) / r;
1150 
1151  return distortedNormalized * scale;
1152  }
1153 }
1154 
1155 template <typename T>
1156 template <bool tUseDistortionParameters>
1157 inline VectorT2<T> FisheyeCameraT<T>::projectToImage(const VectorT3<T>& worldObjectPoint) const
1158 {
1159  ocean_assert(isValid());
1160 
1161  return projectToImageIF<tUseDistortionParameters>(VectorT3<T>(worldObjectPoint.x(), -worldObjectPoint.y(), -worldObjectPoint.z()));
1162 }
1163 
1164 template <typename T>
1165 template <bool tUseDistortionParameters>
1166 inline VectorT2<T> FisheyeCameraT<T>::projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const VectorT3<T>& worldObjectPoint) const
1167 {
1168  ocean_assert(isValid());
1169 
1170  ocean_assert(world_T_camera.isValid());
1171  return projectToImageIF<tUseDistortionParameters>(CameraT<T>::standard2InvertedFlipped(world_T_camera), worldObjectPoint);
1172 }
1173 
1174 template <typename T>
1175 template <bool tUseDistortionParameters>
1176 VectorT2<T> FisheyeCameraT<T>::projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const VectorT3<T>& worldObjectPoint) const
1177 {
1178  ocean_assert(isValid());
1179 
1180  ocean_assert(flippedCamera_T_world.isValid());
1181  return projectToImageIF<tUseDistortionParameters>(flippedCamera_T_world * worldObjectPoint);
1182 }
1183 
1184 template <typename T>
1185 template <bool tUseDistortionParameters>
1186 VectorT2<T> FisheyeCameraT<T>::projectToImageIF(const VectorT3<T>& cameraFlippedObjectPoint) const
1187 {
1188  ocean_assert(isValid());
1189  ocean_assert(NumericT<T>::isNotEqualEps(cameraFlippedObjectPoint.z()));
1190 
1191  const T invZ = T(1) / cameraFlippedObjectPoint.z();
1192 
1193  const VectorT2<T> undistortedNormalized(cameraFlippedObjectPoint.x() * invZ, cameraFlippedObjectPoint.y() * invZ);
1194  const VectorT2<T> distortedNormalizedImagePoint = distortNormalized<tUseDistortionParameters>(undistortedNormalized);
1195 
1196  return VectorT2<T>(distortedNormalizedImagePoint.x() * focalLengthX() + principalPointX(), distortedNormalizedImagePoint.y() * focalLengthY() + principalPointY());
1197 }
1198 
1199 template <typename T>
1200 template <bool tUseDistortionParameters>
1201 inline VectorT3<T> FisheyeCameraT<T>::vector(const VectorT2<T>& distortedImagePoint, const bool makeUnitVector) const
1202 {
1203  ocean_assert(isValid());
1204 
1205  const VectorT2<T> distortedNormalized((distortedImagePoint.x() - principalPointX_) * invFocalLengthX_, (distortedImagePoint.y() - principalPointY_) * invFocalLengthY_);
1206  const VectorT2<T> undistortedNormalized = undistortNormalized<tUseDistortionParameters>(distortedNormalized);
1207 
1208  if (makeUnitVector)
1209  {
1210  return VectorT3<T>(undistortedNormalized.x(), -undistortedNormalized.y(), T(-1)).normalized();
1211  }
1212  else
1213  {
1214  return VectorT3<T>(undistortedNormalized.x(), -undistortedNormalized.y(), T(-1));
1215  }
1216 }
1217 
1218 template <typename T>
1219 template <bool tUseDistortionParameters>
1220 inline VectorT3<T> FisheyeCameraT<T>::vectorIF(const VectorT2<T>& distortedImagePoint, const bool makeUnitVector) const
1221 {
1222  ocean_assert(isValid());
1223 
1224  const VectorT2<T> distortedNormalized((distortedImagePoint.x() - principalPointX_) * invFocalLengthX_, (distortedImagePoint.y() - principalPointY_) * invFocalLengthY_);
1225  const VectorT2<T> undistortedNormalized = undistortNormalized<tUseDistortionParameters>(distortedNormalized);
1226 
1227  if (makeUnitVector)
1228  {
1229  return VectorT3<T>(undistortedNormalized.x(), undistortedNormalized.y(), T(1)).normalized();
1230  }
1231  else
1232  {
1233  return VectorT3<T>(undistortedNormalized.x(), undistortedNormalized.y(), T(1));
1234  }
1235 }
1236 
1237 template <typename T>
1238 template <bool tUseDistortionParameters>
1239 inline LineT3<T> FisheyeCameraT<T>::ray(const VectorT2<T>& distortedImagePoint, const HomogenousMatrixT4<T>& world_T_camera) const
1240 {
1241  ocean_assert(isValid() && world_T_camera.isValid());
1242 
1243  return LineT3<T>(world_T_camera.translation(), world_T_camera.rotationMatrix(vector<tUseDistortionParameters>(distortedImagePoint)));
1244 }
1245 
1246 template <typename T>
1247 template <bool tUseDistortionParameters>
1248 inline LineT3<T> FisheyeCameraT<T>::ray(const VectorT2<T>& distortedImagePoint) const
1249 {
1250  ocean_assert(isValid());
1251 
1252  return LineT3<T>(Vector3(0, 0, 0), vector<tUseDistortionParameters>(distortedImagePoint));
1253 }
1254 
1255 template <typename T>
1256 template <bool tUseDistortionParameters>
1257 inline void FisheyeCameraT<T>::pointJacobian2x3IF(const VectorT3<T>& flippedCameraObjectPoint, T* jx, T* jy) const
1258 {
1259  ocean_assert(isValid());
1260  ocean_assert(jx != nullptr && jy != nullptr);
1261 
1262  const T fx = focalLengthX();
1263  const T fy = focalLengthY();
1264 
1265  const T u = flippedCameraObjectPoint.x();
1266  const T v = flippedCameraObjectPoint.y();
1267  const T w = flippedCameraObjectPoint.z();
1268 
1269  ocean_assert(NumericT<T>::isNotEqualEps(w));
1270  const T invW = T(1) / w;
1271 
1272  const T u_invW = u * invW;
1273  const T v_invW = v * invW;
1274 
1275  if constexpr (tUseDistortionParameters)
1276  {
1277  T jDistX[2];
1278  T jDistY[2];
1279 
1280  jacobianDistortNormalized2x2(u_invW, v_invW, radialDistortion_, tangentialDistortion_, jDistX, jDistY);
1281 
1282  const T fx_jDistXx_invW = fx * jDistX[0] * invW;
1283  const T fy_jDistYx_invW = fy * jDistY[0] * invW;
1284 
1285  const T fx_jDistXy_invW = fx * jDistX[1] * invW;
1286  const T fy_jDistYy_invW = fy * jDistY[1] * invW;
1287 
1288  const T u_fx_jDistXx__ = u_invW * fx_jDistXx_invW + v_invW * fx_jDistXy_invW;
1289  const T u_fy_jDistYx__ = u_invW * fy_jDistYx_invW + v_invW * fy_jDistYy_invW;
1290 
1291  jx[0] = fx_jDistXx_invW;
1292  jx[1] = fx_jDistXy_invW;
1293  jx[2] = -u_fx_jDistXx__;
1294 
1295  jy[0] = fy_jDistYx_invW;
1296  jy[1] = fy_jDistYy_invW;
1297  jy[2] = -u_fy_jDistYx__;
1298  }
1299  else
1300  {
1301  const T fx_jDistXx_invW = fx * invW;
1302  const T fy_jDistYx_invW = fy * invW;
1303 
1304  const T fx_jDistXy_invW = fx * invW;
1305  const T fy_jDistYy_invW = fy * invW;
1306 
1307  const T u_fx_jDistXx__ = u_invW * fx_jDistXx_invW + v_invW * fx_jDistXy_invW;
1308  const T u_fy_jDistYx__ = u_invW * fy_jDistYx_invW + v_invW * fy_jDistYy_invW;
1309 
1310  jx[0] = fx_jDistXx_invW;
1311  jx[1] = fx_jDistXy_invW;
1312  jx[2] = -u_fx_jDistXx__;
1313 
1314  jy[0] = fy_jDistYx_invW;
1315  jy[1] = fy_jDistYy_invW;
1316  jy[2] = -u_fy_jDistYx__;
1317  }
1318 }
1319 
1320 template <typename T>
1321 bool FisheyeCameraT<T>::isEqual(const FisheyeCameraT<T>& fisheyeCamera, const T eps) const
1322 {
1323  return cameraWidth_ == fisheyeCamera.cameraWidth_ && cameraHeight_ == fisheyeCamera.cameraHeight_ && hasDistortionParameters_ == fisheyeCamera.hasDistortionParameters_
1324  && NumericT<T>::isEqual(focalLengthX_, fisheyeCamera.focalLengthX_, eps) && NumericT<T>::isEqual(focalLengthY_, fisheyeCamera.focalLengthY_, eps)
1325  && NumericT<T>::isEqual(principalPointX_, fisheyeCamera.principalPointX_, eps) && NumericT<T>::isEqual(principalPointY_, fisheyeCamera.principalPointY_, eps)
1326  && NumericT<T>::isEqual(radialDistortion_[0], fisheyeCamera.radialDistortion_[0], eps) && NumericT<T>::isEqual(radialDistortion_[1], fisheyeCamera.radialDistortion_[1], eps)
1327  && NumericT<T>::isEqual(radialDistortion_[2], fisheyeCamera.radialDistortion_[2], eps) && NumericT<T>::isEqual(radialDistortion_[3], fisheyeCamera.radialDistortion_[3], eps)
1328  && NumericT<T>::isEqual(radialDistortion_[4], fisheyeCamera.radialDistortion_[4], eps) && NumericT<T>::isEqual(radialDistortion_[5], fisheyeCamera.radialDistortion_[5], eps)
1329  && NumericT<T>::isEqual(tangentialDistortion_[0], fisheyeCamera.tangentialDistortion_[0], eps) && NumericT<T>::isEqual(tangentialDistortion_[1], fisheyeCamera.tangentialDistortion_[1], eps);
1330 }
1331 
1332 template <typename T>
1333 inline bool FisheyeCameraT<T>::isValid() const
1334 {
1335  ocean_assert(NumericT<T>::isEqualEps(focalLengthX_) || NumericT<T>::isEqual(T(1) / focalLengthX_, invFocalLengthX_));
1336  ocean_assert(NumericT<T>::isEqualEps(focalLengthY_) || NumericT<T>::isEqual(T(1) / focalLengthY_, invFocalLengthY_));
1337 
1338  return cameraWidth_ != 0u && cameraHeight_ != 0u;
1339 }
1340 
1341 template <typename T>
1342 bool FisheyeCameraT<T>::operator==(const FisheyeCameraT<T>& fisheyeCamera) const
1343 {
1344  return cameraWidth_ == fisheyeCamera.cameraWidth_ && cameraHeight_ == fisheyeCamera.cameraHeight_
1345  && focalLengthX_ == fisheyeCamera.focalLengthX_ && focalLengthY_ == fisheyeCamera.focalLengthY_
1346  && invFocalLengthX_ == fisheyeCamera.invFocalLengthX_ && invFocalLengthY_ == fisheyeCamera.invFocalLengthY_
1347  && principalPointX_ == fisheyeCamera.principalPointX_ && principalPointY_ == fisheyeCamera.principalPointY_
1348  && hasDistortionParameters_ == fisheyeCamera.hasDistortionParameters_
1349  && memcmp(radialDistortion_, fisheyeCamera.radialDistortion_, sizeof(T) * 6) == 0
1350  && memcmp(tangentialDistortion_, fisheyeCamera.tangentialDistortion_, sizeof(T) * 2) == 0;
1351 }
1352 
1353 template <typename T>
1354 inline bool FisheyeCameraT<T>::operator!=(const FisheyeCameraT<T>& fisheyeCamera) const
1355 {
1356  return !(*this == fisheyeCamera);
1357 }
1358 
1359 template <typename T>
1360 inline FisheyeCameraT<T>::operator bool() const
1361 {
1362  return isValid();
1363 }
1364 
1365 template <typename T>
1367 {
1368  // x' = x_r + x_t
1369  // y' = y_r + y_t
1370 
1371  // x_t = p1 * (2 * x_r^2 + radial^2) + p2 * 2 * x_r * y_r
1372  // y_t = p2 * (2 * y_r^2 + radial^2) + p1 * 2 * x_r * y_r
1373 
1374  // newton-based solving for x_r, y_r:
1375  // x' = p1 * (2 * x_r^2 + radial^2) + p2 * 2 * x_r * y_r + x_r
1376  // y' = p2 * (2 * y_r^2 + radial^2) + p1 * 2 * x_r * y_r + y_r
1377 
1378  const T& p1 = tangentialDistortion_[0];
1379  const T& p2 = tangentialDistortion_[1];
1380 
1382  {
1383  return distortedNormalized;
1384  }
1385 
1386  VectorT2<T> distortedTangentialFree(distortedNormalized);
1387 
1388  for (unsigned int n = 0u; n < 2u; ++n)
1389  {
1390  const T& x_r = distortedTangentialFree.x();
1391  const T& y_r = distortedTangentialFree.y();
1392 
1393  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();
1394  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();
1395 
1396  const T dxx = p1 * T(6) * x_r + T(2) * p2 * y_r + T(1);
1397  const T dxy = p1 * T(2) * y_r + T(2) * p2 * x_r;
1398 
1399  const T& dyx = dxy; // dxy == p2 * T(2) * y_r + T(2) * p1 * y_r;
1400  const T dyy = p2 * T(6) * y_r + T(2) * p1 * x_r + T(1);
1401 
1402  VectorT2<T> delta(0, 0);
1403  SquareMatrixT2<T>(dxx, dyx, dxy, dyy).solve(VectorT2<T>(resultX, resultY), delta);
1404 
1405  distortedTangentialFree -= delta;
1406 
1407  if (delta.sqr() < Numeric::eps())
1408  {
1409  break;
1410  }
1411  }
1412 
1413  return distortedTangentialFree;
1414 }
1415 
1416 template <typename T>
1417 OCEAN_FORCE_INLINE void FisheyeCameraT<T>::jacobianDistortNormalized2x2(const T x, const T y, const T* radialDistortion, const T* tangentialDistortion, T* jx, T* jy)
1418 {
1419  ocean_assert(jx != nullptr && jy != nullptr);
1420  ocean_assert(radialDistortion != nullptr && tangentialDistortion != nullptr);
1421 
1422  const T& k3 = radialDistortion[0];
1423  const T& k5 = radialDistortion[1];
1424  const T& k7 = radialDistortion[2];
1425  const T& k9 = radialDistortion[3];
1426  const T& k11 = radialDistortion[4];
1427  const T& k13 = radialDistortion[5];
1428 
1429  const T& p1 = tangentialDistortion[0];
1430  const T& p2 = tangentialDistortion[1];
1431 
1432  const T x2 = x * x;
1433  const T y2 = y * y;
1434 
1435  const T xy2 = x2 + y2;
1436 
1437  const T r = NumericT<T>::sqrt(xy2);
1438  const T r3 = r * r * r;
1439 
1440  const T t = NumericT<T>::atan(r);
1441  const T t2 = t * t;
1442  const T t3 = t2 * t;
1443  const T t4 = t3 * t;
1444  const T t5 = t4 * t;
1445  const T t6 = t5 * t;
1446  const T t7 = t6 * t;
1447  const T t8 = t7 * t;
1448  const T t9 = t8 * t;
1449  const T t10 = t9 * t;
1450  const T t11 = t10 * t;
1451  const T t12 = t11 * t;
1452  const T t13 = t12 * t;
1453 
1454  const T term0 = k13 * t13 + k11 * t11 + k9 * t9 + k7 * t7 + k5 * t5 + k3 * t3 + t;
1455  const T term1 = 13 * k13 * t12 + 11 * k11 * t10 + 9 * k9 * t8 + 7 * k7 * t6 + 5 * k5 * t4 + 3 * k3 * t2 + 1;
1456 
1457  const T term2 = (xy2 + 1) * term0;
1458  const T term3 = r3 * (xy2 + 1);
1459  const T invTerm3 = T(1) / term3;
1460 
1461  const T xDistortion_dx = (xy2 * term2 - x2 * term2 + x2 * r * term1) * invTerm3;
1462  const T xDistortion_dy = (x * term1 * y) / (xy2 * (xy2 + 1)) - (x * y * term0) / r3;
1463 
1464  //const T yDistortion_dx = (y * term1 * x) / (xy2 * (xy2 + 1)) - (y * x * term0) / r3; == xDistortion_dy
1465  const T& yDistortion_dx = xDistortion_dy;
1466  const T yDistortion_dy = (xy2 * term2 - y2 * term2 + y2 * r * term1) * invTerm3;
1467 
1468  const T radialDistortionFactor = term0 / r;
1469 
1470  const T rx = x * radialDistortionFactor;
1471  const T ry = y * radialDistortionFactor;
1472 
1473  const T xTangential_dx = 6 * p1 * rx + 2 * p2 * ry + 1;
1474  const T xTangential_dy = 2 * p1 * ry + 2 * p2 * rx;
1475 
1476  // const T yTangential_dx = 2 * p2 * rx + 2 * p1 * ry; // == yTangential_dx
1477  const T& yTangential_dx = xTangential_dy;
1478  const T yTangential_dy = 6 * p2 * ry + 2 * p1 * rx + 1;
1479 
1480  // chain rule
1481  // | xTangential_dx xTangential_dy | | xDistortion_dx xDistortion_dy |
1482  // | yTangential_dx yTangential_dy | * | yDistortion_dx yDistortion_dy |
1483 
1484  jx[0] = xTangential_dx * xDistortion_dx + xTangential_dy * yDistortion_dx;
1485  jx[1] = xTangential_dx * xDistortion_dy + xTangential_dy * yDistortion_dy;
1486 
1487  jy[0] = yTangential_dx * xDistortion_dx + yTangential_dy * yDistortion_dx;
1488  jy[1] = yTangential_dx * xDistortion_dy + yTangential_dy * yDistortion_dy;
1489 }
1490 
1491 }
1492 
1493 #endif // META_OCEAN_MATH_FISHEYE_CAMERA_H
This class implements the base class for all cameras.
Definition: Camera.h:54
bool isValid() const
Returns whether this camera is valid.
Definition: FisheyeCamera.h:1333
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:605
const T * radialDistortion() const
Returns the six radial distortion parameters of the camera model.
Definition: FisheyeCamera.h:864
T invFocalLengthX_
The horizontal inverse focal length of the camera, with range (0, infinity)
Definition: FisheyeCamera.h:557
T principalPointX() const
Returns the x-value of the principal point of the camera image in the pixel domain.
Definition: FisheyeCamera.h:828
bool operator!=(const FisheyeCameraT< T > &fisheyeCamera) const
Returns whether two fisheye cameras are not identical.
Definition: FisheyeCamera.h:1354
FisheyeCameraT(const FisheyeCameraT< T > &fisheyeCamera)=default
Copy constructor.
unsigned int height() const
Returns the height of the camera image.
Definition: FisheyeCamera.h:816
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:1157
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:1239
VectorT2< T > principalPoint() const
Returns the coordinate of the principal point of the camera image in the pixel domain.
Definition: FisheyeCamera.h:822
T Type
Definition of the used data type.
Definition: FisheyeCamera.h:114
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:703
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:1166
T fovY() const
Returns the field of view in x direction of the camera.
Definition: FisheyeCamera.h:905
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:1176
const T * tangentialDistortion() const
Returns the two tangential distortion parameters of the camera model.
Definition: FisheyeCamera.h:870
VectorT3< T > vector(const VectorT2< T > &distortedImagePoint, const bool makeUnitVector=true) const
Returns a unit vector (with length 1) starting at the camera's center and intersecting a given 2D poi...
Definition: FisheyeCamera.h:1201
T focalLengthY_
The vertical focal length of the camera, with range (0, infinity)
Definition: FisheyeCamera.h:554
T principalPointX_
The horizontal principal point of the camera, in pixels, with range [0, width())
Definition: FisheyeCamera.h:563
T fovX() const
Returns the field of view in x direction of the camera.
Definition: FisheyeCamera.h:876
friend class FisheyeCameraT
Definition: FisheyeCamera.h:107
T focalLengthX_
The horizontal focal length of the camera, with range (0, infinity)
Definition: FisheyeCamera.h:551
T radialDistortion_[6]
The six radial distortion parameters.
Definition: FisheyeCamera.h:572
T inverseFocalLengthX() const
Returns the inverse horizontal focal length parameter.
Definition: FisheyeCamera.h:852
VectorT3< T > vectorIF(const VectorT2< T > &distortedImagePoint, const bool makeUnitVector=true) const
Returns a normalized vector (with length 1) starting at the camera's center and intersecting a given ...
Definition: FisheyeCamera.h:1220
bool hasDistortionParameters() const
Returns whether this camera object has specified distortion parameters.
Definition: FisheyeCamera.h:804
T tangentialDistortion_[2]
The two tangential distortion parameters.
Definition: FisheyeCamera.h:575
T principalPointY_
The vertical principal point of the camera, in pixels, with range [0, width())
Definition: FisheyeCamera.h:566
FisheyeCameraT< T > & operator=(const FisheyeCameraT< T > &fisheyeCamera)=default
Copy assignment operator.
T invFocalLengthY_
The vertical inverse focal length of the camera, with range (0, infinity)
Definition: FisheyeCamera.h:560
bool operator==(const FisheyeCameraT< T > &fisheyeCamera) const
Returns whether two fisheye cameras are identical.
Definition: FisheyeCamera.h:1342
unsigned int cameraWidth_
Width of the camera image, in pixel.
Definition: FisheyeCamera.h:545
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:645
T focalLengthX() const
Returns the horizontal focal length parameter.
Definition: FisheyeCamera.h:840
void copyParameters(unsigned int &width, unsigned int &height, std::vector< TParameter > &parameters, ParameterConfiguration &parameterConfiguration) const
Copies the parameters of this camera.
Definition: FisheyeCamera.h:949
unsigned int cameraHeight_
Height of the camera image, in pixel.
Definition: FisheyeCamera.h:548
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:674
VectorT2< T > distortNormalized(const VectorT2< T > &undistortedNormalized) const
Returns the normalized distorted position of a given undistorted normalized position.
Definition: FisheyeCamera.h:1002
VectorT2< T > undistortNormalized(const VectorT2< T > &distortedNormalized) const
Returns the normalized undistorted position of a given distorted normalized position.
Definition: FisheyeCamera.h:1084
FisheyeCameraT()=default
Default constructor creating an invalid camera object.
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:1248
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:1321
unsigned int width() const
Returns the width of the camera image.
Definition: FisheyeCamera.h:810
T fovDiagonal() const
Returns the diagonal field of view of the camera.
Definition: FisheyeCamera.h:934
T focalLengthY() const
Returns the vertical focal length parameter.
Definition: FisheyeCamera.h:846
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:1417
FisheyeCameraT(const FisheyeCameraT< U > &fisheyeCamera)
Copy constructor for a fisheye camera with difference element data type than T.
Definition: FisheyeCamera.h:580
bool hasDistortionParameters_
True, if the distortion parameters are defined.
Definition: FisheyeCamera.h:569
VectorT2< T > tangentialFreeDistortion(const VectorT2< T > &distortedNormalized) const
Calculates the tangential-free distortion of a normalized (distorted) image point.
Definition: FisheyeCamera.h:1366
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:991
T inverseFocalLengthY() const
Returns the inverse vertical focal length parameter.
Definition: FisheyeCamera.h:858
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
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:1257
T principalPointY() const
Returns the y-value of the principal point of the camera image in the pixel domain.
Definition: FisheyeCamera.h:834
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:1186
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:70
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:1616
static T pow(const T x, const T y)
Returns x raised to the power of y.
Definition: Numeric.h:1860
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:1533
static constexpr T eps()
Returns a small epsilon.
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition: Numeric.h:2386
static T tan(const T value)
Returns the tangent of a given value.
Definition: Numeric.h:1600
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition: Numeric.h:2087
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:766
This class implements a vector with two elements.
Definition: Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
T sqr() const
Returns the square of the vector length.
Definition: Vector2.h:621
T length() const
Returns the length of the vector.
Definition: Vector2.h:615
This class implements a vector with three elements.
Definition: Vector3.h:97
const T & y() const noexcept
Returns the y value.
Definition: Vector3.h:812
const T & x() const noexcept
Returns the x value.
Definition: Vector3.h:800
VectorT3< T > normalized() const
Returns the normalized vector.
Definition: Vector3.h:605
const T & z() const noexcept
Returns the z value.
Definition: Vector3.h:824
FisheyeCameraT< float > FisheyeCameraF
Definition of a FisheyeCamera object using 'float'' as data type.
Definition: FisheyeCamera.h:38
std::vector< FisheyeCamera > FisheyeCameras
Definition of a vector holding camera objects.
Definition: FisheyeCamera.h:59
FisheyeCameraT< Scalar > FisheyeCamera
Definition of a FisheyeCamera object using Scalar as data type.
Definition: FisheyeCamera.h:24
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition: Vector3.h:22
FisheyeCameraT< double > FisheyeCameraD
Definition of a FisheyeCamera object using 'double'' as data type.
Definition: FisheyeCamera.h:45
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