Ocean
Loading...
Searching...
No Matches
PinholeCamera.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_PINHOLE_CAMERA_H
9#define META_OCEAN_MATH_PINHOLE_CAMERA_H
10
11#include "ocean/math/Math.h"
12#include "ocean/math/Box2.h"
13#include "ocean/math/Box3.h"
14#include "ocean/math/Camera.h"
16#include "ocean/math/Line2.h"
17#include "ocean/math/Line3.h"
18#include "ocean/math/Lookup2.h"
20#include "ocean/math/Rotation.h"
25#include "ocean/math/Vector2.h"
26#include "ocean/math/Vector3.h"
27
28namespace Ocean
29{
30
31// Forward declaration.
32template <typename T> class PinholeCameraT;
33
34/**
35 * Definition of an pinhole camera object with Scalar precision.
36 * @see PinholeCameraT
37 * @ingroup math
38 */
40
41/**
42 * Definition of an pinhole camera object with double precision.
43 * @see PinholeCameraT
44 * @ingroup math
45 */
47
48/**
49 * Definition of an pinhole camera object with float precision.
50 * @see PinholeCameraT
51 * @ingroup math
52 */
54
55/**
56 * Definition of a typename alias for vectors with PinholeCameraT objects.
57 * @see PinholeCameraT
58 * @ingroup math
59 */
60template <typename T>
61using PinholeCamerasT = std::vector<PinholeCameraT<T>>;
62
63/**
64 * Definition of a vector holding pinhole camera objects.
65 * @see PinholeCamera
66 * @ingroup math
67 */
69
70/**
71 * Definition of a vector holding PinholeCameraD objects.
72 * @see PinholeCameraD
73 * @ingroup math
74 */
76
77/**
78 * Definition of a vector holding PinholeCameraF objects.
79 * @see PinholeCameraF
80 * @ingroup math
81 */
83
84/**
85 * Definition of a pinhole camera model.<br>
86 * The class holds the intrinsic and distortion parameters of a camera.<br>
87 * <pre>
88 * The camera holds:
89 * 1) Width and height of the camera image.
90 * 2) Intrinsic camera matrix:
91 * | Fx 0 mx |
92 * | 0 Fy my |
93 * | 0 0 1 |
94 * with mx and my as principal point,
95 * and with Fx = f / sx, Fy = f / sy, with focus f and pixel sizes sx and sy.
96 * 3) Two radial distortion parameters k1, and k2 for r^2 and r^4:
97 * 4) Two tangential distortion parameters p1 and p2.
98 * An distortion free (undistorted) image point is transformed to the corresponding distorted image position as follows:
99 * x' = x + x * (k1 * r^2 + k2 * r^4) + p1 * 2 * x * y + p2 * (r^2 + 2 * x^2),
100 * y' = y + y * (k1 * r^2 + k2 * r^4) + p2 * 2 * x * y + p1 * (r^2 + 2 * y^2).
101 * With: Undistorted and normalized image coordinates (x, y) and distorted and normalized image coordinates (x', y'),
102 * r^2 is defined by: r^2 = (x^2 + y^2), while r^4 = (x^2 + y^2)^2.
103 * The normalized image coordinate is obtained from a 3D object point by application of the perspective division.
104 * Normalized image coordinates may be transformed into the pixel coordinate system by applying the focal length and the principal point.
105 * </pre>
106 * This class provides several distort, undistort or projection functions of image points or object points.<br>
107 * Points lying outside the camera frame, may be distorted or undistorted due to the given position or due to the nearest position lying on the camera frame's border.<br>
108 * The larger the distance to the principal point of the camera, the more irregular the un-/distortion of the distortion model of this camera.<br>
109 * @tparam T The data type of a scalar, 'float' or 'double'
110 * @ingroup math
111 */
112template <typename T>
113class OCEAN_MATH_EXPORT PinholeCameraT : public CameraT<T>
114{
115 template <typename U> friend class PinholeCameraT;
116
117 public:
118
119 /// The scalar data type of this object.
120 using TScalar = T;
121
122 /// Definition of a pair of distortion values.
123 using DistortionPair = std::pair<T, T>;
124
125 /**
126 * Definition of individual parameter configurations.
127 */
129 {
130 /**
131 * An unknown parameter configuration.
132 */
133 PC_UNKNOWN = 0u,
134
135 /**
136 * 3 parameters with order:
137 * focal length (one identical value for horizontal and vertical direction),
138 * horizontal principal point,
139 * vertical principal point
140 */
142
143 /**
144 * 4 parameters with order:
145 * horizontal focal length,
146 * vertical focal length,
147 * horizontal principal point,
148 * vertical principal point
149 */
151
152 /**
153 * 7 parameters with order:
154 * focal length (one identical value for horizontal and vertical direction),
155 * horizontal principal point,
156 * vertical principal point,
157 * two radial distortion parameters k1, k2
158 * two tangential distortion parameters p1, p2
159 */
161
162 /**
163 * 8 parameters with order:
164 * horizontal focal length,
165 * vertical focal length,
166 * horizontal principal point,
167 * vertical principal point,
168 * two radial distortion parameters k1, k2
169 * two tangential distortion parameters p1, p2
170 */
171 PC_8_PARAMETERS
172 };
173
174 /**
175 * Definition of individual optimization strategies for camera parameters.
176 */
178 {
179 /// No optimization.
180 OS_NONE = 0,
181 /// Optimization of one focal length parameter (the same/identical parameter for horizontal and vertical focal length).
182 OS_FOCAL_LENGTH = 1,
183 /// Optimization of two focal length parameters: Horizontal focal length and vertical focal length.
184 OS_FOCAL_LENGTHS = 2,
185 /// Optimization of the four (basic) intrinsic camera parameters: Horizontal focal length, vertical focal length, horizontal principal point, vertical principal point.
186 OS_INTRINSIC_PARAMETERS = 4,
187 /// Optimization of six parameters: Horizontal focal length, vertical focal length, two radial distortion parameters, two tangential distortion parameters.
188 OS_FOCAL_LENGTHS_DISTORTION = 6,
189 /// Optimization of all camera parameters while the horizontal and vertical focal length parameter is identical.
190 OS_SYMMETRIC_INTRINSIC_PARAMETERS_DISTORTIONS = 7,
191 /// Optimization of all 8 intrinsic camera parameters including the distortion parameters: (2x focal length, 2x principal point, 2x radial distortion, 2x tangential distortion).
192 OS_INTRINSIC_PARAMETERS_DISTORTIONS = 8,
193 /// Optimization of four distortion parameters: Two radial distortion parameters, two tangential distortion parameters.
194 OS_DISTORTION = 0x1000 | 4,
195 /// Optimization of four (basic) intrinsic camera parameters: Horizontal focal length, vertical focal length, horizontal principal point, vertical principal point and two radial distortion parameters.
196 OS_INTRINSIC_PARAMETERS_RADIAL_DISTORTION = 0x1000 | 6
197 };
198
199 /**
200 * This class encapsulates a lookup table for camera distortion offsets allowing for faster un-distortion of image points (which is than an approximated position only).
201 */
202 class OCEAN_MATH_EXPORT DistortionLookup
203 {
204 protected:
205
206 /**
207 * Definition of a lookup table for 2D vectors.
208 */
210
211 public:
212
213 /**
214 * Creates an invalid lookup object.
215 */
216 inline DistortionLookup();
217
218 /**
219 * Creates an lookup object for a given camera.
220 * @param camera The camera profile for that the lookup table is determined
221 * @param binSize The size of the lookup bins for the camera distortion, horizontal and vertical in pixel, with range [1u, min(camera.width(), camera.height())]
222 */
223 explicit DistortionLookup(const PinholeCameraT<T>& camera, const unsigned int binSize);
224
225 /**
226 * Returns the undistorted image point for a given (distorted) image point (by application of a bilinear interpolation).
227 * @param distortedImagePoint The distorted image point for that the undistorted image point is returned
228 * @return The approximation of the undistorted image point
229 */
230 inline VectorT2<T> undistortedImagePoint(const VectorT2<T>& distortedImagePoint) const;
231
232 /**
233 * Returns the offset that needs to be added to an distorted image point so that it would be undistorted (by application of a bilinear interpolation).
234 * @param distortedImagePoint The distorted image point for that the offset is returned
235 * @return The approximation of the offset
236 */
237 inline VectorT2<T> undistortionOffset(const VectorT2<T>& distortedImagePoint) const;
238
239 /**
240 * Returns the undistorted image point for a given (distorted) image point (by application of a bicubic interpolation).
241 * @param distortedImagePoint The distorted image point for that the undistorted image point is returned
242 * @return The approximation of the undistorted image point
243 */
244 inline VectorT2<T> undistortedImagePointBicubic(const VectorT2<T>& distortedImagePoint) const;
245
246 /**
247 * Returns the offset that needs to be added to an distorted image point so that it would be undistorted (by application of a bicubic interpolation).
248 * @param distortedImagePoint The distorted image point for that the offset is returned
249 * @return The approximation of the offset
250 */
251 inline VectorT2<T> undistortionOffsetBicubic(const VectorT2<T>& distortedImagePoint) const;
252
253 protected:
254
255 /// The distortion lookup table.
257 };
258
259 public:
260
261 /**
262 * Standard constructor.
263 * Creates a new PinholeCameraT<T> object with all internal parameters as zero.
264 * The resulting camera object is invalid.<br>
265 */
266 PinholeCameraT() = default;
267
268 /**
269 * Creates a new camera object with specified frame dimension and intrinsic camera parameters best matching to a given reference camera profile with different frame dimension.
270 * Beware: The dimension aspect ratio between the new camera and the given reference camera profile should be almost similar.
271 * @param width The width of the camera dimension in pixel, with range [1, infinity)
272 * @param height The height of the camera dimension in pixel, with range [1, infinity)
273 * @param camera The camera profile that is used to adopt the intrinsic (and distortion) parameters
274 */
275 PinholeCameraT(const unsigned int width, const unsigned int height, const PinholeCameraT<T>& camera);
276
277 /**
278 * Creates a new sub-frame camera profile based on a camera profile of the entire camera frame.
279 * @param subFrameLeft The horizontal start position of the sub-frame within the original camera frame, in pixel, with range (-infinity, infinity)
280 * @param subFrameTop The vertical start position of the sub-frame within the original camera frame, in pixel, with range (-infinity, infinity)
281 * @param subFrameWidth The width of the sub-frame in pixel, with range [1, infinity)
282 * @param subFrameHeight The height of the sub-frame in pixel, with range [1, infinity)
283 * @param camera The original camera profile for which a sub-frame camera profile will be created
284 */
285 PinholeCameraT(const T subFrameLeft, const T subFrameTop, const unsigned int subFrameWidth, const unsigned int subFrameHeight, const PinholeCameraT<T>& camera);
286
287 /**
288 * Creates a new PinholeCameraT<T> object by it's given intrinsic parameters.
289 * @param width The width of the camera image, in pixel, with range [1, infinity)
290 * @param height The height of the camera image, in pixel, with range [1, infinity)
291 * @param focalX The focal parameter of the horizontal axis
292 * @param focalY The focal parameter of the vertical axis
293 * @param principalX The principal point of the horizontal axis (in pixel)
294 * @param principalY The principal point of the vertical axis (in pixel)
295 */
296 PinholeCameraT(const unsigned int width, const unsigned int height, const T focalX, const T focalY, const T principalX, const T principalY);
297
298 /**
299 * Creates a new PinholeCameraT<T> object by it's given intrinsic parameters.
300 * @param width The width of the camera image, in pixel, with range [1, infinity)
301 * @param height The height of the camera image, in pixel, with range [1, infinity)
302 * @param focalX The focal parameter of the horizontal axis
303 * @param focalY The focal parameter of the vertical axis
304 * @param principalX The principal point of the horizontal axis (in pixel)
305 * @param principalY The principal point of the vertical axis (in pixel)
306 * @param radial The pair of radial distortion parameter for r^2 and r^4
307 * @param tangential The tangential distortion parameters
308 */
309 PinholeCameraT(const unsigned int width, const unsigned int height, const T focalX, const T focalY, const T principalX, const T principalY, const DistortionPair& radial, const DistortionPair& tangential);
310
311 /**
312 * Creates a new PinholeCameraT<T> object by it's given intrinsic parameters.
313 * @param width The width of the camera image, in pixel, with range [1, infinity)
314 * @param height The height of the camera image, in pixel, with range [1, infinity)
315 * @param parameters The four to eight intrinsic and distortion parameters of the camera focalLegnthX(), focalLengthY(), principalPointX(), principalPointY(), radialDistortion().first, radialDistortion().second, tangentialDistortion().first, tangentialDistortion().second
316 * @param radialDistortion True, if parameter[4] and parameter[5] exist and store radial distortion parameters, must be 'True' if tangentialDistortion is 'True'
317 * @param tangentialDistortion True, if parameter[6] and parameter[7] exist and store tangential distortion parameters
318 */
319 PinholeCameraT(const unsigned int width, const unsigned int height, const T* parameters, const bool radialDistortion = true, const bool tangentialDistortion = true);
320
321 /**
322 * Creates a new PinholeCameraT<T> object by a given projection matrix with the intrinsic camera parameters.
323 * @param intrinsic The matrix with intrinsic camera parameter.
324 */
325 explicit PinholeCameraT(const SquareMatrixT3<T>& intrinsic);
326
327 /**
328 * Creates a new PinholeCameraT<T> object by the given intrinsic camera matrix and width and height of the camera.
329 * @param intrinsic The intrinsic camera matrix
330 * @param width The width of the camera image, in pixel, with range [1, infinity)
331 * @param height The height of the camera image, in pixel, with range [1, infinity)
332 */
333 PinholeCameraT(const SquareMatrixT3<T>& intrinsic, const unsigned int width, const unsigned int height);
334
335 /**
336 * Creates a new PinholeCameraT<T> object by the given intrinsic camera matrix, the width and height and the radial distortion parameters.
337 * @param intrinsic The intrinsic camera matrix
338 * @param width The width of the camera image, in pixel, with range [1, infinity)
339 * @param height The height of the camera image, in pixel, with range [1, infinity)
340 * @param radial The radial distortion parameters (r^2 and r^4)
341 * @param tangential The tangential distortion parameters
342 */
343 PinholeCameraT(const SquareMatrixT3<T>& intrinsic, const unsigned int width, const unsigned int height, const DistortionPair& radial, const DistortionPair& tangential);
344
345 /**
346 * Creates a new PinholeCameraT<T> object by the given width, height and field of view of a camera.
347 * This camera has no radial distortion.
348 * @param width The width of the camera image, in pixel, with range [1, infinity)
349 * @param height The height of the camera image, in pixel, with range [1, infinity)
350 * @param fovX The field of view in x-direction, in radian, with range (0, PI)
351 */
352 PinholeCameraT(const unsigned int width, const unsigned int height, const T fovX);
353
354 /**
355 * Creates a new PinholeCameraT<T> object by the given frame dimensions, the ideal field of view, and the camera's principal point.
356 * The provided field of view is expected to be the ideal field of view (if the camera would have a principal point in the perfect center of the image).<br>
357 * This camera has no radial distortion.
358 * @param width The width of the camera image, in pixel, with range [1, infinity)
359 * @param height The height of the camera image, in pixel, with range [1, infinity)
360 * @param fovX The camera's ideal field of view in x-direction, in radian, with range (0, PI)
361 * @param principalX The horizontal principal point within the camera frame, in pixel, with range (-infinity, infinity)
362 * @param principalY The vertical principal point within the camera frame, in pixel, with range (-infinity, infinity)
363 */
364 PinholeCameraT(const unsigned int width, const unsigned int height, const T fovX, const T principalX, const T principalY);
365
366 /**
367 * Copy constructor for a pinhole camera with difference element data type than T.
368 * @param pinholeCamera The pinhole camera profile to be copied
369 * @param copyDistortionParameters True, to copy the distortion parameters; False, create a new pinhole camera without distortion parameters
370 * @tparam U The element data type of the given pinhole camera
371 */
372 template <typename U>
373 explicit inline PinholeCameraT(const PinholeCameraT<U>& pinholeCamera, const bool copyDistortionParameters = true);
374
375 /**
376 * Creates a new camera object with parameters with specific configuration.
377 * @param width The width of the camera image (in pixel), with range [1, infinity)
378 * @param height The height of the camera image (in pixel), with range [1, infinity)
379 * @param parameterConfiguration The configuration of the given parameter, must be valid
380 * @param parameters The parameters matching with the specific configuration, must be valid
381 * @tparam TParameter The scalar data type in which the intrinsic camera parameters are provided, will be converted to 'T' internally, 'float' or 'double'
382 */
383 template <typename TParameter>
384 inline PinholeCameraT(const unsigned int width, const unsigned int height, const ParameterConfiguration parameterConfiguration, const TParameter* parameters);
385
386 /**
387 * Returns the intrinsic camera matrix.
388 * @return The intrinsic camera matrix
389 */
390 inline const SquareMatrixT3<T>& intrinsic() const;
391
392 /**
393 * Returns the inverted intrinsic camera matrix.
394 * @return The inverted intrinsic camera matrix
395 */
397
398 /**
399 * Returns the pair of radial distortion parameters.
400 * @return The radial distortion parameters for r^2 and r^4
401 */
402 inline const DistortionPair& radialDistortion() const;
403
404 /**
405 * Returns the pair of tangential distortion parameters.
406 * @return The tangential distortion parameters
407 */
409
410 /**
411 * Returns whether this camera object has specified distortion parameters.
412 * @return True, if so
413 */
414 inline bool hasDistortionParameters() const;
415
416 /**
417 * Returns the width of the camera image.
418 * @return The width of the camera image
419 */
420 inline unsigned int width() const;
421
422 /**
423 * Returns the height of the camera image.
424 * @return The height of the camera image
425 */
426 inline unsigned int height() const;
427
428 /**
429 * Returns the coordinate of the principal point of the camera image in the pixel domain.
430 * @return The 2D location of the principal point, with range [0, width)x[0, height)
431 */
433
434 /**
435 * Returns the x-value of the principal point of the camera image in the pixel domain.
436 * @return The x-value of the principal point, with range [0, width)
437 */
438 inline T principalPointX() const;
439
440 /**
441 * Returns the y-value of the principal point of the camera image in the pixel domain.
442 * @return The y-value of the principal point, with range [0, height)
443 */
444 inline T principalPointY() const;
445
446 /**
447 * Returns the horizontal focal length parameter.
448 * @return The horizontal focal length parameter
449 */
450 inline T focalLengthX() const;
451
452 /**
453 * Returns the vertical focal length parameter.
454 * @return The vertical focal length parameter
455 */
456 inline T focalLengthY() const;
457
458 /**
459 * Returns the inverse horizontal focal length parameter.
460 * @return The inverse horizontal focal length parameter
461 */
462 inline T inverseFocalLengthX() const;
463
464 /**
465 * Returns the inverse vertical focal length parameter.
466 * @return The inverse vertical focal length parameter
467 */
468 inline T inverseFocalLengthY() const;
469
470 /**
471 * Returns the field of view in x direction of the camera.
472 * The fov is the sum of the left and right part of the camera.
473 * @return The field of view (in radian), with range (0, PI)
474 */
475 T fovX() const;
476
477 /**
478 * Returns the field of view in x direction of the camera.
479 * The fov is the sum of the top and bottom part of the camera.
480 * @return The field of view (in radian), with range (0, PI)
481 */
482 T fovY() const;
483
484 /**
485 * Returns the left field of view in x direction.
486 * @return The left field of view (in radian), with range (-PI, PI), negative if principal point is outside image region
487 */
488 T fovXLeft() const;
489
490 /**
491 * Returns the right field of view in x direction.
492 * @return The right field of view (in radian), with range (-PI, PI), negative if principal point is outside image region
493 */
494 T fovXRight() const;
495
496 /**
497 * Returns the top field of view in y direction.
498 * @return The top field of view (in radian), with range (-PI, PI), negative if principal point is outside image region
499 */
500 T fovYTop() const;
501
502 /**
503 * Returns the bottom field of view in y direction.
504 * @return The bottom field of view (in radian), with range (-PI, PI), negative if principal point is outside image region
505 */
506 T fovYBottom() const;
507
508 /**
509 * Returns the diagonal field of view of the camera
510 * @return The diagonal field of view (in radian), with range (0, PI)
511 */
512 T fovDiagonal() const;
513
514 /**
515 * Copies the parameters of this camera.
516 * @param width The resulting width of the camera, in pixel, with range [0, infinity)
517 * @param height The resulting height of the camera, in pixel, with range [0, infinity)
518 * @param parameters The resulting parameters of the camera
519 * @param parameterConfiguration The resulting configuration of the resulting parameters
520 */
521 template <typename TParameter>
522 void copyParameters(unsigned int& width, unsigned int& height, std::vector<TParameter>& parameters, ParameterConfiguration& parameterConfiguration) const;
523
524 /**
525 * Gets two rotation parameters of the viewing ray for a given undistorted 2D position in the camera image.
526 * @param undistortedPosition The undistorted 2D position [in pixel]
527 * @param angleX The horizontal angle for the viewing ray [in radian]
528 * @param angleY The vertical angle for the viewing ray [in radian]
529 * @return True, if succeeded
530 */
531 bool rotation(const VectorT2<T>& undistortedPosition, T& angleX, T& angleY) const;
532
533 /**
534 * Copies the elements of this camera to an array with 4 to 8 floating point values.
535 * The resulting values are stored in the following order: focalLegnthX(), focalLengthY(), principalPointX(), principalPointY(), radialDistortion().first, radialDistortion().second, tangentialDistortion().first, tangentialDistortion().second.
536 * @param arrayValues The array with 4 to 8 floating point values receiving the camera data
537 * @param copyRadialDistortion True, if the array holds at least 6 elements so that the radial parameters will be copied too, must be 'True' if tangentialDistortion is 'True'
538 * @param copyTangentialDistortion True, if the array holds at least 8 elements so that the tangential parameters will be copied too
539 */
540 void copyElements(T* arrayValues, const bool copyRadialDistortion = true, const bool copyTangentialDistortion = true) const;
541
542 /**
543 * Sets the intrinsic camera matrix.
544 * @param intrinsic The intrinsic camera matrix
545 * @return True, if the camera matrix is valid
546 */
547 bool setIntrinsic(const SquareMatrixT3<T>& intrinsic);
548
549 /**
550 * Sets the radial distortion parameters.
551 * @param radial The pair of radial distortion parameters for r^2 and r^4
552 */
553 inline void setRadialDistortion(const DistortionPair& radial);
554
555 /**
556 * Sets the tangential distortion parameters.
557 * @param tangential The pair of tangential distortion parameters
558 */
559 inline void setTangentialDistortion(const DistortionPair& tangential);
560
561 /**
562 * Applies a given (relative) zoom factor which mainly multiplies the focal length parameters by the given factor.
563 * @param relativeZoom The (relative) zoom factor to apply, with range (0, infinity)
564 */
565 void applyZoomFactor(const T relativeZoom);
566
567 /**
568 * Checks whether the distortion of this camera is plausible.
569 * The check is based on two individual criteria.
570 * First, we check whether we can distort and un-distort the corner points of the camera frame to almost the same position in the camera frame.<br>
571 * Second we check whether the distortion is almost symmetric by checking that the distances between the distorted corner points of the camera frame and the (virtual) center of the camera frame are almost identical.
572 * @param symmetricFocalLengthRatio The symmetric tolerance ratio between the horizontal and vertical focal length values of the camera, with range (1, infinity)
573 * @param modelAccuracy The accuracy of the distortion model function, measuring the maximal offset between the distorted position of an undistorted position, in percent of the frame size, with range (0, 1)
574 * @param symmetricDistortionRatio The symmetric tolerance ratio between the camera frame's center and the distorted corner positions in percent, with range (1, infinity)
575 * @return True, if so
576 */
577 bool isDistortionPlausible(const T symmetricFocalLengthRatio = T(1.05), const T modelAccuracy = T(0.001), const T symmetricDistortionRatio = T(1.08)) const;
578
579 /**
580 * Returns the undistorted position of a given distorted position defined in pixel coordinates.<br>
581 * Beware: As the camera distortion model can not be inverted numerically, there is no guarantee that a given point can be undistorted for any given camera profile.
582 * @param distorted The distorted pixel position to be undistorted
583 * @param iterations The number of iterative calculations, with range [1, 100]
584 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
585 * @return The resulting undistorted pixel position
586 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
587 * @see distort().
588 */
589 template <bool tUseBorderDistortionIfOutside>
590 VectorT2<T> undistort(const VectorT2<T>& distorted, const unsigned int iterations = 10u, const T zoom = T(1)) const;
591
592 /**
593 * Returns the undistorted position of a given distorted position defined in pixel coordinates.<br>
594 * Beware: As the camera distortion model can not be inverted numerically, there is no guarantee that a given point can be undistorted for any given camera profile.
595 * This function applies a damping for the distortion outside the camera frame so that the quadratic and quartic radii do not have such a significant impact.
596 * @param distorted The distorted pixel position to be undistorted
597 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
598 * @param iterations The number of iterative calculations, with range [1, 100]
599 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
600 * @return The resulting undistorted pixel position
601 * @see distortDamped().
602 */
603 VectorT2<T> undistortDamped(const VectorT2<T>& distorted, const T dampingFactor = T(1), const unsigned int iterations = 10u, const T zoom = T(1)) const;
604
605 /**
606 * Returns the distorted position of a given undistorted position defined in pixel coordinates.<br>
607 * The distorted position is calculated by the usage of the internal distortion parameters of this camera object:
608 * <pre>
609 * dx = x + x * (k1 * r^2 + k2 * r^4) + p1 * 2 * x * y + p2 * (r^2 + 2 * x^2),
610 * dy = y + y * (k1 * r^2 + k2 * r^4) + p2 * 2 * x * y + p1 * (r^2 + 2 * y^2).
611 * </pre>
612 * With (dx, dy) the distorted normalized point coordinates, (x, y) the undistorted normalized point coordinates,<br>
613 * and dcx = Fx * dx + mx, dcy = Fy * dy + my the distorted pixel coordinates.
614 * @param undistorted The undistorted position to be distorted in pixel coordinates
615 * @return The resulting distorted position in pixel coordinates
616 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
617 * @see undistort().
618 */
619 template <bool tUseBorderDistortionIfOutside>
620 VectorT2<T> distort(const VectorT2<T>& undistorted) const;
621
622 /**
623 * Returns the distorted position of a given undistorted position defined in pixel coordinates.<br>
624 * This function applies a damping for the distortion outside the camera frame so that the quadratic and quartic radii do not have such a significant impact.<br>
625 * The damping has an asymptotic pattern and so that distortion is based on normalized coordinates never reaching a specified boundary.<br>
626 * The distorted position is calculated by the usage of the internal distortion parameters of this camera object:
627 * <pre>
628 * dx = x + x * (k1 * r^2 + k2 * r^4) + p1 * 2 * x * y + p2 * (r^2 + 2 * x^2),
629 * dy = y + y * (k1 * r^2 + k2 * r^4) + p2 * 2 * x * y + p1 * (r^2 + 2 * y^2).
630 * </pre>
631 * With (dx, dy) the distorted normalized point coordinates, (x, y) the undistorted normalized point coordinates,<br>
632 * and dcx = Fx * dx + mx, dcy = Fy * dy + my the distorted pixel coordinates.
633 * @param undistorted The undistorted position to be distorted in pixel coordinates
634 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
635 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
636 * @return The resulting distorted position in pixel coordinates
637 * @see undistortDamped().
638 */
639 VectorT2<T> distortDamped(const VectorT2<T>& undistorted, const T dampingFactor = T(1), const T zoom = T(1)) const;
640
641 /**
642 * Returns whether a given 2D image point lies inside the camera frame.
643 * Optional an explicit border can be defined to allow points slightly outside the camera image, or further inside the image.<br>
644 * 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.
645 * @param imagePoint The image point to be checked, must be valid
646 * @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)
647 * @return True, if the image point lies in the ranges [0, width())x[0, height())
648 */
649 inline bool isInside(const VectorT2<T>& imagePoint, const T signedBorder = T(0)) const;
650
651 /**
652 * Returns the viewing angle between two undistorted points on the camera's image plane.
653 * @param first The first undistorted point
654 * @param second The second undistorted point
655 * @return The viewing angle between the defined points (in radian)
656 * @see calculateCosBetween().
657 */
658 T calculateAngleBetween(const VectorT2<T>& first, const VectorT2<T>& second) const;
659
660 /**
661 * Returns the cosine of the viewing angle between two undistorted points on the camera's image plane.
662 * @param first The first undistorted point
663 * @param second The second undistorted point
664 * @return The cosine of viewing angle between the defined points
665 * @see calculateAngleBetween().
666 */
667 T calculateCosBetween(const VectorT2<T>& first, const VectorT2<T>& second) const;
668
669 /**
670 * Calculates the normalized image point corresponding to a given (distorted) image point.
671 * @param imagePoint The image point (that might be distorted)
672 * @param undistortImagePoint True, to force the un-distortion of the image point using the distortion parameters of this camera object
673 * @return The resulting normalized and (optional undistorted) image point
674 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
675 */
676 template <bool tUseBorderDistortionIfOutside>
677 VectorT2<T> imagePoint2normalizedImagePoint(const VectorT2<T>& imagePoint, const bool undistortImagePoint) const;
678
679 /**
680 * Calculates the normalized image point corresponding to a given (distorted) image point.
681 * This function applies a damping for the distortion outside the camera frame so that the quadratic and quartic radii do not have such a significant impact.
682 * @param imagePoint The image point (that might be distorted)
683 * @param undistortImagePoint True, to force the un-distortion of the image point using the distortion parameters of this camera object
684 * @return The resulting normalized and (optional undistorted) image point
685 */
686 inline VectorT2<T> imagePoint2normalizedImagePointDamped(const VectorT2<T>& imagePoint, const bool undistortImagePoint) const;
687
688 /**
689 * Calculates the image point corresponding to a given normalized image point.
690 * @param normalizedImagePoint The normalized image point (projected 3D object point without adjustment of focal length and principal point)
691 * @param distortImagePoint True, to force the distortion of the normalized image point using the distortion parameters of this camera object
692 * @return The resulting image point
693 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
694 */
695 template <bool tUseBorderDistortionIfOutside>
696 VectorT2<T> normalizedImagePoint2imagePoint(const VectorT2<T>& normalizedImagePoint, const bool distortImagePoint) const;
697
698 /**
699 * Calculates the image points corresponding to a set of given normalized image points.
700 * @param normalizedImagePoints The set of normalized image points (projected 3D object points without adjustment of focal length and principal point)
701 * @param numberNormalizedImagePoints The number of normalized image points
702 * @param distortImagePoints True, to force the distortion of the normalized image point using the distortion parameters of this camera object
703 * @param imagePoints The resulting image points, make sure that enough memory is provided
704 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
705 */
706 template <bool tUseBorderDistortionIfOutside>
707 void normalizedImagePoints2imagePoints(const VectorT2<T>* normalizedImagePoints, const size_t numberNormalizedImagePoints, const bool distortImagePoints, VectorT2<T>* imagePoints) const;
708
709 /**
710 * Projects a 3D object point to the 2D image plane of the camera by a given camera pose.
711 * This function may not apply the distortion parameters if the distortion-free projected image point lies outside the camera image.<br>
712 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates.<br>
713 * The viewing direction of the camera is along the negative z-axis.<br>
714 * The extrinsic matrix will be flipped and inverted internally.<br>
715 * Further this function can apply a specific zoom to the intrinsic camera matrix.
716 * @param world_T_camera The pose of the camera, must be valid
717 * @param worldObjectPoint The 3D object point to project, defined in world
718 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
719 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
720 * @return The imagePoint Resulting 2D image plane point defined inside the camera pixel coordinate system
721 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
722 * @see projectToImageIF().
723 */
724 template <bool tUseBorderDistortionIfOutside>
725 inline VectorT2<T> projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const VectorT3<T>& worldObjectPoint, const bool distortImagePoint, const T zoom = T(1)) const;
726
727 /**
728 * Projects a 3D box to the 2D image plane of the camera by a given camera pose.
729 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates.<br>
730 * The viewing direction of the camera is along the negative z-axis.<br>
731 * The extrinsic matrix will be flipped and inverted internally.<br>
732 * Further this function can apply a specific zoom to the intrinsic camera matrix.
733 * @param world_T_camera The pose of the camera, must be valid
734 * @param worldObjectBox The 3D box to project, defined in world, must be valid
735 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
736 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
737 * @return The 2D image box defined inside the camera pixel coordinate system
738 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
739 * @see projectToImageIF().
740 */
741 template <bool tUseBorderDistortionIfOutside>
742 inline BoxT2<T> projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const BoxT3<T>& worldObjectBox, const bool distortImagePoint, const T zoom = T(1)) const;
743
744 /**
745 * Projects a 3D triangle to the 2D image plane of the camera by a given camera pose.
746 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates.<br>
747 * The viewing direction of the camera is along the negative z-axis.<br>
748 * The extrinsic matrix will be flipped and inverted internally.<br>
749 * Further this function can apply a specific zoom to the intrinsic camera matrix.
750 * @param world_T_camera The pose of the camera, must be valid
751 * @param worldObjectTriangle The 3D triangle to project, defined in world, must be valid
752 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
753 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
754 * @return The 2D image triangle defined inside the camera pixel coordinate system
755 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
756 * @see projectToImageIF().
757 */
758 template <bool tUseBorderDistortionIfOutside>
759 inline TriangleT2<T> projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const TriangleT3<T>& worldObjectTriangle, const bool distortImagePoint, const T zoom = T(1)) const;
760
761 /**
762 * Projects a set of 3D object points onto an image plane of the camera by a given camera pose.
763 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates.<br>
764 * The viewing direction of the camera is along the negative z-axis.<br>
765 * The extrinsic matrix will be flipped and inverted internally.<br>
766 * Further this function can apply a specific zoom to the intrinsic camera matrix.
767 * @param world_T_camera The pose of the camera, must be valid
768 * @param worldObjectPoints The 3D object points to project, defined in world
769 * @param numberObjectPoints The number of object points to project, with range [0, infinity)
770 * @param distortImagePoints True, to force the distortion of the image point using the distortion parameters of this camera object
771 * @param imagePoints The resulting image points, make sure that enough memory is provided
772 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
773 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
774 * @see projectToImageIF().
775 */
776 template <bool tUseBorderDistortionIfOutside>
777 inline void projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const VectorT3<T>* worldObjectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2<T>* imagePoints, const T zoom = T(1)) const;
778
779 /**
780 * Projects a 3D line onto an image plane of the camera by a given camera pose.
781 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates.<br>
782 * The viewing direction of the camera is along the negative z-axis.<br>
783 * The extrinsic matrix will be flipped and inverted internally.<br>
784 * Further this function can apply a specific zoom to the intrinsic camera matrix.
785 * @param world_T_camera The pose of the camera, must be valid
786 * @param worldLine The 3D line to be projected, defined in world, with unit length direction
787 * @param distortProjectedLine True, to distort the projected 3D line (a very rough approximation only)
788 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
789 * @return The projectedLine Resulting projected 2D line, an invalid line is returned if the projection fails
790 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
791 */
792 template <bool tUseBorderDistortionIfOutside>
793 inline LineT2<T> projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const LineT3<T>& worldLine, const bool distortProjectedLine, const T zoom = T(1)) const;
794
795 /**
796 * Projects a 3D object point to the 2D image plane of the camera by a given inverse camera pose.
797 * This function may not apply the distortion parameters if the (default) projected image point lies outside the camera image.<br>
798 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
799 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
800 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
801 * Further this function can apply a specific zoom to the intrinsic camera matrix.
802 * @param flippedCamera_T_world The inverted and flipped extrinsic camera matrix, must be valid
803 * @param objectPoint The 3D object point to project
804 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
805 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
806 * @return The imagePoint Resulting 2D image plane point defined inside the camera pixel coordinate system
807 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
808 * @see projectToImage().
809 */
810 template <bool tUseBorderDistortionIfOutside>
811 VectorT2<T> projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const VectorT3<T>& objectPoint, const bool distortImagePoint, const T zoom = T(1)) const;
812
813 /**
814 * Projects a 3D object point to the 2D image plane of the camera by a given inverse camera pose.
815 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
816 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
817 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
818 * Further this function can apply a specific zoom to the intrinsic camera matrix.
819 * @param flippedCamera_T_world The inverted and flipped extrinsic camera matrix, must be valid
820 * @param worldObjectPoint The 3D object point to project, defined in world
821 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
822 * @return The 2D image plane point defined inside the camera pixel coordinate system
823 * @tparam tDistortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
824 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
825 * @see projectToImage().
826 */
827 template <bool tDistortImagePoint, bool tUseBorderDistortionIfOutside>
828 inline VectorT2<T> projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const VectorT3<T>& worldObjectPoint, const T zoom = T(1)) const;
829
830 /**
831 * Projects a 3D box to the 2D image plane of the camera by a given inverse camera pose.
832 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
833 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
834 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
835 * Further this function can apply a specific zoom to the intrinsic camera matrix.
836 * @param flippedCamera_T_world The inverted and flipped extrinsic camera matrix, must be valid
837 * @param worldObjectBox The 3D box to project, defined in world, must be valid
838 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
839 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
840 * @return The 2D box defined inside the camera pixel coordinate system
841 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
842 * @see projectToImage().
843 */
844 template <bool tUseBorderDistortionIfOutside>
845 BoxT2<T> projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const BoxT3<T>& worldObjectBox, const bool distortImagePoint, const T zoom = T(1)) const;
846
847 /**
848 * Projects a 3D triangle to the 2D image plane of the camera by a given extrinsic camera pose.
849 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
850 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
851 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
852 * Further this function can apply a specific zoom to the intrinsic camera matrix.
853 * @param flippedCamera_T_world The inverted and flipped extrinsic camera matrix, must be valid
854 * @param worldObjectTriangle The 3D triangle to project, defined in world, must be valid
855 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
856 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
857 * @return The 2D triangle defined inside the camera pixel coordinate system
858 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
859 * @see projectToImage().
860 */
861 template <bool tUseBorderDistortionIfOutside>
862 TriangleT2<T> projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const TriangleT3<T>& worldObjectTriangle, const bool distortImagePoint, const T zoom = T(1)) const;
863
864 /**
865 * Transforms a normalized object point (a 3D object point transformed by the inverted and flipped extrinsic camera matrix) into the camera pixel coordinate system.
866 * Further this function can apply a specific zoom to the intrinsic camera matrix.
867 * @param normalizedObjectPoint The 2D normalized object point of a 3D object point
868 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
869 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
870 * @return The 2D image plane point defined inside the camera pixel coordinate system
871 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
872 * @see projectToImage().
873 */
874 template <bool tUseBorderDistortionIfOutside>
875 VectorT2<T> projectToImageIF(const VectorT2<T>& normalizedObjectPoint, const bool distortImagePoint, const T zoom = T(1)) const;
876
877 /**
878 * Projects a set of 3D object points onto an image plane of the camera by a given inverse camera pose.
879 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
880 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
881 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
882 * Further this function can apply a specific zoom to the intrinsic camera matrix.
883 * @param flippedCamera_T_world The inverted and flipped extrinsic camera matrix, must be valid
884 * @param worldObjectPoints The 3D object points to project, defined in world
885 * @param numberObjectPoints The number of object points to project, with range [0, infinity)
886 * @param distortImagePoints True, to force the distortion of the image point using the distortion parameters of this camera object
887 * @param imagePoints The resulting image points, make sure that enough memory is provided
888 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
889 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
890 * @see projectToImage().
891 */
892 template <bool tUseBorderDistortionIfOutside>
893 void projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const VectorT3<T>* worldObjectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2<T>* imagePoints, const T zoom = T(1)) const;
894
895 /**
896 * Projects a 3D line onto an image plane of the camera by a given inverse camera pose.
897 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
898 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
899 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
900 * Further this function can apply a specific zoom to the intrinsic camera matrix.
901 * @param flippedCamera_T_world The inverted and flipped extrinsic camera matrix, must be valid
902 * @param worldLine The 3D line to be projected, with unit length direction, defined in world, must be valid
903 * @param distortProjectedLine True, to distort the projected 3D line (a very rough approximation only)
904 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
905 * @return The projectedLine Resulting projected 2D line, an invalid line is returned if the projection fails
906 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
907 */
908 template <bool tUseBorderDistortionIfOutside>
909 LineT2<T> projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const LineT3<T>& worldLine, const bool distortProjectedLine, const T zoom = T(1)) const;
910
911 /**
912 * Projects a 3D object point to the 2D image plane of the camera by a given extrinsic camera matrix.
913 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates.<br>
914 * The viewing direction of the camera is along the negative z-axis.<br>
915 * Object points projecting outside the camera frame will be distorted (if desired) by application of a damping factor.<br>
916 * Further this function can apply a specific zoom to the intrinsic camera matrix.
917 * @param extrinsic The extrinsic camera matrix
918 * @param objectPoint The 3D object point to project
919 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
920 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
921 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
922 * @return The imagePoint Resulting 2D image plane point defined inside the camera pixel coordinate system
923 * @see projectToImageDampedIF().
924 */
925 inline VectorT2<T> projectToImageDamped(const HomogenousMatrixT4<T>& extrinsic, const VectorT3<T>& objectPoint, const bool distortImagePoint, const T dampingFactor = T(1), const T zoom = T(1)) const;
926
927 /**
928 * Projects a 3D box to the 2D image plane of the camera by a given inverse extrinsic camera matrix.
929 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
930 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
931 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
932 * Object points projecting outside the camera frame will be distorted (if desired) by application of a damping factor.<br>
933 * Further this function can apply a specific zoom to the intrinsic camera matrix.
934 * @param extrinsic The extrinsic camera matrix
935 * @param objectBox The 3D box to project
936 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
937 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
938 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
939 * @return The 2D box defined inside the camera pixel coordinate system
940 * @see projectToImageDampedIF().
941 */
942 inline BoxT2<T> projectToImageDamped(const HomogenousMatrixT4<T>& extrinsic, const BoxT3<T>& objectBox, const bool distortImagePoint, const T dampingFactor = T(1), const T zoom = T(1)) const;
943
944 /**
945 * Projects a 3D triangle to the 2D image plane of the camera by a given extrinsic camera matrix.
946 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates.<br>
947 * The viewing direction of the camera is along the negative z-axis.<br>
948 * The extrinsic matrix will be flipped and inverted internally.<br>
949 * Object points projecting outside the camera frame will be distorted (if desired) by application of a damping factor.<br>
950 * Further this function can apply a specific zoom to the intrinsic camera matrix.
951 * @param extrinsic The extrinsic camera matrix
952 * @param objectTriangle The 3D triangle to project
953 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
954 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
955 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
956 * @return The 2D image triangle defined inside the camera pixel coordinate system
957 * @see projectToImageDampedIF().
958 */
959 inline TriangleT2<T> projectToImageDamped(const HomogenousMatrixT4<T>& extrinsic, const TriangleT3<T>& objectTriangle, const bool distortImagePoint, const T dampingFactor = T(1), const T zoom = T(1)) const;
960
961 /**
962 * Projects a set of 3D object points onto an image plane of the camera by a given extrinsic camera matrix.
963 * The extrinsic matrix transforms a 3D point given in camera coordinates into 3D world coordinates.<br>
964 * The viewing direction of the camera is along the negative z-axis.<br>
965 * The extrinsic matrix will be flipped and inverted internally.<br>
966 * Object points projecting outside the camera frame will be distorted (if desired) by application of a damping factor.<br>
967 * Further this function can apply a specific zoom to the intrinsic camera matrix.
968 * @param extrinsic The extrinsic camera matrix
969 * @param objectPoints The set of 3D object points to project
970 * @param numberObjectPoints The number of object points to project
971 * @param distortImagePoints True, to force the distortion of the image point using the distortion parameters of this camera object
972 * @param imagePoints The resulting image points, make sure that enough memory is provided
973 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
974 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
975 * @see projectToImageIF().
976 */
977 inline void projectToImageDamped(const HomogenousMatrixT4<T>& extrinsic, const VectorT3<T>* objectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2<T>* imagePoints, const T dampingFactor = T(1), const T zoom = T(1)) const;
978
979 /**
980 * Projects a 3D object point to the 2D image plane of the camera by a given inverse extrinsic camera matrix.
981 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
982 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
983 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
984 * Object points projecting outside the camera frame will be distorted (if desired) by application of a damping factor.<br>
985 * Further this function can apply a specific zoom to the intrinsic camera matrix.
986 * @param iFlippedExtrinsic The inverted and flipped extrinsic camera matrix
987 * @param objectPoint The 3D object point to project
988 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
989 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
990 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
991 * @return The resulting 2D image plane point defined inside the camera pixel coordinate system
992 * @see projectToImageDamped().
993 */
994 VectorT2<T> projectToImageDampedIF(const HomogenousMatrixT4<T>& iFlippedExtrinsic, const VectorT3<T>& objectPoint, const bool distortImagePoint, const T dampingFactor = T(1), const T zoom = T(1)) const;
995
996 /**
997 * Projects a 3D box to the 2D image plane of the camera by a given inverse extrinsic camera matrix.
998 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
999 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
1000 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
1001 * Object points projecting outside the camera frame will be distorted (if desired) by application of a damping factor.<br>
1002 * Further this function can apply a specific zoom to the intrinsic camera matrix.
1003 * @param iFlippedExtrinsic The inverted and flipped extrinsic camera matrix
1004 * @param objectBox The 3D box to project
1005 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
1006 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
1007 * @param zoom The optional zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1008 * @return The 2D box defined inside the camera pixel coordinate system
1009 * @see projectToImageDamped().
1010 */
1011 BoxT2<T> projectToImageDampedIF(const HomogenousMatrixT4<T>& iFlippedExtrinsic, const BoxT3<T>& objectBox, const bool distortImagePoint, const T dampingFactor = T(1), const T zoom = T(1)) const;
1012
1013 /**
1014 * Projects a 3D triangle to the 2D image plane of the camera by a given inverse extrinsic camera matrix.
1015 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
1016 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
1017 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
1018 * Object points projecting outside the camera frame will be distorted (if desired) by application of a damping factor.<br>
1019 * Further this function can apply a specific zoom to the intrinsic camera matrix.
1020 * @param iFlippedExtrinsic The inverted and flipped extrinsic camera matrix
1021 * @param objectTriangle The 3D triangle to project
1022 * @param distortImagePoint True, to force the distortion of the image point using the distortion parameters of this camera object
1023 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
1024 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1025 * @return The 2D triangle defined inside the camera pixel coordinate system
1026 * @see projectToImageDamped().
1027 */
1028 TriangleT2<T> projectToImageDampedIF(const HomogenousMatrixT4<T>& iFlippedExtrinsic, const TriangleT3<T>& objectTriangle, const bool distortImagePoint, const T dampingFactor = T(1), const T zoom = T(1)) const;
1029
1030 /**
1031 * Projects a set of 3D object points onto an image plane of the camera by a given inverse extrinsic camera matrix.
1032 * The inverse extrinsic matrix transforms a 3D point given in world coordinates into 3D camera coordinates.<br>
1033 * The coordinate system of the camera is flipped meaning that the viewing direction is along the positive z-axis.<br>
1034 * The flipped coordinate system can be received by a rotation around the x-axis by 180 degree.<br>
1035 * Object points projecting outside the camera frame will be distorted (if desired) by application of a damping factor.<br>
1036 * Further this function can apply a specific zoom to the intrinsic camera matrix.
1037 * @param invertedFlippedExtrinsic The inverted and flipped extrinsic camera matrix
1038 * @param objectPoints The set of 3D object points to project
1039 * @param numberObjectPoints The number of object points to project
1040 * @param distortImagePoints True, to force the distortion of the image point using the distortion parameters of this camera object
1041 * @param imagePoints The resulting image points, make sure that enough memory is provided
1042 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
1043 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1044 * @see projectToImageDamped().
1045 */
1046 void projectToImageDampedIF(const HomogenousMatrixT4<T>& invertedFlippedExtrinsic, const VectorT3<T>* objectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2<T>* imagePoints, const T dampingFactor = T(1), const T zoom = T(1)) const;
1047
1048 /**
1049 * Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane.
1050 * @param position The 2D position on the image plane, specified in the pixel domain
1051 * @param makeUnitVector True, to return a vector with length 1; False, to return a vector with any length
1052 * @return The normalized vector with -Z direction
1053 * @see vectorIF(), ray().
1054 */
1055 inline VectorT3<T> vector(const VectorT2<T>& position, const bool makeUnitVector = true) const;
1056
1057 /**
1058 * Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane.
1059 * Further this function can apply a specific zoom to the intrinsic camera matrix.
1060 * @param position The 2D position on the image plane, specified in the pixel domain
1061 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1062 * @param makeUnitVector True, to return a vector with length 1; False, to return a vector with any length
1063 * @return The normalized vector with -Z direction
1064 * @see vectorIF(), ray().
1065 */
1066 inline VectorT3<T> vector(const VectorT2<T>& position, const T zoom, const bool makeUnitVector = true) const;
1067
1068 /**
1069 * Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane.
1070 * The length of the vector is determined so that the vector (exactly) reaches a plane parallel to the image plane.<br>
1071 * The plane's normal is parallel to the z-axis while a positive distance locates the plane in the space of the negative z-axis.
1072 * @param position The 2D position on the image plane, specified in the pixel domain
1073 * @param distance The distance between the camera's center and the plane parallel to the image plane, with range (0, infinity)
1074 * @return The normalized vector with -Z direction
1075 */
1076 inline VectorT3<T> vectorToPlane(const VectorT2<T>& position, const T distance) const;
1077
1078 /**
1079 * Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane.
1080 * Further this function can apply a specific zoom to the intrinsic camera matrix.<br>
1081 * The length of the vector is determined so that the vector (exactly) reaches a plane parallel to the image plane.<br>
1082 * The plane's normal is parallel to the z-axis while a positive distance locates the plane in the space of the negative z-axis.
1083 * @param position The 2D position on the image plane, specified in the pixel domain
1084 * @param distance The distance between the camera's center and the plane parallel to the image plane, with range (0, infinity)
1085 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1086 * @return The normalized vector with -Z direction
1087 */
1088 inline VectorT3<T> vectorToPlane(const VectorT2<T>& position, const T distance, const T zoom) const;
1089
1090 /**
1091 * Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane.
1092 * @param position The 2D position on the image plane, specified in the pixel domain
1093 * @param makeUnitVector True, to return a vector with length 1; False, to return a vector with any length
1094 * @return The normalized vector with +Z direction
1095 */
1096 inline VectorT3<T> vectorIF(const VectorT2<T>& position, const bool makeUnitVector = true) const;
1097
1098 /**
1099 * Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane.
1100 * Further this function can apply a specific zoom to the intrinsic camera matrix.
1101 * @param position The 2D position on the image plane, specified in the pixel domain
1102 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1103 * @param makeUnitVector True, to return a vector with length 1; False, to return a vector with any length
1104 * @return The normalized vector with +Z direction
1105 */
1106 inline VectorT3<T> vectorIF(const VectorT2<T>& position, const T zoom, const bool makeUnitVector) const;
1107
1108 /**
1109 * Returns a ray starting at the camera's center and intersection a given 2D point on the image plane.
1110 * Further this function can apply a specific zoom to the intrinsic camera matrix.
1111 * @param position The 2D position on the image plane, specified in the pixel domain
1112 * @param world_T_camera The pose of the camera, the extrinsic camera matrix, must be valid
1113 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1114 * @return The specified ray for a camera pointing towards the negative z-space
1115 * @see vector().
1116 */
1117 inline LineT3<T> ray(const VectorT2<T>& position, const HomogenousMatrixT4<T>& world_T_camera, const T zoom = T(1)) const;
1118
1119 /**
1120 * Returns a ray starting at the camera's center and intersection a given 2D point on the image plane.
1121 * Further this function can apply a specific zoom to the intrinsic camera matrix.
1122 * @param position The 2D position on the image plane, specified in the pixel domain
1123 * @param world_t_camera The translation (position) of the camera pose
1124 * @param world_Q_camera The standard rotation quaternion of the camera pose, must be valid
1125 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1126 * @return The specified ray for a camera pointing towards the negative z-space
1127 * @see vector().
1128 */
1129 inline LineT3<T> ray(const VectorT2<T>& position, const VectorT3<T>& world_t_camera, const QuaternionT<T>& world_Q_camera, const T zoom = T(1)) const;
1130
1131 /**
1132 * Returns the 4x4 frustum projection matrix corresponding to this camera.
1133 * The frustum matrix is defined to point into negative z axis and does not provide any distortion parameters.<br>
1134 * @param nearDistance The positive distance to the near clipping plane
1135 * @param farDistance The positive distance to the far clipping plane
1136 * @return The resulting frustum projection matrix
1137 */
1138 SquareMatrixT4<T> frustumMatrix(const T nearDistance, const T farDistance) const;
1139
1140 /**
1141 * Returns a 4x4 homogeneous transformation matrix (corresponding to a 3x4 matrix) that covers an extrinsic (inverted and flipped) camera matrix and the intrinsic projection matrix of this camera object.
1142 * Further this function can apply a specific zoom to the intrinsic camera matrix.
1143 * @param iFlippedExtrinsic The inverted and flipped extrinsic camera matrix
1144 * @param zoom The zoom factor of the camera, with range (0, infinity), with 1 the default zoom factor
1145 * @return The resulting transformation matrix
1146 */
1147 inline HomogenousMatrixT4<T> transformationMatrixIF(const HomogenousMatrixT4<T>& iFlippedExtrinsic, const T zoom = T(1)) const;
1148
1149 /**
1150 * Returns whether two camera profiles are identical up to a given epsilon.
1151 * The image resolution must always be identical.
1152 * @param camera The second camera profile to be used for comparison, can be invalid
1153 * @param eps The epsilon threshold to be used, with range [0, infinity)
1154 * @return True, if so
1155 */
1156 bool isEqual(const PinholeCameraT<T>& camera, const T eps = NumericT<T>::eps()) const;
1157
1158 /**
1159 * Calculates the 2x3 jacobian matrix for the 3D object point projection into the camera frame.
1160 * The resulting jacobian matrix has the following layout:
1161 * <pre>
1162 * | dfu / dx, dfu / dy, dfu / dz |
1163 * | dfv / dx, dfv / dy, dfv / dz |
1164 * with projection function
1165 * q = f(p)
1166 * q_u = fu(p), q_y = fv(p)
1167 * with 2D image point q = (q_u, q_v) and 3D object point p = (x, y, z)
1168 * </pre>
1169 * @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).
1170 * @param jx The resulting first row of the Jacobian matrix, must contain three elements, must be valid
1171 * @param jy The resulting second row of the Jacobian matrix, must contain three elements, must be valid
1172 * @tparam U The data type of the scalar element either 'float' or 'double'
1173 * @tparam tUseDistortionParameters True, to use the camera profile's distortion parameters when calculating the Jacobian; False, to skip the distortion parameters
1174 */
1175 template <typename U, bool tUseDistortionParameters>
1176 inline void pointJacobian2x3IF(const VectorT3<U>& flippedCameraObjectPoint, U* jx, U* jy) const;
1177
1178 /**
1179 * Returns whether this camera is valid.
1180 * @return True, if so
1181 */
1182 inline bool isValid() const;
1183
1184 /**
1185 * Returns whether two camera objects are identical up to a small epsilon.
1186 * @param camera The second camera object
1187 * @return True, if so
1188 */
1189 bool operator==(const PinholeCameraT<T>& camera) const;
1190
1191 /**
1192 * Returns whether two camera objects are not identical up to a small epsilon.
1193 * @param camera The second camera object
1194 * @return True, if so
1195 */
1196 inline bool operator!=(const PinholeCameraT<T>& camera) const;
1197
1198 /**
1199 * Returns whether the camera holds valid parameters.
1200 * @return True, if so
1201 */
1202 explicit inline operator bool() const;
1203
1204 private:
1205
1206 /**
1207 * Determines the inverse of the intrinsic camera matrix.
1208 * This function must be invoked immediately after the intrinsic matrix has changed.
1209 */
1211
1212 /**
1213 * Returns the distorted position of a given undistorted normalized position.<br>
1214 * The distorted position is calculated by the usage of the internal distortion parameters of this camera object:
1215 * <pre>
1216 * x' = x + x * (k1 * r^2 + k2 * r^4) + p1 * 2 * x * y + p2 * (r^2 + 2 * x^2),
1217 * y' = y + y * (k1 * r^2 + k2 * r^4) + p2 * 2 * x * y + p1 * (r^2 + 2 * y^2).
1218 * </pre>
1219 * @param undistortedNormalized The undistorted normalized position to be distorted
1220 * @param invZoom The optional the inverse zoom factor (1/zoom) of the camera, with range (0, infinity), with 1 the default zoom factor
1221 * @return The resulting distorted normalized position
1222 * @tparam tUseBorderDistortionIfOutside True, to apply the distortion from the nearest point lying on the frame border if the point lies outside the visible camera area; False to apply the distortion from the given position
1223 * @see distort().
1224 */
1225 template <bool tUseBorderDistortionIfOutside>
1226 VectorT2<T> distortNormalized(const VectorT2<T>& undistortedNormalized, const T invZoom) const;
1227
1228 /**
1229 * Returns the distorted position of a given undistorted normalized position.<br>
1230 * This function applies a damping for the distortion outside the camera frame so that the quadratic and quartic radii do not have such a significant impact.<br>
1231 * The damping has an asymptotic pattern and so that distortion is based on normalized coordinates never reaching a specified boundary.<br>
1232 * The distorted position is calculated by the usage of the internal distortion parameters of this camera object:
1233 * <pre>
1234 * dx = x + x * (k1 * r^2 + k2 * r^4) + p1 * 2 * x * y + p2 * (r^2 + 2 * x^2),
1235 * dy = y + y * (k1 * r^2 + k2 * r^4) + p2 * 2 * x * y + p1 * (r^2 + 2 * y^2).
1236 * </pre>
1237 * With (dx, dy) the distorted normalized point coordinates and (x, y) the undistorted normalized point coordinates.
1238 * @param undistortedNormalized The undistorted normalized position to be distorted
1239 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
1240 * @param invZoom The optional the inverse zoom factor (1/zoom) of the camera, with range (0, infinity), with 1 the default zoom factor
1241 * @return The resulting distorted normalized position
1242 * @see distortDamped().
1243 */
1244 VectorT2<T> distortNormalizedDamped(const VectorT2<T>& undistortedNormalized, const T dampingFactor, const T invZoom) const;
1245
1246 /**
1247 * Determines the damped normalized coordinate for a given normalized coordinate.
1248 * The damping is applied to coordinates outside the camera frame.<br>
1249 * The damping has an asymptotic pattern so that a damped coordinate never reaches a boundary (specified by the dampingFactor).
1250 * @param normalized The normalized coordinate for which the damped coordinate will be calculated
1251 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
1252 * @param invZoom The optional the inverse zoom factor (1/zoom) of the camera, with range (0, infinity), with 1 the default zoom factor
1253 * @return The damped normalized coordinate
1254 */
1255 VectorT2<T> dampedNormalized(const VectorT2<T>& normalized, const T dampingFactor, const T invZoom) const;
1256
1257 /**
1258 * Determines the damped normalized coordinate for a given normalized coordinate.
1259 * The damping is applied to coordinates outside the camera frame.<br>
1260 * The damping has an asymptotic pattern so that a damped coordinate never reaches a boundary (specified by the dampingFactor).
1261 * @param normalized The normalized coordinate for which the damped coordinate will be calculated
1262 * @param dampingFactor The factor defining the boundary of the asymptotic damping behavior for normalized coordinates, with range [0, infinity)
1263 * @param leftNormalizedBorder The left border of camera frame in normalized coordinates, respecting a possible zoom factor already
1264 * @param rightNormalizedBorder The right border of the camera frame in normalized coordinates, respecting a possible zoom factor already
1265 * @param topNormalizedBorder The top border of the camera frame in normalized coordinates, respecting a possible zoom factor already
1266 * @param bottomNormalizedBorder The bottom border of the camera frame in normalized coordinates, respecting a possible zoom factor already
1267 * @return The damped normalized coordinate
1268 */
1269 VectorT2<T> dampedNormalized(const VectorT2<T>& normalized, const T dampingFactor, const T leftNormalizedBorder, const T rightNormalizedBorder, const T topNormalizedBorder, const T bottomNormalizedBorder) const;
1270
1271 protected:
1272
1273 /// Width of the camera image, in pixels.
1274 unsigned int width_ = 0u;
1275
1276 /// Height of the camera image, in pixels.
1277 unsigned int height_ = 0u;
1278
1279 /// Intrinsic camera matrix.
1281
1282 /// Inverted intrinsic camera matrix.
1283 SquareMatrixT3<T> invertedIntrinsics_ = SquareMatrixT3<T>(false);
1284
1285 /// Pair of radial distortion parameters for r^2 and r^4.
1286 DistortionPair radialDistortion_ = DistortionPair(T(0), T(0));
1287
1288 /// Pair of tangential distortion parameters.
1289 DistortionPair tangentialDistortion_ = DistortionPair(T(0), T(0));
1290};
1291
1292template <typename T>
1294{
1295 // nothing to do here
1296}
1297
1298template <typename T>
1300{
1301 ocean_assert(distortionLookupTable);
1302 return distortionLookupTable.bilinearValue(distortedImagePoint.x(), distortedImagePoint.y()) + distortedImagePoint;
1303}
1304
1305template <typename T>
1307{
1308 ocean_assert(distortionLookupTable);
1309 return distortionLookupTable.bilinearValue(distortedImagePoint.x(), distortedImagePoint.y());
1310}
1311
1312template <typename T>
1314{
1315 ocean_assert(distortionLookupTable);
1316 return distortionLookupTable.bicubicValue(distortedImagePoint.x(), distortedImagePoint.y()) + distortedImagePoint;
1317}
1318
1319template <typename T>
1321{
1322 ocean_assert(distortionLookupTable);
1323 return distortionLookupTable.bicubicValue(distortedImagePoint.x(), distortedImagePoint.y());
1324}
1325
1326template <typename T>
1328{
1329 return intrinsics_;
1330}
1331
1332template <typename T>
1337
1338template <typename T>
1343
1344template <typename T>
1349
1350template <typename T>
1351template <typename U>
1354{
1356 {
1357 radialDistortion_ = DistortionPair(T(pinholeCamera.radialDistortion_.first), T(pinholeCamera.radialDistortion_.second));
1358 tangentialDistortion_ = DistortionPair(T(pinholeCamera.tangentialDistortion_.first), T(pinholeCamera.tangentialDistortion_.second));
1359 }
1360}
1361
1362template <typename T>
1363template <typename TParameter>
1364inline PinholeCameraT<T>::PinholeCameraT(const unsigned int width, const unsigned int height, const ParameterConfiguration parameterConfiguration, const TParameter* parameters)
1365{
1366 static_assert((std::is_same<TParameter, float>::value) || (std::is_same<TParameter, double>::value), "Invalid TParameter, must be 'float' or 'double'!");
1367
1368 ocean_assert(width != 0u && height != 0u);
1369 ocean_assert(parameters != nullptr);
1370
1371 switch (parameterConfiguration)
1372 {
1373 case PC_3_PARAMETERS_ONE_FOCAL_LENGTH:
1374 {
1375 const T focalLength = T(parameters[0]);
1376
1377 const T principalPointX = T(parameters[1]);
1378 const T principalPointY = T(parameters[2]);
1379
1380 constexpr T radialDistortion = T(0);
1381 constexpr T tangentialDistortion = T(0);
1382
1383 *this = PinholeCameraT<T>(width, height, focalLength, focalLength, principalPointX, principalPointY, DistortionPair(radialDistortion, radialDistortion), DistortionPair(tangentialDistortion, tangentialDistortion));
1384 return;
1385 }
1386
1387 case PC_4_PARAMETERS:
1388 {
1389 const T focalLengthX = T(parameters[0]);
1390 const T focalLengthY = T(parameters[1]);
1391
1392 const T principalPointX = T(parameters[2]);
1393 const T principalPointY = T(parameters[3]);
1394
1395 constexpr T radialDistortion = T(0);
1396 constexpr T tangentialDistortion = T(0);
1397
1398 *this = PinholeCameraT<T>(width, height, focalLengthX, focalLengthY, principalPointX, principalPointY, DistortionPair(radialDistortion, radialDistortion), DistortionPair(tangentialDistortion, tangentialDistortion));
1399 return;
1400 }
1401
1402 case PC_7_PARAMETERS_ONE_FOCAL_LENGTH:
1403 {
1404 const T focalLength = T(parameters[0]);
1405
1406 const T principalPointX = T(parameters[1]);
1407 const T principalPointY = T(parameters[2]);
1408
1409 const T radialDistortion0 = T(parameters[3]);
1410 const T radialDistortion1 = T(parameters[4]);
1411
1412 const T tangentialDistortion0 = T(parameters[5]);
1413 const T tangentialDistortion1 = T(parameters[6]);
1414
1415 *this = PinholeCameraT<T>(width, height, focalLength, focalLength, principalPointX, principalPointY, DistortionPair(radialDistortion0, radialDistortion1), DistortionPair(tangentialDistortion0, tangentialDistortion1));
1416 return;
1417 }
1418
1419 case PC_8_PARAMETERS:
1420 {
1421 const T focalLengthX = T(parameters[0]);
1422 const T focalLengthY = T(parameters[1]);
1423
1424 const T principalPointX = T(parameters[2]);
1425 const T principalPointY = T(parameters[3]);
1426
1427 const T radialDistortion0 = T(parameters[4]);
1428 const T radialDistortion1 = T(parameters[5]);
1429
1430 const T tangentialDistortion0 = T(parameters[6]);
1431 const T tangentialDistortion1 = T(parameters[7]);
1432
1433 *this = PinholeCameraT<T>(width, height, focalLengthX, focalLengthY, principalPointX, principalPointY, DistortionPair(radialDistortion0, radialDistortion1), DistortionPair(tangentialDistortion0, tangentialDistortion1));
1434 return;
1435 }
1436
1437 case PC_UNKNOWN:
1438 break;
1439 }
1440
1441 ocean_assert(false && "Invalid parameter configuration!");
1442}
1443
1444template <typename T>
1446{
1447 return radialDistortion_.first != 0 || radialDistortion_.second != 0
1448 || tangentialDistortion_.first != 0 || tangentialDistortion_.second != 0;
1449}
1450
1451template <typename T>
1452inline unsigned int PinholeCameraT<T>::width() const
1453{
1454 return width_;
1455}
1456
1457template <typename T>
1458inline unsigned int PinholeCameraT<T>::height() const
1459{
1460 return height_;
1461}
1462
1463template <typename T>
1465{
1466 return VectorT2<T>(principalPointX(), principalPointY());
1467}
1468
1469template <typename T>
1471{
1472 return intrinsics_(6);
1473}
1474
1475template <typename T>
1477{
1478 return intrinsics_(7);
1479}
1480
1481template <typename T>
1483{
1484 return intrinsics_(0);
1485}
1486
1487template <typename T>
1489{
1490 return intrinsics_(4);
1491}
1492
1493template <typename T>
1495{
1496 ocean_assert((std::is_same<T, float>::value) || intrinsics_.inverted() == invertedIntrinsics_);
1497 ocean_assert(NumericT<T>::isEqual(invertedIntrinsics_(0) * intrinsics_(0), 1));
1498
1499 return invertedIntrinsics_(0);
1500}
1501
1502template <typename T>
1504{
1505 ocean_assert((std::is_same<T, float>::value) || intrinsics_.inverted() == invertedIntrinsics_);
1506 ocean_assert(NumericT<T>::isEqual(invertedIntrinsics_(4) * intrinsics_(4), 1));
1507
1508 return invertedIntrinsics_(4);
1509}
1510
1511template <typename T>
1513{
1514 radialDistortion_ = radial;
1515}
1516
1517template <typename T>
1519{
1520 tangentialDistortion_ = tangential;
1521}
1522
1523template <typename T>
1524template <bool tUseBorderDistortionIfOutside>
1525VectorT2<T> PinholeCameraT<T>::undistort(const VectorT2<T>& distorted, const unsigned int iterations, const T zoom) const
1526{
1527 ocean_assert(iterations >= 1u && iterations <= 1000u && zoom > NumericT<T>::eps());
1528
1529 // check whether the camera is distortion free
1530 if (!hasDistortionParameters())
1531 {
1532 return distorted;
1533 }
1534
1535 const T invZoom = T(1) / zoom;
1536
1537 const VectorT2<T> nDistorted((distorted.x() - principalPointX()) * inverseFocalLengthX() * invZoom, (distorted.y() - principalPointY()) * inverseFocalLengthY() * invZoom);
1538
1539 const VectorT2<T> nMainOffset(distortNormalized<tUseBorderDistortionIfOutside>(nDistorted, invZoom) - nDistorted);
1540 VectorT2<T> nIntermediateUndistorted(nDistorted - nMainOffset);
1541
1542 unsigned int i = 0u;
1543
1544 while (i++ < iterations)
1545 {
1546 const VectorT2<T> nIntermediateDistorted(distortNormalized<tUseBorderDistortionIfOutside>(nIntermediateUndistorted, invZoom));
1547 const VectorT2<T> nIntermediateOffset(nDistorted - nIntermediateDistorted);
1548
1549 nIntermediateUndistorted = nIntermediateUndistorted + nIntermediateOffset * T(0.75);
1550
1551 const T offsetPixelX = NumericT<T>::abs(nIntermediateOffset.x() * focalLengthX());
1552 const T offsetPixelY = NumericT<T>::abs(nIntermediateOffset.y() * focalLengthY());
1553
1554 if (offsetPixelX < 0.05 && offsetPixelY < 0.05)
1555 {
1556 break;
1557 }
1558
1559 if (offsetPixelX > T(width_ * 10u) || offsetPixelY > T(height_ * 10u))
1560 {
1561 return distorted;
1562 }
1563 }
1564
1565 return VectorT2<T>(nIntermediateUndistorted.x() * focalLengthX() * zoom + principalPointX(), nIntermediateUndistorted.y() * focalLengthY() * zoom + principalPointY());
1566}
1567
1568template <typename T>
1569template <bool tUseBorderDistortionIfOutside>
1571{
1572 if (hasDistortionParameters())
1573 {
1574 if constexpr (tUseBorderDistortionIfOutside)
1575 {
1576 const VectorT2<T> nUndistorted((undistorted.x() - principalPointX()) * inverseFocalLengthX(),
1577 (undistorted.y() - principalPointY()) * inverseFocalLengthY());
1578
1579 const VectorT2<T> clampedNormalizedImagePoint(minmax(-principalPointX() * inverseFocalLengthX(), nUndistorted.x(), (T(width_) - principalPointX()) * inverseFocalLengthX()),
1580 minmax(-principalPointY() * inverseFocalLengthY(), nUndistorted.y(), (T(height_) - principalPointY()) * inverseFocalLengthY()));
1581
1582 const T sqr = clampedNormalizedImagePoint.sqr();
1583
1584 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1585
1586 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y()
1587 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.x()));
1588
1589 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.y()))
1590 + tangentialDistortion_.second * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y();
1591
1592 return VectorT2<T>((nUndistorted.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() + principalPointX(),
1593 (nUndistorted.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() + principalPointY());
1594 }
1595 else
1596 {
1597 const VectorT2<T> nUndistorted((undistorted.x() - principalPointX()) * inverseFocalLengthX(),
1598 (undistorted.y() - principalPointY()) * inverseFocalLengthY());
1599
1600 const T sqr = nUndistorted.sqr();
1601
1602 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1603
1604 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * nUndistorted.x() * nUndistorted.y()
1605 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(nUndistorted.x()));
1606
1607 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(nUndistorted.y()))
1608 + tangentialDistortion_.second * 2 * nUndistorted.x() * nUndistorted.y();
1609
1610 return VectorT2<T>((nUndistorted.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() + principalPointX(),
1611 (nUndistorted.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() + principalPointY());
1612 }
1613 }
1614 else
1615 {
1616 return undistorted;
1617 }
1618}
1619
1620template <typename T>
1621template <typename TParameter>
1622void PinholeCameraT<T>::copyParameters(unsigned int& width, unsigned int& height, std::vector<TParameter>& parameters, ParameterConfiguration& parameterConfiguration) const
1623{
1624 if (isValid())
1625 {
1626 width = width_;
1627 height = height_;
1628
1629 parameters =
1630 {
1631 TParameter(focalLengthX()),
1632 TParameter(focalLengthY()),
1633
1634 TParameter(principalPointX()),
1635 TParameter(principalPointY()),
1636
1637 TParameter(radialDistortion_.first),
1638 TParameter(radialDistortion_.second),
1639 TParameter(tangentialDistortion_.first),
1640 TParameter(tangentialDistortion_.second),
1641 };
1642
1643 ocean_assert(parameters.size() == 8);
1644
1645 parameterConfiguration = PC_8_PARAMETERS;
1646 }
1647 else
1648 {
1649 width = 0u;
1650 height = 0u;
1651
1652 parameters.clear();
1653
1654 parameterConfiguration = PC_UNKNOWN;
1655 }
1656}
1657
1658template <typename T>
1659inline bool PinholeCameraT<T>::isInside(const VectorT2<T>& imagePoint, const T signedBorder) const
1660{
1661 ocean_assert(isValid());
1662 ocean_assert(signedBorder < T(std::min(width_ / 2u, height_ / 2u)));
1663
1664 return imagePoint.x() >= signedBorder && imagePoint.y() >= signedBorder
1665 && imagePoint.x() < T(width_) - signedBorder && imagePoint.y() < T(height_) - signedBorder;
1666}
1667
1668template <typename T>
1670{
1671 ocean_assert(zoom > NumericT<T>::eps());
1672
1673#ifdef OCEAN_DEBUG
1674 SquareMatrixT4<T> debugCameraMatrix(intrinsic());
1675 debugCameraMatrix(0, 0) *= zoom;
1676 debugCameraMatrix(1, 1) *= zoom;
1677 debugCameraMatrix[15] = 1;
1678
1679 const SquareMatrixT4<T> debugEntireMatrix(debugCameraMatrix * (SquareMatrixT4<T>&)iFlippedExtrinsic);
1680 const HomogenousMatrixT4<T>& debugTransformationMatrix = (const HomogenousMatrixT4<T>&)debugEntireMatrix;
1681
1682 const HomogenousMatrixT4<T> transformationMatrix(HomogenousMatrixT4<T>(VectorT3<T>(intrinsics_[0] * zoom, intrinsics_[1], intrinsics_[2]), VectorT3<T>(intrinsics_[3], intrinsics_[4] * zoom, intrinsics_[5]), VectorT3<T>(intrinsics_[6], intrinsics_[7], intrinsics_[8])) * iFlippedExtrinsic);
1683 ocean_assert(transformationMatrix.isValid());
1684
1685 ocean_assert(transformationMatrix == debugTransformationMatrix);
1686#endif
1687
1688 return HomogenousMatrixT4<T>(HomogenousMatrixT4<T>(VectorT3<T>(intrinsics_[0] * zoom, intrinsics_[1], intrinsics_[2]), VectorT3<T>(intrinsics_[3], intrinsics_[4] * zoom, intrinsics_[5]), VectorT3<T>(intrinsics_[6], intrinsics_[7], intrinsics_[8])) * iFlippedExtrinsic);
1689}
1690
1691template <typename T>
1692template <typename U, bool tUseDistortionParameters>
1693inline void PinholeCameraT<T>::pointJacobian2x3IF(const VectorT3<U>& flippedCameraObjectPoint, U* jx, U* jy) const
1694{
1695 ocean_assert(isValid());
1696 ocean_assert(jx != nullptr && jy != nullptr);
1697
1698 if (tUseDistortionParameters && hasDistortionParameters())
1699 {
1700 const U x = U(flippedCameraObjectPoint.x());
1701 const U y = U(flippedCameraObjectPoint.y());
1702 const U z = U(flippedCameraObjectPoint.z());
1703
1704 const U fx = U(focalLengthX());
1705 const U fy = U(focalLengthY());
1706
1707 const U k1 = U(radialDistortion().first);
1708 const U k2 = U(radialDistortion().second);
1709
1710 const U p1 = U(tangentialDistortion().first);
1711 const U p2 = U(tangentialDistortion().second);
1712
1713 ocean_assert(NumericT<U>::isNotEqualEps(z));
1714 const U invZ = U(1) / z;
1715
1716 const U u = x * invZ;
1717 const U v = y * invZ;
1718
1719 const U dist1_u = U(1) + U(6) * p2 * u + U(2) * p1 * v + k1 * (U(3) * u * u + v * v) + k2 * (u * u + v * v) * (U(5) * u * u + v * v);
1720 const U dist2_u_1_v = U(2) * (p1 * u + v * (p2 + u * (k1 + U(2) * k2 * (u * u + v * v))));
1721 const U dist2_v = U(1) + U(2) * p2 * u + U(6) * p1 * v + k1 * (u * u + U(3) * v * v) + k2 * (u * u + v * v) * (u * u + U(5) * v * v);
1722
1723 const U Fx_w_dist1_u = fx * invZ * dist1_u;
1724 const U Fy_w_dist2_u = fy * invZ * dist2_u_1_v;
1725
1726 const U Fx_w_dist1_v = fx * invZ * dist2_u_1_v;
1727 const U Fy_w_dist2_v = fy * invZ * dist2_v;
1728
1729 const U Fx_w2__ = -fx * invZ * invZ * (x * dist1_u + y * dist2_u_1_v);
1730 const U Fy_w2__ = -fy * invZ * invZ * (x * dist2_u_1_v + y * dist2_v);
1731
1732 jx[0] = Fx_w_dist1_u;
1733 jx[1] = Fx_w_dist1_v;
1734 jx[2] = Fx_w2__;
1735
1736 jy[0] = Fy_w_dist2_u;
1737 jy[1] = Fy_w_dist2_v;
1738 jy[2] = Fy_w2__;
1739 }
1740 else
1741 {
1742 ocean_assert(NumericT<U>::isNotEqualEps(U(flippedCameraObjectPoint.z())));
1743 const U invZ = U(1) / U(flippedCameraObjectPoint.z());
1744
1745 const U fx_z = U(focalLengthX()) * invZ;
1746 const U fy_z = U(focalLengthY()) * invZ;
1747
1748 const U fx_x_z2 = -fx_z * U(flippedCameraObjectPoint.x()) * invZ;
1749 const U fy_y_z2 = -fy_z * U(flippedCameraObjectPoint.y()) * invZ;
1750
1751 jx[0] = fx_z;
1752 jx[1] = 0;
1753 jx[2] = fx_x_z2;
1754
1755 jy[0] = 0;
1756 jy[1] = fy_z;
1757 jy[2] = fy_y_z2;
1758 }
1759}
1760
1761template <typename T>
1763{
1764 return width_ != 0u && height_ != 0u;
1765}
1766
1767template <typename T>
1768template <bool tUseBorderDistortionIfOutside>
1769VectorT2<T> PinholeCameraT<T>::imagePoint2normalizedImagePoint(const VectorT2<T>& imagePoint, const bool undistortImagePoint) const
1770{
1771 if (undistortImagePoint)
1772 {
1773 return invertedIntrinsics_ * undistort<tUseBorderDistortionIfOutside>(imagePoint);
1774 }
1775
1776 return invertedIntrinsics_ * imagePoint;
1777}
1778
1779template <typename T>
1780inline VectorT2<T> PinholeCameraT<T>::imagePoint2normalizedImagePointDamped(const VectorT2<T>& imagePoint, const bool undistortImagePoint) const
1781{
1782 if (undistortImagePoint)
1783 {
1784 return invertedIntrinsics_ * undistortDamped(imagePoint);
1785 }
1786
1787 return invertedIntrinsics_ * imagePoint;
1788}
1789
1790template <typename T>
1791template <bool tUseBorderDistortionIfOutside>
1792VectorT2<T> PinholeCameraT<T>::normalizedImagePoint2imagePoint(const VectorT2<T>& normalizedImagePoint, const bool distortImagePoints) const
1793{
1794 ocean_assert(isValid());
1795
1796 if (distortImagePoints)
1797 {
1798 if constexpr (tUseBorderDistortionIfOutside)
1799 {
1800 const VectorT2<T> clampedNormalizedImagePoint(minmax(-principalPointX() * inverseFocalLengthX(), normalizedImagePoint.x(), (T(width_) - principalPointX()) * inverseFocalLengthX()),
1801 minmax(-principalPointY() * inverseFocalLengthY(), normalizedImagePoint.y(), (T(height_) - principalPointY()) * inverseFocalLengthY()));
1802
1803 // if the camera does not provide a tangential distortion
1804 if (tangentialDistortion_.first == 0 && tangentialDistortion_.second == 0)
1805 {
1806 const T sqr = clampedNormalizedImagePoint.sqr();
1807 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1808
1809 return VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor) * focalLengthX() + principalPointX(),
1810 (normalizedImagePoint.y() * radialDistortionFactor) * focalLengthY() + principalPointY());
1811 }
1812 else
1813 {
1814 ocean_assert(tangentialDistortion_.first != 0 || tangentialDistortion_.second != 0);
1815
1816 const T sqr = clampedNormalizedImagePoint.sqr();
1817 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1818
1819 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y()
1820 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.x()));
1821
1822 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.y()))
1823 + tangentialDistortion_.second * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y();
1824
1825 return VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() + principalPointX(),
1826 (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() + principalPointY());
1827 }
1828 }
1829 else
1830 {
1831 // if the camera does not provide a tangential distortion
1832 if (tangentialDistortion_.first == 0 && tangentialDistortion_.second == 0)
1833 {
1834 const T sqr = normalizedImagePoint.sqr();
1835 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1836
1837 return VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor) * focalLengthX() + principalPointX(),
1838 (normalizedImagePoint.y() * radialDistortionFactor) * focalLengthY() + principalPointY());
1839 }
1840 else
1841 {
1842 ocean_assert(tangentialDistortion_.first != 0 || tangentialDistortion_.second != 0);
1843
1844 const T sqr = normalizedImagePoint.sqr();
1845 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1846
1847 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * normalizedImagePoint.x() * normalizedImagePoint.y()
1848 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.x()));
1849
1850 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.y()))
1851 + tangentialDistortion_.second * 2 * normalizedImagePoint.x() * normalizedImagePoint.y();
1852
1853 return VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() + principalPointX(),
1854 (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() + principalPointY());
1855 }
1856 }
1857 }
1858 else
1859 {
1860 return VectorT2<T>(normalizedImagePoint.x() * focalLengthX() + principalPointX(), normalizedImagePoint.y() * focalLengthY() + principalPointY());
1861 }
1862}
1863
1864template <typename T>
1865template <bool tUseBorderDistortionIfOutside>
1866void PinholeCameraT<T>::normalizedImagePoints2imagePoints(const VectorT2<T>* normalizedImagePoints, const size_t numberNormalizedImagePoints, const bool distortImagePoints, VectorT2<T>* imagePoints) const
1867{
1868 ocean_assert(numberNormalizedImagePoints == 0u || (normalizedImagePoints && imagePoints));
1869
1870 const T leftClamping = -principalPointX() * inverseFocalLengthX();
1871 const T rightClamping = (T(width_) - principalPointX()) * inverseFocalLengthX();
1872 const T topClamping = -principalPointY() * inverseFocalLengthY();
1873 const T bottomClamping = (T(height_) - principalPointY()) * inverseFocalLengthY();
1874
1875 if (distortImagePoints && hasDistortionParameters())
1876 {
1877 // if the camera does not provide a tangential distortion
1878 if (tangentialDistortion_.first == 0 && tangentialDistortion_.second == 0)
1879 {
1880 T sqr, radialDistortionFactor;
1881
1882 for (unsigned int n = 0u; n < numberNormalizedImagePoints; ++n)
1883 {
1884 const VectorT2<T>& normalizedImagePoint(normalizedImagePoints[n]);
1885
1886 if constexpr (tUseBorderDistortionIfOutside)
1887 {
1888 const VectorT2<T> clampedNormalizedImagePoint(minmax(leftClamping, normalizedImagePoint.x(), rightClamping), minmax(topClamping, normalizedImagePoint.y(), bottomClamping));
1889
1890 sqr = clampedNormalizedImagePoint.sqr();
1891 radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1892
1893 imagePoints[n].x() = (normalizedImagePoint.x() * radialDistortionFactor) * focalLengthX() + principalPointX();
1894 imagePoints[n].y() = (normalizedImagePoint.y() * radialDistortionFactor) * focalLengthY() + principalPointY();
1895 }
1896 else
1897 {
1898 sqr = normalizedImagePoint.sqr();
1899 radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1900
1901 imagePoints[n].x() = (normalizedImagePoint.x() * radialDistortionFactor) * focalLengthX() + principalPointX();
1902 imagePoints[n].y() = (normalizedImagePoint.y() * radialDistortionFactor) * focalLengthY() + principalPointY();
1903 }
1904 }
1905 }
1906 else
1907 {
1908 ocean_assert(tangentialDistortion_.first != 0 || tangentialDistortion_.second != 0);
1909 T sqr, radialDistortionFactor, tangentialDistortionCorrectionX, tangentialDistortionCorrectionY;
1910
1911 for (unsigned int n = 0u; n < numberNormalizedImagePoints; ++n)
1912 {
1913 const VectorT2<T>& normalizedImagePoint(normalizedImagePoints[n]);
1914
1915 if constexpr (tUseBorderDistortionIfOutside)
1916 {
1917 const VectorT2<T> clampedNormalizedImagePoint(minmax(leftClamping, normalizedImagePoint.x(), rightClamping), minmax(topClamping, normalizedImagePoint.y(), bottomClamping));
1918
1919 sqr = clampedNormalizedImagePoint.sqr();
1920 radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1921
1922 tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y()
1923 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.x()));
1924
1925 tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.y()))
1926 + tangentialDistortion_.second * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y();
1927
1928 imagePoints[n].x() = (normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() + principalPointX();
1929 imagePoints[n].y() = (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() + principalPointY();
1930 }
1931 else
1932 {
1933 sqr = normalizedImagePoint.sqr();
1934 radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
1935
1936 tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * normalizedImagePoint.x() * normalizedImagePoint.y()
1937 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.x()));
1938
1939 tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.y()))
1940 + tangentialDistortion_.second * 2 * normalizedImagePoint.x() * normalizedImagePoint.y();
1941
1942 imagePoints[n].x() = (normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() + principalPointX();
1943 imagePoints[n].y() = (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() + principalPointY();
1944 }
1945 }
1946 }
1947 }
1948 else
1949 {
1950 for (unsigned int n = 0u; n < numberNormalizedImagePoints; ++n)
1951 {
1952 const VectorT2<T>& normalizedImagePoint(normalizedImagePoints[n]);
1953
1954 imagePoints[n].x() = normalizedImagePoint.x() * focalLengthX() + principalPointX();
1955 imagePoints[n].y() = normalizedImagePoint.y() * focalLengthY() + principalPointY();
1956 }
1957 }
1958}
1959
1960template <typename T>
1961template <bool tUseBorderDistortionIfOutside>
1962inline VectorT2<T> PinholeCameraT<T>::projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const VectorT3<T>& worldObjectPoint, const bool distortImagePoint, const T zoom) const
1963{
1964 ocean_assert(world_T_camera.isValid() && zoom > NumericT<T>::eps());
1965 return projectToImageIF<tUseBorderDistortionIfOutside>(CameraT<T>::standard2InvertedFlipped(world_T_camera), worldObjectPoint, distortImagePoint, zoom);
1966}
1967
1968template <typename T>
1969template <bool tUseBorderDistortionIfOutside>
1970inline BoxT2<T> PinholeCameraT<T>::projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const BoxT3<T>& worldObjectBox, const bool distortImagePoint, const T zoom) const
1971{
1972 ocean_assert(world_T_camera.isValid() && worldObjectBox.isValid() && zoom > NumericT<T>::eps());
1973 return projectToImageIF<tUseBorderDistortionIfOutside>(CameraT<T>::standard2InvertedFlipped(world_T_camera), worldObjectBox, distortImagePoint, zoom);
1974}
1975
1976template <typename T>
1977template <bool tUseBorderDistortionIfOutside>
1978inline TriangleT2<T> PinholeCameraT<T>::projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const TriangleT3<T>& worldObjectTriangle, const bool distortImagePoint, const T zoom) const
1979{
1980 ocean_assert(world_T_camera.isValid() && worldObjectTriangle.isValid() && zoom > NumericT<T>::eps());
1981 return projectToImageIF<tUseBorderDistortionIfOutside>(CameraT<T>::standard2InvertedFlipped(world_T_camera), worldObjectTriangle, distortImagePoint, zoom);
1982}
1983
1984template <typename T>
1985template <bool tUseBorderDistortionIfOutside>
1986inline void PinholeCameraT<T>::projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const VectorT3<T>* worldObjectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2<T>* imagePoints, const T zoom) const
1987{
1988 ocean_assert(world_T_camera.isValid() && zoom > NumericT<T>::eps());
1989 ocean_assert(numberObjectPoints == 0u || (worldObjectPoints != nullptr && imagePoints != nullptr));
1990
1991 return projectToImageIF<tUseBorderDistortionIfOutside>(CameraT<T>::standard2InvertedFlipped(world_T_camera), worldObjectPoints, numberObjectPoints, distortImagePoints, imagePoints, zoom);
1992}
1993
1994template <typename T>
1995template <bool tUseBorderDistortionIfOutside>
1996inline LineT2<T> PinholeCameraT<T>::projectToImage(const HomogenousMatrixT4<T>& world_T_camera, const LineT3<T>& worldLine, const bool distortProjectedLine, const T zoom) const
1997{
1998 ocean_assert(world_T_camera.isValid() && zoom > NumericT<T>::eps());
1999 ocean_assert(worldLine.isValid());
2000
2001 return projectToImageIF<tUseBorderDistortionIfOutside>(CameraT<T>::standard2InvertedFlipped(world_T_camera), worldLine, distortProjectedLine, zoom);
2002}
2003
2004template <typename T>
2005template <bool tUseBorderDistortionIfOutside>
2006VectorT2<T> PinholeCameraT<T>::projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const VectorT3<T>& worldObjectPoint, const bool distortImagePoint, const T zoom) const
2007{
2008 ocean_assert(flippedCamera_T_world.isValid() && zoom > NumericT<T>::eps());
2009
2010 const VectorT3<T> transformedObjectPoint(flippedCamera_T_world * worldObjectPoint);
2011
2012 ocean_assert(NumericT<T>::isNotEqualEps(transformedObjectPoint.z()));
2013 const T factor = T(1) / transformedObjectPoint.z();
2014
2015 const VectorT2<T> normalizedImagePoint(transformedObjectPoint.x() * factor, transformedObjectPoint.y() * factor);
2016
2017 if (!distortImagePoint)
2018 {
2019 return VectorT2<T>(normalizedImagePoint.x() * focalLengthX() * zoom + principalPointX(), normalizedImagePoint.y() * focalLengthY() * zoom + principalPointY());
2020 }
2021
2022 if constexpr (tUseBorderDistortionIfOutside)
2023 {
2024 const T invZoom = T(1) / zoom;
2025
2026 const VectorT2<T> clampedNormalizedImagePoint(minmax(-principalPointX() * inverseFocalLengthX() * invZoom, normalizedImagePoint.x(), (T(width_) - principalPointX()) * inverseFocalLengthX() * invZoom),
2027 minmax(-principalPointY() * inverseFocalLengthY() * invZoom, normalizedImagePoint.y(), (T(height_) - principalPointY()) * inverseFocalLengthY() * invZoom));
2028
2029 const T sqr = clampedNormalizedImagePoint.sqr();
2030
2031 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2032
2033 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y()
2034 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.x()));
2035
2036 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.y()))
2037 + tangentialDistortion_.second * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y();
2038
2039 return VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() * zoom + principalPointX(),
2040 (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() * zoom + principalPointY());
2041 }
2042 else
2043 {
2044 const T sqr = normalizedImagePoint.sqr();
2045
2046 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2047
2048 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * normalizedImagePoint.x() * normalizedImagePoint.y()
2049 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.x()));
2050
2051 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.y()))
2052 + tangentialDistortion_.second * 2 * normalizedImagePoint.x() * normalizedImagePoint.y();
2053
2054 return VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() * zoom + principalPointX(),
2055 (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() * zoom + principalPointY());
2056 }
2057}
2058
2059template <typename T>
2060template <bool tUseBorderDistortionIfOutside>
2061BoxT2<T> PinholeCameraT<T>::projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const BoxT3<T>& worldObjectBox, const bool distortImagePoint, const T zoom) const
2062{
2063 ocean_assert(flippedCamera_T_world.isValid() && zoom > NumericT<T>::eps());
2064 ocean_assert(worldObjectBox.isValid());
2065
2066 VectorT3<T> boxObjectCorners[8];
2067 const unsigned int numberBoxImagePoints = worldObjectBox.corners(boxObjectCorners);
2068
2069 BoxT2<T> result;
2070 for (unsigned int n = 0; n < numberBoxImagePoints; ++n)
2071 {
2072 result += projectToImageIF<tUseBorderDistortionIfOutside>(flippedCamera_T_world, boxObjectCorners[n], distortImagePoint, zoom);
2073 }
2074
2075 return result;
2076}
2077
2078template <typename T>
2079template <bool tUseBorderDistortionIfOutside>
2080TriangleT2<T> PinholeCameraT<T>::projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const TriangleT3<T>& worldObjectTriangle, const bool distortImagePoint, const T zoom) const
2081{
2082 ocean_assert(flippedCamera_T_world.isValid() && zoom > NumericT<T>::eps());
2083 ocean_assert(worldObjectTriangle.isValid());
2084
2085 return TriangleT2<T>(projectToImageIF<tUseBorderDistortionIfOutside>(flippedCamera_T_world, worldObjectTriangle.point0(), distortImagePoint, zoom),
2086 projectToImageIF<tUseBorderDistortionIfOutside>(flippedCamera_T_world, worldObjectTriangle.point1(), distortImagePoint, zoom),
2087 projectToImageIF<tUseBorderDistortionIfOutside>(flippedCamera_T_world, worldObjectTriangle.point2(), distortImagePoint, zoom));
2088}
2089
2090template <typename T>
2091template <bool tUseBorderDistortionIfOutside>
2092VectorT2<T> PinholeCameraT<T>::projectToImageIF(const VectorT2<T>& normalizedObjectPoint, const bool distortImagePoint, const T zoom) const
2093{
2094 ocean_assert(zoom > NumericT<T>::eps());
2095
2096 if (distortImagePoint)
2097 {
2098 if constexpr (tUseBorderDistortionIfOutside)
2099 {
2100 const T invZoom = T(1) / zoom;
2101
2102 const VectorT2<T> clampedNormalizedImagePoint(minmax(-principalPointX() * inverseFocalLengthX() * invZoom, normalizedObjectPoint.x(), (T(width_) - principalPointX()) * inverseFocalLengthX() * invZoom),
2103 minmax(-principalPointY() * inverseFocalLengthY() * invZoom, normalizedObjectPoint.y(), (T(height_) - principalPointY()) * inverseFocalLengthY() * invZoom));
2104
2105 const T sqr = clampedNormalizedImagePoint.sqr();
2106
2107 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2108
2109 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y()
2110 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.x()));
2111
2112 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.y()))
2113 + tangentialDistortion_.second * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y();
2114
2115 return VectorT2<T>((normalizedObjectPoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() * zoom + principalPointX(),
2116 (normalizedObjectPoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() * zoom + principalPointY());
2117 }
2118 else
2119 {
2120 const T sqr = normalizedObjectPoint.sqr();
2121
2122 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2123
2124 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * normalizedObjectPoint.x() * normalizedObjectPoint.y()
2125 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(normalizedObjectPoint.x()));
2126
2127 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(normalizedObjectPoint.y()))
2128 + tangentialDistortion_.second * 2 * normalizedObjectPoint.x() * normalizedObjectPoint.y();
2129
2130 return VectorT2<T>((normalizedObjectPoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() * zoom + principalPointX(),
2131 (normalizedObjectPoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() * zoom + principalPointY());
2132 }
2133 }
2134 else
2135 {
2136 return VectorT2<T>(normalizedObjectPoint.x() * focalLengthX() * zoom + principalPointX(), normalizedObjectPoint.y() * focalLengthY() * zoom + principalPointY());
2137 }
2138}
2139
2140template <typename T>
2141template <bool tUseBorderDistortionIfOutside>
2142void PinholeCameraT<T>::projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const VectorT3<T>* worldObjectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2<T>* imagePoints, const T zoom) const
2143{
2144 ocean_assert(flippedCamera_T_world.isValid() && zoom > NumericT<T>::eps());
2145 ocean_assert((worldObjectPoints != nullptr && imagePoints != nullptr) || numberObjectPoints == 0u);
2146
2147 if (distortImagePoints && hasDistortionParameters())
2148 {
2149 const T invZoom = T(1) / zoom;
2150
2151 const T leftClamping = -principalPointX() * inverseFocalLengthX() * invZoom;
2152 const T rightClamping = (T(width_) - principalPointX()) * inverseFocalLengthX() * invZoom;
2153 const T topClamping = -principalPointY() * inverseFocalLengthY() * invZoom;
2154 const T bottomClamping = (T(height_) - principalPointY()) * inverseFocalLengthY() * invZoom;
2155
2156 // if the camera does not provide tangential distortion
2157 if (tangentialDistortion_.first == 0 && tangentialDistortion_.second == 0)
2158 {
2159 for (size_t n = 0; n < numberObjectPoints; ++n)
2160 {
2161 const VectorT3<T> objectPoint(flippedCamera_T_world * worldObjectPoints[n]);
2162
2163 ocean_assert(NumericT<T>::isNotEqualEps(objectPoint.z()));
2164 const T factor = 1 / objectPoint.z();
2165
2166 const VectorT2<T> normalizedImagePoint(objectPoint.x() * factor, objectPoint.y() * factor);
2167
2168 if constexpr (tUseBorderDistortionIfOutside)
2169 {
2170 const VectorT2<T> clampedNormalizedImagePoint(minmax(leftClamping, normalizedImagePoint.x(), rightClamping), minmax(topClamping, normalizedImagePoint.y(), bottomClamping));
2171
2172 const T sqr = clampedNormalizedImagePoint.sqr();
2173 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2174
2175 *imagePoints = VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor) * focalLengthX() * zoom + principalPointX(),
2176 (normalizedImagePoint.y() * radialDistortionFactor) * focalLengthY() * zoom + principalPointY());
2177 }
2178 else
2179 {
2180 const T sqr = normalizedImagePoint.sqr();
2181 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2182
2183 *imagePoints = VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor) * focalLengthX() * zoom + principalPointX(),
2184 (normalizedImagePoint.y() * radialDistortionFactor) * focalLengthY() * zoom + principalPointY());
2185 }
2186
2187 ++imagePoints;
2188 }
2189 }
2190 else
2191 {
2192 ocean_assert(tangentialDistortion_.first != 0 || tangentialDistortion_.second != 0);
2193
2194 for (size_t n = 0; n < numberObjectPoints; ++n)
2195 {
2196 const VectorT3<T> objectPoint(flippedCamera_T_world * worldObjectPoints[n]);
2197
2198 ocean_assert(NumericT<T>::isNotEqualEps(objectPoint.z()));
2199 const T factor = 1 / objectPoint.z();
2200
2201 const VectorT2<T> normalizedImagePoint(objectPoint.x() * factor, objectPoint.y() * factor);
2202
2203 if constexpr (tUseBorderDistortionIfOutside)
2204 {
2205 const VectorT2<T> clampedNormalizedImagePoint(minmax(leftClamping, normalizedImagePoint.x(), rightClamping), minmax(topClamping, normalizedImagePoint.y(), bottomClamping));
2206
2207 const T sqr = clampedNormalizedImagePoint.sqr();
2208 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2209
2210 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y()
2211 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.x()));
2212
2213 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.y()))
2214 + tangentialDistortion_.second * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y();
2215
2216 *imagePoints = VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() * zoom + principalPointX(),
2217 (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() * zoom + principalPointY());
2218 }
2219 else
2220 {
2221 const T sqr = normalizedImagePoint.sqr();
2222 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2223
2224 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * normalizedImagePoint.x() * normalizedImagePoint.y()
2225 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.x()));
2226
2227 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.y()))
2228 + tangentialDistortion_.second * 2 * normalizedImagePoint.x() * normalizedImagePoint.y();
2229
2230 *imagePoints = VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() * zoom + principalPointX(),
2231 (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() * zoom + principalPointY());
2232 }
2233
2234 ++imagePoints;
2235 }
2236 }
2237 }
2238 else
2239 {
2240 // create one transformation matrix covering the entire pipeline (transformation and then projection)
2241 const HomogenousMatrixT4<T> transformationIF(transformationMatrixIF(flippedCamera_T_world, zoom));
2242 ocean_assert(transformationIF.isValid());
2243
2244 for (size_t n = 0; n < numberObjectPoints; ++n)
2245 {
2246 const VectorT3<T> transformedObjectPoint(transformationIF * worldObjectPoints[n]);
2247
2248 ocean_assert(NumericT<T>::isNotEqualEps(transformedObjectPoint.z()));
2249 const T factor = 1 / transformedObjectPoint.z();
2250
2251 *imagePoints++ = VectorT2<T>(transformedObjectPoint.x() * factor, transformedObjectPoint.y() * factor);
2252 }
2253 }
2254}
2255
2256template <typename T>
2257template <bool tUseBorderDistortionIfOutside>
2258LineT2<T> PinholeCameraT<T>::projectToImageIF(const HomogenousMatrixT4<T>& flippedCamera_T_world, const LineT3<T>& worldLine, const bool distortProjectedLine, const T zoom) const
2259{
2260 ocean_assert(flippedCamera_T_world.isValid() && zoom > NumericT<T>::eps());
2261 ocean_assert(worldLine.isValid());
2262
2263 const VectorT2<T> firstImagePoint(projectToImageIF<tUseBorderDistortionIfOutside>(flippedCamera_T_world, worldLine.point(), distortProjectedLine, zoom));
2264 const VectorT2<T> secondImagePoint(projectToImageIF<tUseBorderDistortionIfOutside>(flippedCamera_T_world, worldLine.point(10), distortProjectedLine, zoom));
2265
2266 if (firstImagePoint == secondImagePoint)
2267 {
2268 return LineT2<T>();
2269 }
2270
2271 return LineT2<T>(firstImagePoint, (secondImagePoint - firstImagePoint).normalized());
2272}
2273
2274template <typename T>
2275inline VectorT2<T> PinholeCameraT<T>::projectToImageDamped(const HomogenousMatrixT4<T>& extrinsic, const VectorT3<T>& objectPoint, const bool distortImagePoint, const T dampingFactor, const T zoom) const
2276{
2277 ocean_assert(extrinsic.isValid() && dampingFactor >= 0 && zoom > NumericT<T>::eps());
2278 return projectToImageDampedIF(CameraT<T>::standard2InvertedFlipped(extrinsic), objectPoint, distortImagePoint, dampingFactor, zoom);
2279}
2280
2281template <typename T>
2282inline BoxT2<T> PinholeCameraT<T>::projectToImageDamped(const HomogenousMatrixT4<T>& extrinsic, const BoxT3<T>& objectBox, const bool distortImagePoint, const T dampingFactor, const T zoom) const
2283{
2284 ocean_assert(extrinsic.isValid() && dampingFactor >= 0 && zoom > NumericT<T>::eps());
2285 return projectToImageDampedIF(CameraT<T>::standard2InvertedFlipped(extrinsic), objectBox, distortImagePoint, dampingFactor, zoom);
2286}
2287
2288template <typename T>
2289inline TriangleT2<T> PinholeCameraT<T>::projectToImageDamped(const HomogenousMatrixT4<T>& extrinsic, const TriangleT3<T>& objectTriangle, const bool distortImagePoint, const T dampingFactor, const T zoom) const
2290{
2291 ocean_assert(extrinsic.isValid() && dampingFactor >= 0 && zoom > NumericT<T>::eps());
2292 return projectToImageDampedIF(CameraT<T>::standard2InvertedFlipped(extrinsic), objectTriangle, distortImagePoint, dampingFactor, zoom);
2293}
2294
2295template <typename T>
2296inline void PinholeCameraT<T>::projectToImageDamped(const HomogenousMatrixT4<T>& extrinsic, const VectorT3<T>* objectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2<T>* imagePoints, const T dampingFactor, const T zoom) const
2297{
2298 ocean_assert(extrinsic.isValid() && dampingFactor >= 0 && zoom > NumericT<T>::eps());
2299 ocean_assert(numberObjectPoints == 0u || (objectPoints && imagePoints));
2300
2301 return projectToImageDampedIF(CameraT<T>::standard2InvertedFlipped(extrinsic), objectPoints, numberObjectPoints, distortImagePoints, imagePoints, dampingFactor, zoom);
2302}
2303
2304template <typename T>
2305template <bool tDistortImagePoint, bool tUseBorderDistortionIfOutside>
2306inline VectorT2<T> PinholeCameraT<T>::projectToImageIF(const HomogenousMatrixT4<T>& iFlippedExtrinsic, const VectorT3<T>& objectPoint, const T zoom) const
2307{
2308 ocean_assert(iFlippedExtrinsic.isValid() && zoom > NumericT<T>::eps());
2309
2310 const VectorT3<T> transformedObjectPoint(iFlippedExtrinsic * objectPoint);
2311
2312 ocean_assert(NumericT<T>::isNotEqualEps(transformedObjectPoint.z()));
2313 const T factor = T(1) / transformedObjectPoint.z();
2314 ocean_assert(NumericT<T>::isNotEqualEps(factor));
2315
2316 const VectorT2<T> normalizedImagePoint(transformedObjectPoint.x() * factor, transformedObjectPoint.y() * factor);
2317
2318 if (!tDistortImagePoint)
2319 {
2320 return VectorT2<T>(normalizedImagePoint.x() * focalLengthX() * zoom + principalPointX(), normalizedImagePoint.y() * focalLengthY() * zoom + principalPointY());
2321 }
2322
2323 if constexpr (tUseBorderDistortionIfOutside)
2324 {
2325 const T invZoom = T(1) / zoom;
2326
2327 const VectorT2<T> clampedNormalizedImagePoint(minmax(-principalPointX() * inverseFocalLengthX() * invZoom, normalizedImagePoint.x(), (T(width_) - principalPointX()) * inverseFocalLengthX() * invZoom),
2328 minmax(-principalPointY() * inverseFocalLengthY() * invZoom, normalizedImagePoint.y(), (T(height_) - principalPointY()) * inverseFocalLengthY() * invZoom));
2329
2330 const T sqr = clampedNormalizedImagePoint.sqr();
2331
2332 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2333
2334 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y()
2335 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.x()));
2336
2337 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.y()))
2338 + tangentialDistortion_.second * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y();
2339
2340 return VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() * zoom + principalPointX(),
2341 (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() * zoom + principalPointY());
2342 }
2343 else
2344 {
2345 const T sqr = normalizedImagePoint.sqr();
2346
2347 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2348
2349 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * normalizedImagePoint.x() * normalizedImagePoint.y()
2350 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.x()));
2351
2352 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(normalizedImagePoint.y()))
2353 + tangentialDistortion_.second * 2 * normalizedImagePoint.x() * normalizedImagePoint.y();
2354
2355 return VectorT2<T>((normalizedImagePoint.x() * radialDistortionFactor + tangentialDistortionCorrectionX) * focalLengthX() * zoom + principalPointX(),
2356 (normalizedImagePoint.y() * radialDistortionFactor + tangentialDistortionCorrectionY) * focalLengthY() * zoom + principalPointY());
2357 }
2358}
2359
2360template <typename T>
2361inline VectorT3<T> PinholeCameraT<T>::vector(const VectorT2<T>& position, const bool makeUnitVector) const
2362{
2363 /**
2364 * Ray determination: with object point (X, Y, Z) and image point (x, y, z) -> (x', y')
2365 *
2366 * x = Fx * X + mx * Z
2367 * y = Fy * Y + my * Z
2368 * z = Z
2369 *
2370 * x' = x / z = (Fx * X) / Z + mx
2371 * y' = y / z = (Fy * Y) / Z + my
2372 *
2373 * Inverse calculation:
2374 * (x' - mx) / Fx = X / Z
2375 * (y' - my) / Fy = Y / Z
2376 *
2377 * Using a distance of Z:= 1 results in:
2378 * X = (x' - mx) / Fx
2379 * Y = (y' - my) / Fy
2380 */
2381
2382 /**
2383 * The calculation is identical to the multiplication between the inverted camera matrix and the position vector.
2384 *
2385 * Inverse camera matrix:
2386 * | 1/Fx 0 -mx/Fx |<br>
2387 * | 0 1/Fy -my/Fy |<br>
2388 * | 0 0 1 |<br>
2389 */
2390
2391#ifdef OCEAN_DEBUG
2392
2393 const VectorT3<T> testVector(VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX(), (position(1) - principalPointY()) * -inverseFocalLengthY(), -1).normalized());
2394 ocean_assert(position.isEqual(projectToImage<false>(HomogenousMatrixT4<T>(true), testVector, false), T(0.01)));
2395 ocean_assert(NumericT<T>::isWeakEqual(testVector.length(), 1));
2396
2397#endif
2398
2399 if (makeUnitVector)
2400 {
2401 return VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX(), (position(1) - principalPointY()) * -inverseFocalLengthY(), -1).normalized();
2402 }
2403 else
2404 {
2405 return VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX(), (position(1) - principalPointY()) * -inverseFocalLengthY(), -1);
2406 }
2407}
2408
2409template <typename T>
2410inline VectorT3<T> PinholeCameraT<T>::vector(const VectorT2<T>& position, const T zoom, const bool makeUnitVector) const
2411{
2412 ocean_assert(zoom > NumericT<T>::eps());
2413
2414 /**
2415 * Ray determination: with object point (X, Y, Z), zoom s, and image point (x, y, z) -> (x', y')
2416 *
2417 * x = s * Fx * X + mx * Z
2418 * y = s * Fy * Y + my * Z
2419 * z = Z
2420 *
2421 * x' = x / z = (s * Fx * X) / Z + mx
2422 * y' = y / z = (s * Fy * Y) / Z + my
2423 *
2424 * Inverse calculation:
2425 * (x' - mx) / (s * Fx) = X / Z
2426 * (y' - my) / (s * Fy) = Y / Z
2427 *
2428 * Using a distance of Z:= 1 results in:
2429 * X = (x' - mx) / (s * Fx)
2430 * Y = (y' - my) / (s * Fy)
2431 */
2432
2433 /**
2434 * The calculation is identical to the multiplication between the inverted camera matrix and the position vector.
2435 *
2436 * Inverse camera matrix:
2437 * | 1/(s Fx) 0 -mx/(s Fx) |<br>
2438 * | 0 1/(s Fy) -my/(s Fy) |<br>
2439 * | 0 0 1 |<br>
2440 */
2441
2442 const T invZoom = T(1) / zoom;
2443
2444#ifdef OCEAN_DEBUG
2445
2446 const VectorT3<T> testVector(VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX() * invZoom, (position(1) - principalPointY()) * -inverseFocalLengthY() * invZoom, -1).normalized());
2447 ocean_assert(position.isEqual(projectToImage<false>(HomogenousMatrixT4<T>(true), testVector, false, zoom), T(0.01)));
2448 ocean_assert(NumericT<T>::isWeakEqual(testVector.length(), 1));
2449
2450#endif
2451
2452 if (makeUnitVector)
2453 {
2454 return VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX() * invZoom, (position(1) - principalPointY()) * -inverseFocalLengthY() * invZoom, -1).normalized();
2455 }
2456 else
2457 {
2458 return VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX() * invZoom, (position(1) - principalPointY()) * -inverseFocalLengthY() * invZoom, -1);
2459 }
2460}
2461
2462template <typename T>
2463inline VectorT3<T> PinholeCameraT<T>::vectorToPlane(const VectorT2<T>& position, const T distance) const
2464{
2465 /**
2466 * Ray determination: with object point (X, Y, Z) and image point (x, y, z) -> (x / z, y / z, 1) -> (x', y')
2467 *
2468 * x = Fx * X + mx * Z
2469 * y = Fy * Y + my * Z
2470 * z = Z
2471 *
2472 * x' = x / z = (Fx * X) / Z + mx
2473 * y' = y / z = (Fy * Y) / Z + my
2474 *
2475 * Inverse calculation:
2476 * (x' - mx) / Fx = X / Z
2477 * (y' - my) / Fy = Y / Z
2478 */
2479
2480#ifdef OCEAN_DEBUG
2481
2482 const VectorT3<T> testVector(distance * (position(0) - principalPointX()) * inverseFocalLengthX(), distance * (position(1) - principalPointY()) * -inverseFocalLengthY(), -distance);
2483 ocean_assert(position.isEqual(projectToImage<false>(HomogenousMatrixT4<T>(true), testVector, false), T(0.01)));
2484 ocean_assert(NumericT<T>::isWeakEqual(testVector * VectorT3<T>(0, 0, -1), distance));
2485
2486#endif
2487
2488 return VectorT3<T>(distance * (position(0) - principalPointX()) * inverseFocalLengthX(), distance * (position(1) - principalPointY()) * -inverseFocalLengthY(), -distance);
2489}
2490
2491template <typename T>
2492inline VectorT3<T> PinholeCameraT<T>::vectorToPlane(const VectorT2<T>& position, const T distance, const T zoom) const
2493{
2494 ocean_assert(zoom > NumericT<T>::eps());
2495
2496 /**
2497 * Ray determination: with object point (X, Y, Z) and image point (x, y, z) -> (x / z, y / z, 1) -> (x', y')
2498 *
2499 * x = Fx * X + mx * Z
2500 * y = Fy * Y + my * Z
2501 * z = Z
2502 *
2503 * x' = x / z = (Fx * X) / Z + mx
2504 * y' = y / z = (Fy * Y) / Z + my
2505 *
2506 * Inverse calculation:
2507 * (x' - mx) / Fx = X / Z
2508 * (y' - my) / Fy = Y / Z
2509 */
2510
2511 const T invZoom = T(1) / zoom;
2512
2513#ifdef OCEAN_DEBUG
2514
2515 const VectorT3<T> testVector(distance * (position(0) - principalPointX()) * inverseFocalLengthX() * invZoom, distance * (position(1) - principalPointY()) * -inverseFocalLengthY() * invZoom, -distance);
2516 ocean_assert(position.isEqual(projectToImage<false>(HomogenousMatrixT4<T>(true), testVector, false, zoom), T(0.01)));
2517 ocean_assert(NumericT<T>::isWeakEqual(testVector * VectorT3<T>(0, 0, -1), distance));
2518
2519#endif
2520
2521 return VectorT3<T>(distance * (position(0) - principalPointX()) * inverseFocalLengthX() * invZoom, distance * (position(1) - principalPointY()) * -inverseFocalLengthY() * invZoom, -distance);
2522}
2523
2524template <typename T>
2525inline VectorT3<T> PinholeCameraT<T>::vectorIF(const VectorT2<T>& position, const bool makeUnitVector) const
2526{
2527#ifdef OCEAN_DEBUG
2528
2529 const VectorT3<T> testVector(VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX(), (position(1) - principalPointY()) * inverseFocalLengthY(), 1).normalized());
2530 ocean_assert((std::is_same<T, float>::value) || position.isEqual(projectToImageIF<false>(HomogenousMatrixT4<T>(true), testVector, false), T(0.01)));
2531#endif
2532
2533 if (makeUnitVector)
2534 {
2535 return VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX(), (position(1) - principalPointY()) * inverseFocalLengthY(), 1).normalized();
2536 }
2537 else
2538 {
2539 return VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX(), (position(1) - principalPointY()) * inverseFocalLengthY(), 1);
2540 }
2541}
2542
2543template <typename T>
2544inline VectorT3<T> PinholeCameraT<T>::vectorIF(const VectorT2<T>& position, const T zoom, const bool makeUnitVector) const
2545{
2546 ocean_assert(zoom > NumericT<T>::eps());
2547
2548 const T invZoom = T(1) / zoom;
2549
2550#ifdef OCEAN_DEBUG
2551
2552 const VectorT3<T> testVector(VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX() * invZoom, (position(1) - principalPointY()) * inverseFocalLengthY() * invZoom, 1).normalized());
2553 ocean_assert(position.isEqual(projectToImageIF<false>(HomogenousMatrixT4<T>(true), testVector, false, zoom), T(0.01)));
2554
2555#endif
2556
2557 if (makeUnitVector)
2558 {
2559 return VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX() * invZoom, (position(1) - principalPointY()) * inverseFocalLengthY() * invZoom, 1).normalized();
2560 }
2561 else
2562 {
2563 return VectorT3<T>((position(0) - principalPointX()) * inverseFocalLengthX() * invZoom, (position(1) - principalPointY()) * inverseFocalLengthY() * invZoom, 1);
2564 }
2565}
2566
2567template <typename T>
2568inline LineT3<T> PinholeCameraT<T>::ray(const VectorT2<T>& position, const HomogenousMatrixT4<T>& world_T_camera, const T zoom) const
2569{
2570 ocean_assert(world_T_camera.isValid() && zoom > NumericT<T>::eps());
2571 ocean_assert((std::is_same<T, float>::value) || NumericT<T>::rad2deg((world_T_camera.rotation() * vector(position, zoom)).angle(world_T_camera.rotationMatrix(vector(position, zoom)))) <= T(0.01));
2572 ocean_assert(NumericT<T>::isEqual((world_T_camera.rotation() * vector(position, zoom)).length(), 1));
2573
2574 return LineT3<T>(world_T_camera.translation(), world_T_camera.rotationMatrix(vector(position, zoom)));
2575}
2576
2577template <typename T>
2578inline LineT3<T> PinholeCameraT<T>::ray(const VectorT2<T>& position, const VectorT3<T>& world_t_camera, const QuaternionT<T>& world_Q_camera, const T zoom) const
2579{
2580 ocean_assert(world_Q_camera.isValid() && zoom >= NumericT<T>::eps());
2581
2582 return LineT3<T>(world_t_camera, world_Q_camera * vector(position, zoom));
2583}
2584
2585template <typename T>
2587{
2588 /**
2589 * The calculation is identical to the multiplication between the inverted camera matrix and the position vector.
2590 *
2591 * Inverse camera matrix:
2592 * | 1/Fx 0 -mx/Fx |<br>
2593 * | 0 1/Fy -my/Fy |<br>
2594 * | 0 0 1 |<br>
2595 */
2596
2597 ocean_assert(NumericT<T>::isNotEqualEps(focalLengthX()));
2598 ocean_assert(NumericT<T>::isNotEqualEps(focalLengthY()));
2599
2600 const T inverseFocalLengthX = T(1) / focalLengthX();
2601 const T inverseFocalLengthY = T(1) / focalLengthY();
2602
2603 invertedIntrinsics_(0, 0) = inverseFocalLengthX;
2604 invertedIntrinsics_(1, 1) = inverseFocalLengthY;
2605 invertedIntrinsics_(0, 2) = - principalPointX() * inverseFocalLengthX;
2606 invertedIntrinsics_(1, 2) = - principalPointY() * inverseFocalLengthY;
2607 invertedIntrinsics_(2, 2) = 1;
2608
2609 ocean_assert(invertedIntrinsics_(1, 0) == 0);
2610 ocean_assert(invertedIntrinsics_(2, 0) == 0);
2611 ocean_assert(invertedIntrinsics_(0, 1) == 0);
2612 ocean_assert(invertedIntrinsics_(2, 1) == 0);
2613}
2614
2615template <typename T>
2616inline bool PinholeCameraT<T>::operator!=(const PinholeCameraT<T>& camera) const
2617{
2618 return !(*this == camera);
2619}
2620
2621template <typename T>
2623{
2624 return isValid();
2625}
2626
2627template <typename T>
2628template <bool tUseBorderDistortionIfOutside>
2629VectorT2<T> PinholeCameraT<T>::distortNormalized(const VectorT2<T>& undistortedNormalized, const T invZoom) const
2630{
2631 ocean_assert(invZoom > NumericT<T>::eps());
2632
2633 if (hasDistortionParameters())
2634 {
2635 if constexpr (tUseBorderDistortionIfOutside)
2636 {
2637 const VectorT2<T> clampedNormalizedImagePoint(minmax(-principalPointX() * inverseFocalLengthX() * invZoom, undistortedNormalized.x(), (T(width_) - principalPointX()) * inverseFocalLengthX() * invZoom),
2638 minmax(-principalPointY() * inverseFocalLengthY() * invZoom, undistortedNormalized.y(), (T(height_) - principalPointY()) * inverseFocalLengthY() * invZoom));
2639
2640 const T sqr = clampedNormalizedImagePoint.sqr();
2641
2642 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2643
2644 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y()
2645 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.x()));
2646
2647 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(clampedNormalizedImagePoint.y()))
2648 + tangentialDistortion_.second * 2 * clampedNormalizedImagePoint.x() * clampedNormalizedImagePoint.y();
2649
2650 return VectorT2<T>(undistortedNormalized.x() * radialDistortionFactor + tangentialDistortionCorrectionX,
2651 undistortedNormalized.y() * radialDistortionFactor + tangentialDistortionCorrectionY);
2652 }
2653 else
2654 {
2655 const T sqr = undistortedNormalized.sqr();
2656
2657 const T radialDistortionFactor = T(1) + radialDistortion_.first * sqr + radialDistortion_.second * NumericT<T>::sqr(sqr);
2658
2659 const T tangentialDistortionCorrectionX = tangentialDistortion_.first * 2 * undistortedNormalized.x() * undistortedNormalized.y()
2660 + tangentialDistortion_.second * (sqr + 2 * NumericT<T>::sqr(undistortedNormalized.x()));
2661
2662 const T tangentialDistortionCorrectionY = tangentialDistortion_.first * (sqr + 2 * NumericT<T>::sqr(undistortedNormalized.y()))
2663 + tangentialDistortion_.second * 2 * undistortedNormalized.x() * undistortedNormalized.y();
2664
2665 return VectorT2<T>(undistortedNormalized.x() * radialDistortionFactor + tangentialDistortionCorrectionX,
2666 undistortedNormalized.y() * radialDistortionFactor + tangentialDistortionCorrectionY);
2667 }
2668 }
2669 else
2670 {
2671 return undistortedNormalized;
2672 }
2673}
2674
2675}
2676
2677#endif // META_OCEAN_MATH_PINHOLE_CAMERA_H
This class implements an axis aligned 2D box object.
Definition Box2.h:68
This class implements an axis aligned 3D bounding box.
Definition Box3.h:67
bool isValid() const
Returns whether the bounding box is valid.
unsigned int corners(VectorT3< T > *corners) const
Returns the corner positions of this box.
This class implements the base class for all cameras.
Definition Camera.h:54
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
QuaternionT< T > rotation() const
Returns the rotation of the transformation as quaternion.
Definition HomogenousMatrix4.h:1388
This class implements an infinite line in 2D space.
Definition Line2.h:83
This class implements an infinite line in 3D space.
Definition Line3.h:68
bool isValid() const
Returns whether this line has valid parameters.
Definition Line3.h:301
const VectorT3< T > & point() const
Returns a point on the line.
Definition Line3.h:269
This class implements a 2D lookup object with values at the bins' center positions defining the indiv...
Definition Lookup2.h:198
This class provides basic numeric functionalities.
Definition Numeric.h:57
static T abs(const T value)
Returns the absolute value of a given value.
Definition Numeric.h:1220
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition Numeric.h:1495
This class encapsulates a lookup table for camera distortion offsets allowing for faster un-distortio...
Definition PinholeCamera.h:203
DistortionLookup(const PinholeCameraT< T > &camera, const unsigned int binSize)
Creates an lookup object for a given camera.
VectorT2< T > undistortionOffset(const VectorT2< T > &distortedImagePoint) const
Returns the offset that needs to be added to an distorted image point so that it would be undistorted...
Definition PinholeCamera.h:1306
VectorT2< T > undistortedImagePointBicubic(const VectorT2< T > &distortedImagePoint) const
Returns the undistorted image point for a given (distorted) image point (by application of a bicubic ...
Definition PinholeCamera.h:1313
VectorT2< T > undistortionOffsetBicubic(const VectorT2< T > &distortedImagePoint) const
Returns the offset that needs to be added to an distorted image point so that it would be undistorted...
Definition PinholeCamera.h:1320
VectorT2< T > undistortedImagePoint(const VectorT2< T > &distortedImagePoint) const
Returns the undistorted image point for a given (distorted) image point (by application of a bilinear...
Definition PinholeCamera.h:1299
DistortionLookup()
Creates an invalid lookup object.
Definition PinholeCamera.h:1293
LookupTable distortionLookupTable
The distortion lookup table.
Definition PinholeCamera.h:256
LookupCenter2< VectorT2< T >, T > LookupTable
Definition of a lookup table for 2D vectors.
Definition PinholeCamera.h:209
Definition of a pinhole camera model.
Definition PinholeCamera.h:114
std::pair< T, T > DistortionPair
Definition of a pair of distortion values.
Definition PinholeCamera.h:123
VectorT2< T > projectToImageIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const VectorT3< T > &worldObjectPoint, const T zoom=T(1)) const
Projects a 3D object point to the 2D image plane of the camera by a given inverse camera pose.
Definition PinholeCamera.h:2306
void setTangentialDistortion(const DistortionPair &tangential)
Sets the tangential distortion parameters.
Definition PinholeCamera.h:1518
VectorT2< T > imagePoint2normalizedImagePoint(const VectorT2< T > &imagePoint, const bool undistortImagePoint) const
Calculates the normalized image point corresponding to a given (distorted) image point.
Definition PinholeCamera.h:1769
unsigned int width() const
Returns the width of the camera image.
Definition PinholeCamera.h:1452
PinholeCameraT(const unsigned int width, const unsigned int height, const T focalX, const T focalY, const T principalX, const T principalY, const DistortionPair &radial, const DistortionPair &tangential)
Creates a new PinholeCameraT<T> object by it's given intrinsic parameters.
VectorT2< T > projectToImageDamped(const HomogenousMatrixT4< T > &extrinsic, const VectorT3< T > &objectPoint, const bool distortImagePoint, const T dampingFactor=T(1), const T zoom=T(1)) const
Projects a 3D object point to the 2D image plane of the camera by a given extrinsic camera matrix.
Definition PinholeCamera.h:2275
T fovYBottom() const
Returns the bottom field of view in y direction.
bool isEqual(const PinholeCameraT< T > &camera, const T eps=NumericT< T >::eps()) const
Returns whether two camera profiles are identical up to a given epsilon.
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 PinholeCamera.h:1659
T fovYTop() const
Returns the top field of view in y direction.
VectorT2< T > dampedNormalized(const VectorT2< T > &normalized, const T dampingFactor, const T invZoom) const
Determines the damped normalized coordinate for a given normalized coordinate.
PinholeCameraT(const unsigned int width, const unsigned int height, const T *parameters, const bool radialDistortion=true, const bool tangentialDistortion=true)
Creates a new PinholeCameraT<T> object by it's given intrinsic parameters.
T principalPointX() const
Returns the x-value of the principal point of the camera image in the pixel domain.
Definition PinholeCamera.h:1470
DistortionPair tangentialDistortion_
Pair of tangential distortion parameters.
Definition PinholeCamera.h:1289
PinholeCameraT()=default
Standard constructor.
const SquareMatrixT3< T > & invertedIntrinsic() const
Returns the inverted intrinsic camera matrix.
Definition PinholeCamera.h:1333
bool operator==(const PinholeCameraT< T > &camera) const
Returns whether two camera objects are identical up to a small epsilon.
VectorT2< T > principalPoint() const
Returns the coordinate of the principal point of the camera image in the pixel domain.
Definition PinholeCamera.h:1464
void copyParameters(unsigned int &width, unsigned int &height, std::vector< TParameter > &parameters, ParameterConfiguration &parameterConfiguration) const
Copies the parameters of this camera.
Definition PinholeCamera.h:1622
BoxT2< T > projectToImage(const HomogenousMatrixT4< T > &world_T_camera, const BoxT3< T > &worldObjectBox, const bool distortImagePoint, const T zoom=T(1)) const
Projects a 3D box to the 2D image plane of the camera by a given camera pose.
Definition PinholeCamera.h:1970
PinholeCameraT(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 PinholeCamera.h:1364
TriangleT2< T > projectToImageIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const TriangleT3< T > &worldObjectTriangle, const bool distortImagePoint, const T zoom=T(1)) const
Projects a 3D triangle to the 2D image plane of the camera by a given extrinsic camera pose.
Definition PinholeCamera.h:2080
VectorT2< T > projectToImageIF(const VectorT2< T > &normalizedObjectPoint, const bool distortImagePoint, const T zoom=T(1)) const
Transforms a normalized object point (a 3D object point transformed by the inverted and flipped extri...
Definition PinholeCamera.h:2092
bool isDistortionPlausible(const T symmetricFocalLengthRatio=T(1.05), const T modelAccuracy=T(0.001), const T symmetricDistortionRatio=T(1.08)) const
Checks whether the distortion of this camera is plausible.
VectorT2< T > dampedNormalized(const VectorT2< T > &normalized, const T dampingFactor, const T leftNormalizedBorder, const T rightNormalizedBorder, const T topNormalizedBorder, const T bottomNormalizedBorder) const
Determines the damped normalized coordinate for a given normalized coordinate.
LineT3< T > ray(const VectorT2< T > &position, const HomogenousMatrixT4< T > &world_T_camera, const T zoom=T(1)) const
Returns a ray starting at the camera's center and intersection a given 2D point on the image plane.
Definition PinholeCamera.h:2568
T fovXRight() const
Returns the right field of view in x direction.
BoxT2< T > projectToImageDamped(const HomogenousMatrixT4< T > &extrinsic, const BoxT3< T > &objectBox, const bool distortImagePoint, const T dampingFactor=T(1), const T zoom=T(1)) const
Projects a 3D box to the 2D image plane of the camera by a given inverse extrinsic camera matrix.
Definition PinholeCamera.h:2282
VectorT2< T > distortDamped(const VectorT2< T > &undistorted, const T dampingFactor=T(1), const T zoom=T(1)) const
Returns the distorted position of a given undistorted position defined in pixel coordinates.
VectorT2< T > distort(const VectorT2< T > &undistorted) const
Returns the distorted position of a given undistorted position defined in pixel coordinates.
Definition PinholeCamera.h:1570
LineT3< T > ray(const VectorT2< T > &position, const VectorT3< T > &world_t_camera, const QuaternionT< T > &world_Q_camera, const T zoom=T(1)) const
Returns a ray starting at the camera's center and intersection a given 2D point on the image plane.
Definition PinholeCamera.h:2578
PinholeCameraT(const unsigned int width, const unsigned int height, const T fovX, const T principalX, const T principalY)
Creates a new PinholeCameraT<T> object by the given frame dimensions, the ideal field of view,...
PinholeCameraT(const SquareMatrixT3< T > &intrinsic)
Creates a new PinholeCameraT<T> object by a given projection matrix with the intrinsic camera paramet...
VectorT2< T > distortNormalized(const VectorT2< T > &undistortedNormalized, const T invZoom) const
Returns the distorted position of a given undistorted normalized position.
Definition PinholeCamera.h:2629
BoxT2< T > projectToImageDampedIF(const HomogenousMatrixT4< T > &iFlippedExtrinsic, const BoxT3< T > &objectBox, const bool distortImagePoint, const T dampingFactor=T(1), const T zoom=T(1)) const
Projects a 3D box to the 2D image plane of the camera by a given inverse extrinsic camera matrix.
VectorT2< T > undistort(const VectorT2< T > &distorted, const unsigned int iterations=10u, const T zoom=T(1)) const
Returns the undistorted position of a given distorted position defined in pixel coordinates.
Definition PinholeCamera.h:1525
bool isValid() const
Returns whether this camera is valid.
Definition PinholeCamera.h:1762
VectorT3< T > vectorToPlane(const VectorT2< T > &position, const T distance, const T zoom) const
Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane...
Definition PinholeCamera.h:2492
void setRadialDistortion(const DistortionPair &radial)
Sets the radial distortion parameters.
Definition PinholeCamera.h:1512
BoxT2< T > projectToImageIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const BoxT3< T > &worldObjectBox, const bool distortImagePoint, const T zoom=T(1)) const
Projects a 3D box to the 2D image plane of the camera by a given inverse camera pose.
Definition PinholeCamera.h:2061
T focalLengthY() const
Returns the vertical focal length parameter.
Definition PinholeCamera.h:1488
SquareMatrixT3< T > invertedIntrinsics_
Inverted intrinsic camera matrix.
Definition PinholeCamera.h:1283
PinholeCameraT(const PinholeCameraT< U > &pinholeCamera, const bool copyDistortionParameters=true)
Copy constructor for a pinhole camera with difference element data type than T.
Definition PinholeCamera.h:1352
bool hasDistortionParameters() const
Returns whether this camera object has specified distortion parameters.
Definition PinholeCamera.h:1445
VectorT2< T > projectToImageDampedIF(const HomogenousMatrixT4< T > &iFlippedExtrinsic, const VectorT3< T > &objectPoint, const bool distortImagePoint, const T dampingFactor=T(1), const T zoom=T(1)) const
Projects a 3D object point to the 2D image plane of the camera by a given inverse extrinsic camera ma...
const SquareMatrixT3< T > & intrinsic() const
Returns the intrinsic camera matrix.
Definition PinholeCamera.h:1327
T calculateCosBetween(const VectorT2< T > &first, const VectorT2< T > &second) const
Returns the cosine of the viewing angle between two undistorted points on the camera's image plane.
TriangleT2< T > projectToImageDamped(const HomogenousMatrixT4< T > &extrinsic, const TriangleT3< T > &objectTriangle, const bool distortImagePoint, const T dampingFactor=T(1), const T zoom=T(1)) const
Projects a 3D triangle to the 2D image plane of the camera by a given extrinsic camera matrix.
Definition PinholeCamera.h:2289
PinholeCameraT(const unsigned int width, const unsigned int height, const T focalX, const T focalY, const T principalX, const T principalY)
Creates a new PinholeCameraT<T> object by it's given intrinsic parameters.
void calculateInverseIntrinsic()
Determines the inverse of the intrinsic camera matrix.
Definition PinholeCamera.h:2586
void projectToImageDamped(const HomogenousMatrixT4< T > &extrinsic, const VectorT3< T > *objectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2< T > *imagePoints, const T dampingFactor=T(1), const T zoom=T(1)) const
Projects a set of 3D object points onto an image plane of the camera by a given extrinsic camera matr...
Definition PinholeCamera.h:2296
VectorT3< T > vectorToPlane(const VectorT2< T > &position, const T distance) const
Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane...
Definition PinholeCamera.h:2463
bool rotation(const VectorT2< T > &undistortedPosition, T &angleX, T &angleY) const
Gets two rotation parameters of the viewing ray for a given undistorted 2D position in the camera ima...
T fovY() const
Returns the field of view in x direction of the camera.
SquareMatrixT3< T > intrinsics_
Intrinsic camera matrix.
Definition PinholeCamera.h:1280
T fovDiagonal() const
Returns the diagonal field of view of the camera.
SquareMatrixT4< T > frustumMatrix(const T nearDistance, const T farDistance) const
Returns the 4x4 frustum projection matrix corresponding to this camera.
HomogenousMatrixT4< T > transformationMatrixIF(const HomogenousMatrixT4< T > &iFlippedExtrinsic, const T zoom=T(1)) const
Returns a 4x4 homogeneous transformation matrix (corresponding to a 3x4 matrix) that covers an extrin...
Definition PinholeCamera.h:1669
void normalizedImagePoints2imagePoints(const VectorT2< T > *normalizedImagePoints, const size_t numberNormalizedImagePoints, const bool distortImagePoints, VectorT2< T > *imagePoints) const
Calculates the image points corresponding to a set of given normalized image points.
Definition PinholeCamera.h:1866
T TScalar
The scalar data type of this object.
Definition PinholeCamera.h:120
VectorT3< T > vectorIF(const VectorT2< T > &position, 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 PinholeCamera.h:2525
OptimizationStrategy
Definition of individual optimization strategies for camera parameters.
Definition PinholeCamera.h:178
unsigned int height() const
Returns the height of the camera image.
Definition PinholeCamera.h:1458
const DistortionPair & radialDistortion() const
Returns the pair of radial distortion parameters.
Definition PinholeCamera.h:1339
DistortionPair radialDistortion_
Pair of radial distortion parameters for r^2 and r^4.
Definition PinholeCamera.h:1286
TriangleT2< T > projectToImage(const HomogenousMatrixT4< T > &world_T_camera, const TriangleT3< T > &worldObjectTriangle, const bool distortImagePoint, const T zoom=T(1)) const
Projects a 3D triangle to the 2D image plane of the camera by a given camera pose.
Definition PinholeCamera.h:1978
VectorT3< T > vectorIF(const VectorT2< T > &position, const T zoom, const bool makeUnitVector) const
Returns a vector starting at the camera's center and intersecting a given 2D point on the image plane...
Definition PinholeCamera.h:2544
void applyZoomFactor(const T relativeZoom)
Applies a given (relative) zoom factor which mainly multiplies the focal length parameters by the giv...
T inverseFocalLengthX() const
Returns the inverse horizontal focal length parameter.
Definition PinholeCamera.h:1494
PinholeCameraT(const SquareMatrixT3< T > &intrinsic, const unsigned int width, const unsigned int height)
Creates a new PinholeCameraT<T> object by the given intrinsic camera matrix and width and height of t...
PinholeCameraT(const unsigned int width, const unsigned int height, const T fovX)
Creates a new PinholeCameraT<T> object by the given width, height and field of view of a camera.
const DistortionPair & tangentialDistortion() const
Returns the pair of tangential distortion parameters.
Definition PinholeCamera.h:1345
VectorT2< T > normalizedImagePoint2imagePoint(const VectorT2< T > &normalizedImagePoint, const bool distortImagePoint) const
Calculates the image point corresponding to a given normalized image point.
Definition PinholeCamera.h:1792
VectorT2< T > distortNormalizedDamped(const VectorT2< T > &undistortedNormalized, const T dampingFactor, const T invZoom) const
Returns the distorted position of a given undistorted normalized position.
void copyElements(T *arrayValues, const bool copyRadialDistortion=true, const bool copyTangentialDistortion=true) const
Copies the elements of this camera to an array with 4 to 8 floating point values.
void projectToImageDampedIF(const HomogenousMatrixT4< T > &invertedFlippedExtrinsic, const VectorT3< T > *objectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2< T > *imagePoints, const T dampingFactor=T(1), const T zoom=T(1)) const
Projects a set of 3D object points onto an image plane of the camera by a given inverse extrinsic cam...
ParameterConfiguration
Definition of individual parameter configurations.
Definition PinholeCamera.h:129
@ PC_7_PARAMETERS_ONE_FOCAL_LENGTH
7 parameters with order: focal length (one identical value for horizontal and vertical direction),...
Definition PinholeCamera.h:160
@ PC_3_PARAMETERS_ONE_FOCAL_LENGTH
3 parameters with order: focal length (one identical value for horizontal and vertical direction),...
Definition PinholeCamera.h:141
@ PC_4_PARAMETERS
4 parameters with order: horizontal focal length, vertical focal length, horizontal principal point,...
Definition PinholeCamera.h:150
VectorT2< T > projectToImageIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const VectorT3< T > &objectPoint, const bool distortImagePoint, const T zoom=T(1)) const
Projects a 3D object point to the 2D image plane of the camera by a given inverse camera pose.
Definition PinholeCamera.h:2006
T principalPointY() const
Returns the y-value of the principal point of the camera image in the pixel domain.
Definition PinholeCamera.h:1476
LineT2< T > projectToImage(const HomogenousMatrixT4< T > &world_T_camera, const LineT3< T > &worldLine, const bool distortProjectedLine, const T zoom=T(1)) const
Projects a 3D line onto an image plane of the camera by a given camera pose.
Definition PinholeCamera.h:1996
T fovX() const
Returns the field of view in x direction of the camera.
T calculateAngleBetween(const VectorT2< T > &first, const VectorT2< T > &second) const
Returns the viewing angle between two undistorted points on the camera's image plane.
VectorT2< T > undistortDamped(const VectorT2< T > &distorted, const T dampingFactor=T(1), const unsigned int iterations=10u, const T zoom=T(1)) const
Returns the undistorted position of a given distorted position defined in pixel coordinates.
PinholeCameraT(const unsigned int width, const unsigned int height, const PinholeCameraT< T > &camera)
Creates a new camera object with specified frame dimension and intrinsic camera parameters best match...
bool operator!=(const PinholeCameraT< T > &camera) const
Returns whether two camera objects are not identical up to a small epsilon.
Definition PinholeCamera.h:2616
PinholeCameraT(const SquareMatrixT3< T > &intrinsic, const unsigned int width, const unsigned int height, const DistortionPair &radial, const DistortionPair &tangential)
Creates a new PinholeCameraT<T> object by the given intrinsic camera matrix, the width and height and...
T fovXLeft() const
Returns the left field of view in x direction.
T inverseFocalLengthY() const
Returns the inverse vertical focal length parameter.
Definition PinholeCamera.h:1503
VectorT3< T > vector(const VectorT2< T > &position, const T zoom, 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 PinholeCamera.h:2410
bool setIntrinsic(const SquareMatrixT3< T > &intrinsic)
Sets the intrinsic camera matrix.
VectorT2< T > imagePoint2normalizedImagePointDamped(const VectorT2< T > &imagePoint, const bool undistortImagePoint) const
Calculates the normalized image point corresponding to a given (distorted) image point.
Definition PinholeCamera.h:1780
PinholeCameraT(const T subFrameLeft, const T subFrameTop, const unsigned int subFrameWidth, const unsigned int subFrameHeight, const PinholeCameraT< T > &camera)
Creates a new sub-frame camera profile based on a camera profile of the entire camera frame.
LineT2< T > projectToImageIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const LineT3< T > &worldLine, const bool distortProjectedLine, const T zoom=T(1)) const
Projects a 3D line onto an image plane of the camera by a given inverse camera pose.
Definition PinholeCamera.h:2258
void pointJacobian2x3IF(const VectorT3< U > &flippedCameraObjectPoint, U *jx, U *jy) const
Calculates the 2x3 jacobian matrix for the 3D object point projection into the camera frame.
Definition PinholeCamera.h:1693
void projectToImageIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const VectorT3< T > *worldObjectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2< T > *imagePoints, const T zoom=T(1)) const
Projects a set of 3D object points onto an image plane of the camera by a given inverse camera pose.
Definition PinholeCamera.h:2142
friend class PinholeCameraT
Definition PinholeCamera.h:115
TriangleT2< T > projectToImageDampedIF(const HomogenousMatrixT4< T > &iFlippedExtrinsic, const TriangleT3< T > &objectTriangle, const bool distortImagePoint, const T dampingFactor=T(1), const T zoom=T(1)) const
Projects a 3D triangle to the 2D image plane of the camera by a given inverse extrinsic camera matrix...
void projectToImage(const HomogenousMatrixT4< T > &world_T_camera, const VectorT3< T > *worldObjectPoints, const size_t numberObjectPoints, const bool distortImagePoints, VectorT2< T > *imagePoints, const T zoom=T(1)) const
Projects a set of 3D object points onto an image plane of the camera by a given camera pose.
Definition PinholeCamera.h:1986
VectorT2< T > projectToImage(const HomogenousMatrixT4< T > &world_T_camera, const VectorT3< T > &worldObjectPoint, const bool distortImagePoint, const T zoom=T(1)) const
Projects a 3D object point to the 2D image plane of the camera by a given camera pose.
Definition PinholeCamera.h:1962
T focalLengthX() const
Returns the horizontal focal length parameter.
Definition PinholeCamera.h:1482
VectorT3< T > vector(const VectorT2< T > &position, 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 PinholeCamera.h:2361
This class implements a unit quaternion rotation.
Definition Quaternion.h:100
bool isValid() const
Returns whether this quaternion is a valid unit quaternion.
Definition Quaternion.h:901
This class implements a 3x3 square matrix.
Definition SquareMatrix3.h:88
SquareMatrixT3< T > inverted() const
Returns the inverted matrix of this matrix.
Definition SquareMatrix3.h:1176
This class implements a 4x4 square matrix.
Definition SquareMatrix4.h:85
This class implements a 2D triangle with Cartesian coordinates.
Definition Triangle2.h:81
This class implements a 3D triangle.
Definition Triangle3.h:80
const VectorT3< T > & point0() const
Returns the first point of this triangle.
Definition Triangle3.h:278
bool isValid() const
Returns whether this triangle is valid.
Definition Triangle3.h:580
const VectorT3< T > & point2() const
Returns the third point of this triangle.
Definition Triangle3.h:290
const VectorT3< T > & point1() const
Returns the second point of this triangle.
Definition Triangle3.h:284
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
bool isEqual(const VectorT2< T > &vector, const T eps) const
Returns whether two vectors are equal up to a specified epsilon.
Definition Vector2.h:758
T sqr() const
Returns the square of the vector length.
Definition Vector2.h:633
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
T length() const
Returns the length of the vector.
Definition Vector3.h:676
T minmax(const T &lowerBoundary, const T &value, const T &upperBoundary)
This function fits a given parameter into a specified value range.
Definition base/Utilities.h:927
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition base/Utilities.h:1053
PinholeCameraT< double > PinholeCameraD
Definition of an pinhole camera object with double precision.
Definition PinholeCamera.h:46
PinholeCameraT< float > PinholeCameraF
Definition of an pinhole camera object with float precision.
Definition PinholeCamera.h:53
PinholeCamerasT< double > PinholeCamerasD
Definition of a vector holding PinholeCameraD objects.
Definition PinholeCamera.h:75
PinholeCamerasT< Scalar > PinholeCameras
Definition of a vector holding pinhole camera objects.
Definition PinholeCamera.h:68
std::vector< PinholeCameraT< T > > PinholeCamerasT
Definition of a typename alias for vectors with PinholeCameraT objects.
Definition PinholeCamera.h:61
PinholeCameraT< Scalar > PinholeCamera
Definition of an pinhole camera object with Scalar precision.
Definition PinholeCamera.h:39
PinholeCamerasT< float > PinholeCamerasF
Definition of a vector holding PinholeCameraF objects.
Definition PinholeCamera.h:82
The namespace covering the entire Ocean framework.
Definition Accessor.h:15