Ocean
Loading...
Searching...
No Matches
PoseProjection.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_TRACKING_POSE_PROJECTION_H
9#define META_OCEAN_TRACKING_POSE_PROJECTION_H
10
12
13#include "ocean/base/Worker.h"
14
16
18
21
24
25#include <algorithm>
26
27namespace Ocean
28{
29
30namespace Tracking
31{
32
33/**
34 * This class implements a pose projection.
35 * @ingroup tracking
36 */
37class OCEAN_TRACKING_EXPORT PoseProjection
38{
39 public:
40
41 /**
42 * Creates an empty pose projection object.
43 */
44 PoseProjection() = default;
45
46 /**
47 * Creates a new pose projection object by a given pose and object points.
48 * @param world_T_camera The transformation between camera and world, with default camera looking into the negative z-space with y-axis up, must be valid
49 * @param camera The camera object defining the projection
50 * @param objectPoints Object points to be projected
51 * @param number Number Of object points to be projected
52 */
53 PoseProjection(const HomogenousMatrix4& world_T_camera, const AnyCamera& camera, const Geometry::ObjectPoint* objectPoints, const size_t number);
54
55 /**
56 * Returns the pose of this projection.
57 * @return Projection pose
58 */
59 inline const HomogenousMatrix4& world_T_camera() const;
60
61 /**
62 * Returns the image points (the projected object points) of this pose projection.
63 * @return Pose image points
64 */
65 inline const Geometry::ImagePoints& imagePoints() const;
66
67 /**
68 * Returns the number of stored pose points.
69 * @return Pose points
70 */
71 inline size_t size() const;
72
73 /**
74 * Returns the robust minimal average square error between this pose projection and a given 2D point cloud.
75 * The number of given image points must be equal or small to the number of internal pose points of this object.
76 * @param imagePoints Image points to find corresponding pose points for
77 * @param numberImagePoints Number of given image points
78 * @param validImagePoints Number of valid image points expecting to have corresponding points in the pose points, with range [1, numberImagePoints]
79 * @param errorDetermination Depending on this flag uniqueAveragedRobustErrorInPointCloud, approximatedAveragedRobustErrorInPointCloud() or ambiguousAveragedRobustErrorInPointCloud() will be used
80 * @return Resulting minimal average square error
81 * @tparam tEstimator Estimator to be applied
82 */
83 template <Geometry::Estimator::EstimatorType tEstimator>
84 Scalar minimalAverageSquareError(const Geometry::ImagePoint* imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination);
85
86 /**
87 * Returns whether this pose projection holds no points.
88 * @return True, if so
89 */
90 inline bool isEmpty() const;
91
92 /**
93 * Returns whether this pose projection holds at least one point.
94 * @return True, if so
95 */
96 explicit inline operator bool() const;
97
98 private:
99
100 /**
101 * Converts an element to an object point.
102 * @param element Element to be converted
103 * @return Converted object point
104 */
105 static inline const Vector3& objectPoint2objectPoint(const Geometry::ObjectPoint& element);
106
107 private:
108
109 /// Pose of this projection.
110 HomogenousMatrix4 world_T_camera_ = HomogenousMatrix4(false);
111
112 /// Projection object points for this pose.
114};
115
116/**
117 * This class implements a set of pose projections.
118 * @ingroup tracking
119 */
120 class OCEAN_TRACKING_EXPORT PoseProjectionSet
121 {
122 public:
123
124 /**
125 * Definition of a vector holding pose projections.
126 */
127 using PoseProjections = std::vector<PoseProjection>;
128
129 /**
130 * This class implements a error object.
131 */
133 {
134 public:
135
136 /**
137 * Creates a new error object.
138 * @param index Index of the element
139 * @param error Error of the element
140 */
141 inline ErrorObject(const unsigned int index, const Scalar error);
142
143 /**
144 * Returns the index of this object.
145 * @return Object index
146 */
147 inline unsigned int index() const;
148
149 /**
150 * Returns the error of this object.
151 * @return Object error
152 */
153 inline Scalar error() const;
154
155 /**
156 * Returns whether the left object has a lesser error value than the right one.
157 * @param object Right error object to compare
158 * @return True, if so
159 */
160 inline bool operator<(const ErrorObject& object) const;
161
162 private:
163
164 /// Object index.
165 unsigned int objectIndex;
166
167 /// Object error.
169 };
170
171 /**
172 * Definition of a vector holding error objects.
173 */
174 using ErrorObjects = std::vector<ErrorObject>;
175
176 public:
177
178 /**
179 * Creates an empty set of pose projections.
180 */
181 PoseProjectionSet() = default;
182
183 /**
184 * Destructs a set of pose projections.
185 */
187
188 /**
189 * Returns the width of the camera in pixel used for all projections.
190 * @return The camera width in pixels
191 * @see height().
192 */
193 inline unsigned int width() const;
194
195 /**
196 * Returns the height of the camera in pixel used for all projections.
197 * @return The camera height in pixels
198 * @see width().
199 */
200 inline unsigned int height() const;
201
202 /**
203 * Adds a new pose projection.
204 * @param poseProjection Pose projection to be added
205 */
206 inline void addPoseProjection(const PoseProjection& poseProjection);
207
208 /**
209 * Returns the registered pose projections.
210 * @return Pose projections
211 */
212 inline const PoseProjections& poseProjections() const;
213
214 /**
215 * Returns the number of registered pose projections.
216 * @return Pose projection number
217 */
218 inline size_t size() const;
219
220 /**
221 * Sets the dimension of the camera used for all pose projections.
222 * @param width The camera width in pixel
223 * @param height The camera height in pixel
224 * @see width(), height().
225 */
226 inline void setDimension(const unsigned int width, const unsigned int height);
227
228 /**
229 * Clears the projection set.
230 */
231 void clear();
232
233 /**
234 * Returns the pose with the minimal distance error.
235 * The number of given image points must be equal or small to the number of internal pose points of this object.
236 * @param imagePoints Image points to find corresponding pose points for
237 * @param numberImagePoints Number of given image points
238 * @param validImagePoints Number of valid image points expecting to have corresponding points in the pose points, with range [1, numberImagePoints]
239 * @param errorDetermination Depending on this flag uniqueAveragedRobustErrorInPointCloud, approximatedAveragedRobustErrorInPointCloud() or ambiguousAveragedRobustErrorInPointCloud() will be used
240 * @param resultingError Optional resulting minimal average square error
241 * @param worker Optional worker object to distribute the computation
242 * @return Pose with minimal error
243 * @tparam tEstimator Estimator to be applied
244 */
245 template <Geometry::Estimator::EstimatorType tEstimator>
246 inline HomogenousMatrix4 findPoseWithMinimalError(const Geometry::ImagePoint* imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, Scalar* resultingError = nullptr, Worker* worker = nullptr);
247
248 /**
249 * Returns the poses with the minimal distance error.
250 * The number of given image points must be equal or small to the number of internal pose points of this object.
251 * @param imagePoints Image points to find corresponding pose points for
252 * @param numberImagePoints Number of given image points
253 * @param validImagePoints Number of valid image points expecting to have corresponding points in the pose points, with range [1, numberImagePoints]
254 * @param errorDetermination Depending on this flag uniqueAveragedRobustErrorInPointCloud, approximatedAveragedRobustErrorInPointCloud() or ambiguousAveragedRobustErrorInPointCloud() will be used
255 * @param numberPoses Number of poses to be found
256 * @param poses Resulting poses, make sure that the memory block provides enough space
257 * @param resultingErrors Optional resulting minimal average square errors individual for each returned pose, make sure that the memory block provides enough space
258 * @param worker Optional worker object to distribute the computation
259 * @return Number of found best poses
260 * @tparam tEstimator Estimator to be applied
261 */
262 template <Geometry::Estimator::EstimatorType tEstimator>
263 unsigned int findPosesWithMinimalError(const Geometry::ImagePoint* imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, const size_t numberPoses, HomogenousMatrix4* poses, Scalar* resultingErrors = nullptr, Worker* worker = nullptr);
264
265 /**
266 * Returns whether this set holds no pose projections.
267 * @return True, if so
268 */
269 inline bool isEmpty() const;
270
271 /**
272 * Returns whether this set holds at least one pose projection.
273 * @return True, if so
274 */
275 explicit inline operator bool() const;
276
277 private:
278
279 /**
280 * Returns the pose with the minimal distance error for a subset of the pose projections.
281 * @param imagePoints Image points to find corresponding pose points for
282 * @param numberImagePoints Number of given image points
283 * @param validImagePoints Number of valid image points expecting to have corresponding points in the pose points, with range [1, numberImagePoints]
284 * @param errorDetermination Depending on this flag uniqueAveragedRobustErrorInPointCloud, approximatedAveragedRobustErrorInPointCloud() or ambiguousAveragedRobustErrorInPointCloud() will be used
285 * @param errorObjects Error objects receiving the estimated error values
286 * @param firstProjection First projection to be handled
287 * @param numberProjections Number of projections to be handled
288 * @tparam tEstimator Estimator to be applied
289 */
290 template <Geometry::Estimator::EstimatorType tEstimator>
291 void findPoseWithMinimalErrorSubset(const Geometry::ImagePoint* imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, ErrorObject* errorObjects, const unsigned int firstProjection, const unsigned int numberProjections);
292
293 private:
294
295 /// All registered pose projections.
297
298 /// Width of the camera in pixel used for all pose projections
299 unsigned int cameraWidth_ = 0u;
300
301 /// Height of the camera in pixel used for all pose projections
302 unsigned int cameraHeight_ = 0u;
303};
304
306{
307 return objectPoint;
308}
309
311{
312 return world_T_camera_;
313}
314
316{
317 return imagePoints_;
318}
319
320inline size_t PoseProjection::size() const
321{
322 return imagePoints_.size();
323}
324
325inline bool PoseProjection::isEmpty() const
326{
327 return imagePoints_.empty();
328}
329
330inline PoseProjection::operator bool() const
331{
332 return !imagePoints_.empty();
333}
334
335inline unsigned int PoseProjectionSet::width() const
336{
337 return cameraWidth_;
338}
339
340inline unsigned int PoseProjectionSet::height() const
341{
342 return cameraHeight_;
343}
344
345inline void PoseProjectionSet::setDimension(const unsigned int width, const unsigned int height)
346{
349}
350
351inline void PoseProjectionSet::addPoseProjection(const PoseProjection& poseProjection)
352{
353 poseProjections_.push_back(poseProjection);
354}
355
360
361inline size_t PoseProjectionSet::size() const
362{
363 return poseProjections_.size();
364}
365
366inline bool PoseProjectionSet::isEmpty() const
367{
368 return poseProjections_.empty();
369}
370
371inline PoseProjectionSet::operator bool() const
372{
373 return !poseProjections_.empty();
374}
375
376inline PoseProjectionSet::ErrorObject::ErrorObject(const unsigned int index, const Scalar error) :
377 objectIndex(index),
378 objectError(error)
379{
380 // nothing to do here
381}
382
383inline unsigned int PoseProjectionSet::ErrorObject::index() const
384{
385 return objectIndex;
386}
387
389{
390 return objectError;
391}
392
394{
395 return objectError < element.objectError;
396}
397
398template <Geometry::Estimator::EstimatorType tEstimator>
399Scalar PoseProjection::minimalAverageSquareError(const Geometry::ImagePoint* imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination)
400{
401 if (isEmpty())
402 {
403 return Numeric::maxValue();
404 }
405
406 const size_t points = min(size(), numberImagePoints);
407 const size_t validPoints = min(validImagePoints, points);
408
409 return Geometry::Error::averagedRobustErrorInPointCloud<tEstimator>(imagePoints, points, validPoints, imagePoints_.data(), size(), errorDetermination);
410}
411
412template <Geometry::Estimator::EstimatorType tEstimator>
413HomogenousMatrix4 PoseProjectionSet::findPoseWithMinimalError(const Geometry::ImagePoint* imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, Scalar* resultingError, Worker* worker)
414{
415 ocean_assert(!isEmpty());
416
417 if (isEmpty())
418 {
419 return HomogenousMatrix4();
420 }
421
422 ErrorObjects errorObjects(poseProjections_.size(), ErrorObject(0xFFFFFFFF, Numeric::maxValue()));
423
424 if (worker)
425 {
426 worker->executeFunction(Worker::Function::create(*this, &PoseProjectionSet::findPoseWithMinimalErrorSubset<tEstimator>, imagePoints, numberImagePoints, validImagePoints, errorDetermination, errorObjects.data(), 0u, 0u), 0u, size(), 5u, 6u);
427 }
428 else
429 {
430 findPoseWithMinimalErrorSubset<tEstimator>(imagePoints, numberImagePoints, validImagePoints, errorDetermination, errorObjects.data(), 0u, (unsigned int)(size()));
431 }
432
433 std::sort(errorObjects.begin(), errorObjects.end());
434
435 if (resultingError != nullptr)
436 {
437 *resultingError = errorObjects.front().error();
438 }
439
440 ocean_assert(errorObjects.front().index() < poseProjections_.size());
441 return poseProjections_[errorObjects.front().index()].world_T_camera();
442}
443
444template <Geometry::Estimator::EstimatorType tEstimator>
445unsigned int PoseProjectionSet::findPosesWithMinimalError(const Geometry::ImagePoint* imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, const size_t numberPoses, HomogenousMatrix4* poses, Scalar* resultingErrors, Worker* worker)
446{
447 ocean_assert(poses);
448
449 if (isEmpty() || numberPoses == 0)
450 {
451 return 0;
452 }
453
454 ErrorObjects errorObjects(poseProjections_.size(), ErrorObject(0xFFFFFFFF, Numeric::maxValue()));
455
456 if (worker)
457 {
458 worker->executeFunction(Worker::Function::create(*this, &PoseProjectionSet::findPoseWithMinimalErrorSubset<tEstimator>, imagePoints, numberImagePoints, validImagePoints, errorDetermination, errorObjects.data(), 0u, 0u), 0u, (unsigned int)size(), 5u, 6u);
459 }
460 else
461 {
462 findPoseWithMinimalErrorSubset<tEstimator>(imagePoints, numberImagePoints, validImagePoints, errorDetermination, errorObjects.data(), 0u, (unsigned int)size());
463 }
464
465 // **NOTE** We should seek a slightly larger set of best matching poses as we should try to find good poses but also different poses
466 // **NOTE** We should think about the application of more suitable data structures like KD-Trees to improve the performance
467
468 std::sort(errorObjects.begin(), errorObjects.end());
469
470 const size_t results = min(numberPoses, errorObjects.size());
471
472 for (size_t n = 0; n < results; ++n)
473 {
474 poses[n] = poseProjections_[errorObjects[n].index()].world_T_camera();
475
476 if (resultingErrors)
477 {
478 resultingErrors[n] = errorObjects[n].error();
479 }
480 }
481
482 return (unsigned int)(results);
483}
484
485template <Geometry::Estimator::EstimatorType tEstimator>
486void PoseProjectionSet::findPoseWithMinimalErrorSubset(const Geometry::ImagePoint* imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, ErrorObject* errorObjects, const unsigned int firstProjection, const unsigned int numberProjections)
487{
488 ocean_assert(imagePoints);
489 ocean_assert(errorObjects);
490
491 ocean_assert(firstProjection + numberProjections <= poseProjections_.size());
492
493 for (unsigned int n = firstProjection; n < firstProjection + numberProjections; ++n)
494 {
495 const Scalar errorValue = poseProjections_[n].minimalAverageSquareError<tEstimator>(imagePoints, numberImagePoints, validImagePoints, errorDetermination);
496 errorObjects[n] = ErrorObject(n, errorValue);
497 }
498}
499
500}
501
502}
503
504#endif // META_OCEAN_TRACKING_POSE_PROJECTION_H
This class implements the abstract base class for all AnyCamera objects.
Definition AnyCamera.h:131
static Caller< void > create(CT &object, typename MemberFunctionPointerMaker< CT, void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a member function with no function parameter.
Definition Caller.h:3024
ErrorDetermination
Definition of different error determination stages.
Definition Error.h:41
static constexpr T maxValue()
Returns the max scalar value.
Definition Numeric.h:3253
This class implements a pose projection.
Definition PoseProjection.h:38
Scalar minimalAverageSquareError(const Geometry::ImagePoint *imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination)
Returns the robust minimal average square error between this pose projection and a given 2D point clo...
Definition PoseProjection.h:399
PoseProjection()=default
Creates an empty pose projection object.
PoseProjection(const HomogenousMatrix4 &world_T_camera, const AnyCamera &camera, const Geometry::ObjectPoint *objectPoints, const size_t number)
Creates a new pose projection object by a given pose and object points.
const Geometry::ImagePoints & imagePoints() const
Returns the image points (the projected object points) of this pose projection.
Definition PoseProjection.h:315
size_t size() const
Returns the number of stored pose points.
Definition PoseProjection.h:320
HomogenousMatrix4 world_T_camera_
Pose of this projection.
Definition PoseProjection.h:110
Vectors2 imagePoints_
Projection object points for this pose.
Definition PoseProjection.h:113
bool isEmpty() const
Returns whether this pose projection holds no points.
Definition PoseProjection.h:325
static const Vector3 & objectPoint2objectPoint(const Geometry::ObjectPoint &element)
Converts an element to an object point.
Definition PoseProjection.h:305
const HomogenousMatrix4 & world_T_camera() const
Returns the pose of this projection.
Definition PoseProjection.h:310
This class implements a error object.
Definition PoseProjection.h:133
bool operator<(const ErrorObject &object) const
Returns whether the left object has a lesser error value than the right one.
Definition PoseProjection.h:393
unsigned int objectIndex
Object index.
Definition PoseProjection.h:165
Scalar error() const
Returns the error of this object.
Definition PoseProjection.h:388
Scalar objectError
Object error.
Definition PoseProjection.h:168
ErrorObject(const unsigned int index, const Scalar error)
Creates a new error object.
Definition PoseProjection.h:376
unsigned int index() const
Returns the index of this object.
Definition PoseProjection.h:383
This class implements a set of pose projections.
Definition PoseProjection.h:121
HomogenousMatrix4 findPoseWithMinimalError(const Geometry::ImagePoint *imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, Scalar *resultingError=nullptr, Worker *worker=nullptr)
Returns the pose with the minimal distance error.
Definition PoseProjection.h:413
unsigned int cameraWidth_
Width of the camera in pixel used for all pose projections.
Definition PoseProjection.h:299
PoseProjectionSet()=default
Creates an empty set of pose projections.
std::vector< PoseProjection > PoseProjections
Definition of a vector holding pose projections.
Definition PoseProjection.h:127
const PoseProjections & poseProjections() const
Returns the registered pose projections.
Definition PoseProjection.h:356
~PoseProjectionSet()
Destructs a set of pose projections.
unsigned int cameraHeight_
Height of the camera in pixel used for all pose projections.
Definition PoseProjection.h:302
std::vector< ErrorObject > ErrorObjects
Definition of a vector holding error objects.
Definition PoseProjection.h:174
unsigned int findPosesWithMinimalError(const Geometry::ImagePoint *imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, const size_t numberPoses, HomogenousMatrix4 *poses, Scalar *resultingErrors=nullptr, Worker *worker=nullptr)
Returns the poses with the minimal distance error.
Definition PoseProjection.h:445
bool isEmpty() const
Returns whether this set holds no pose projections.
Definition PoseProjection.h:366
void setDimension(const unsigned int width, const unsigned int height)
Sets the dimension of the camera used for all pose projections.
Definition PoseProjection.h:345
void findPoseWithMinimalErrorSubset(const Geometry::ImagePoint *imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Geometry::Error::ErrorDetermination errorDetermination, ErrorObject *errorObjects, const unsigned int firstProjection, const unsigned int numberProjections)
Returns the pose with the minimal distance error for a subset of the pose projections.
Definition PoseProjection.h:486
void clear()
Clears the projection set.
void addPoseProjection(const PoseProjection &poseProjection)
Adds a new pose projection.
Definition PoseProjection.h:351
unsigned int width() const
Returns the width of the camera in pixel used for all projections.
Definition PoseProjection.h:335
PoseProjections poseProjections_
All registered pose projections.
Definition PoseProjection.h:296
size_t size() const
Returns the number of registered pose projections.
Definition PoseProjection.h:361
unsigned int height() const
Returns the height of the camera in pixel used for all projections.
Definition PoseProjection.h:340
This class implements a worker able to distribute function calls over different threads.
Definition Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
std::vector< ImagePoint > ImagePoints
Definition of a vector holding 2D image points.
Definition geometry/Geometry.h:123
std::vector< Vector2 > Vectors2
Definition of a vector holding Vector2 objects.
Definition Vector2.h:64
float Scalar
Definition of a scalar type.
Definition Math.h:129
HomogenousMatrixT4< Scalar > HomogenousMatrix4
Definition of the HomogenousMatrix4 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION flag eit...
Definition HomogenousMatrix4.h:44
The namespace covering the entire Ocean framework.
Definition Accessor.h:15