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