Ocean
UnidirectionalCorrespondences.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_UNIDIRECTIONAL_CORRESPONDENCES_H
9 #define META_OCEAN_TRACKING_UNIDIRECTIONAL_CORRESPONDENCES_H
10 
12 
13 #include "ocean/base/Lock.h"
14 #include "ocean/base/Worker.h"
15 
17 
18 #include "ocean/math/AnyCamera.h"
20 
21 namespace Ocean
22 {
23 
24 namespace Tracking
25 {
26 
27 /**
28  * This class provides unidirectional feature correspondences.
29  * @ingroup tracking
30  */
31 class OCEAN_TRACKING_EXPORT UnidirectionalCorrespondences
32 {
33  public:
34 
35  /**
36  * Definition of a pair holding the indices of two corresponding features or descriptors.
37  */
38  using CorrespondencePair = std::pair<unsigned int, unsigned int>;
39 
40  /**
41  * Definition of a vector holding correspondence pairs.
42  */
43  using CorrespondencePairs = std::vector<CorrespondencePair>;
44 
45  protected:
46 
47  /// Definition of a match count value for zero matches.
48  static constexpr Index32 matchCountZero_ = Index32(-1);
49 
50  /// Definition of a match count value for two+ matches.
51  static constexpr Index32 matchCounterTwo_ = Index32(-2);
52 
53  public:
54 
55  /**
56  * Creates a new unidirectional correspondences object.
57  * @param numberForward The number of forward features, with range [1, infinity)
58  * @param numberBackward The number of backward features, with range [1, infinity)
59  */
60  UnidirectionalCorrespondences(const size_t numberForward, const size_t numberBackward);
61 
62  /**
63  * Adds a new feature correspondence candidate.
64  * @param forwardIndex Index of the forward feature or descriptor, with range [0, sizeForward-1]
65  * @param backwardIndex Index of the corresponding backward feature or descriptor, with range [0, sizeBackward-1]
66  * @tparam tThreadSafe True, in case the call needs to be thread-safe; False, if no other thread is currently using this correspondence object
67  */
68  template <bool tThreadSafe>
69  void addCandidate(const unsigned int forwardIndex, const unsigned int backwardIndex);
70 
71  /**
72  * Returns all unidirectional feature correspondences.
73  * @return The resulting unique feature correspondences
74  */
76 
77  /**
78  * Determines unidirectional correspondences pairs between two sets of descriptors.
79  * @param forwardDescriptors The first (forward) set of descriptors, can be invalid if 'numberForwardDescriptors == 0'
80  * @param numberForwardDescriptors The number of descriptors in the first set, with range [0, infinity)
81  * @param backwardDescriptors The second (backward) set of descriptors, can be invalid if 'numberBackwardDescriptors == 0'
82  * @param numberBackwardDescriptors The number of descriptors in the second set, with range [0, infinity)
83  * @param maximalDistance The maximal distance between two descriptors to count as match, with range [0, infinity)
84  * @parma worker Optional worker to distribute the computation
85  * @return The resulting pairs with unidirectional correspondences
86  * @tparam TDescriptor The data type of the descriptors
87  * @tparam TDistance The data type of the distance between two descriptors
88  * @tparam tDistanceFunction The function returning the distance between two descriptors
89  */
90  template <typename TDescriptor, typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
91  static CorrespondencePairs determineCorrespondingDescriptors(const TDescriptor* forwardDescriptors, const size_t numberForwardDescriptors, const TDescriptor* backwardDescriptors, const size_t numberBackwardDescriptors, const TDistance maximalDistance, Worker* worker);
92 
93  /**
94  * Determines guided unidirectional correspondence pairs between image features and object features.
95  * The resulting matches are guided based on a given rough 6-DOF camera pose.
96  * @param camera The camera profile defining the projection, must be valid
97  * @param world_T_camera The rough 6-DOF pose of the camera, with default camera pointing towards the negative z-space with y-axis upwards
98  * @param objectPoints The 3D locations of the 3D object features, one for each object feature, must be valid
99  * @param objectPointDescriptors The descriptors of the 3D object features, one for each object feature, must be valid
100  * @param numberObjectFeatures The number of 3D object features, with range [1, infinity)
101  * @param imagePoints The 2D location of the 2D image features, one for each image feature, must be valid
102  * @param imagePointDescriptors The descriptors of the 2D image features, one for each image feature, must be valid
103  * @param numberImageFeatures The number of 2D image features, with range [1, infinity)
104  * @param maximalDistance The maximal distance between two descriptors (an object descriptor and an image descriptor) to count as match, with range [0, infinity)
105  * @param maximalProjectionError The maximal projection error between image features and projected object features to count as candidate (allows to balance the number of candidates based on the precision of the given camera pose), in pixels, with range [0, infinity)
106  * @tparam TDescriptor The data type of the descriptors
107  * @tparam TDistance The data type of the distance between two descriptors
108  * @tparam tDistanceFunction The function returning the distance between two descriptors
109  */
110  template <typename TDescriptor, typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
111  static CorrespondencePairs determineCorrespondingFeatures(const AnyCamera& camera, const HomogenousMatrix4& world_T_camera, const Vector3* objectPoints, const TDescriptor* objectPointDescriptors, const size_t numberObjectFeatures, const Vector2* imagePoints, const TDescriptor* imagePointDescriptors, const size_t numberImageFeatures, const TDistance maximalDistance, const Scalar maximalProjectionError);
112 
113  /**
114  * Extracts corresponding elements based on correspondence pairs.
115  * @param correspondencePairs The correspondence pairs providing the individual indices of the elements to be extracted
116  * @param firstElements The entire set of first elements, the first index of each correspondence pair belongs to these elements, must be valid
117  * @param sizeFirstElements The size of the entire set of first elements, with range [1, infinity)
118  * @param secondElements The entire set of second elements, the second index of each correspondence pair belongs to these elements, must be valid
119  * @param sizeSecondElements The size of the entire set of second elements, with range [1, infinity)
120  * @param correspondenceFirstElements The resulting elements from the first set which were defined in the provided correspondence pairs
121  * @param correspondenceSecondElements The resulting elements from the second set which were define i the provided correspondence pairs, one for each elements in correspondenceFirstElements
122  * @tparam TFirst The data type of the first elements
123  * @tparam TSecond The data type of the second elements
124  */
125  template <typename TFirst, typename TSecond>
126  static void extractCorrespondenceElements(const CorrespondencePairs& correspondencePairs, const TFirst* firstElements, const size_t sizeFirstElements, const TSecond* secondElements, const size_t sizeSecondElements, std::vector<TFirst>& correspondenceFirstElements, std::vector<TSecond>& correspondenceSecondElements);
127 
128  protected:
129 
130  /**
131  * Determines a subset of all unidirectional correspondences pairs between two sets of descriptors.
132  * @param forwardDescriptors The first (forward) set of descriptors, must be valid
133  * @param numberForwardDescriptors The number of descriptors in the first set, with range [1, infinity)
134  * @param backwardDescriptors The second (backward) set of descriptors, must be valid
135  * @param numberBackwardDescriptors The number of descriptors in the second set, with range [1, infinity)
136  * @param maximalDistance The maximal distance between two descriptors to count as match, with range [0, infinity)
137  * @param forwardIndicesForBackwardDescriptors The individual indices of matching forward descriptors, one for each backward descriptor
138  * @param locks The 'tLocks' locks elements, must be valid if 'tLocks >= 1'
139  * @param subsetFirstForwardDescriptor The first forward descriptor to be handled, with range [0, numberForwardDescriptors-1]
140  * @param subsetNumberForwardDescriptors The number of forward descriptors to be handled, with range [1, numberForwardDescriptors-subsetFirstForwardDescriptor]
141  * @return The resulting pairs with unidirectional correspondences
142  * @tparam TDescriptor The data type of the descriptors
143  * @tparam TDistance The data type of the distance between two descriptors
144  * @tparam tDistanceFunction The function returning the distance between two descriptors
145  * @tparam tLocks The number of provided lock objects, with range [0, infinity)
146  */
147  template <typename TDescriptor, typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&), unsigned int tLocks>
148  static void determineCorrespondingDescriptorsSubset(const TDescriptor* forwardDescriptors, const size_t numberForwardDescriptors, const TDescriptor* backwardDescriptors, const size_t numberBackwardDescriptors, const TDistance maximalDistance, Index32* forwardIndicesForBackwardDescriptors, Lock* locks, const unsigned int subsetFirstForwardDescriptor, const unsigned int subsetNumberForwardDescriptors);
149 
150  protected:
151 
152  /// Correspondence counter for forward features (or for the first features).
154 
155  /// Correspondence counter for backward features (or for the second features).
157 
158  /// Correspondence candidates.
160 
161  /// The object's lock.
162  mutable Lock lock_;
163 };
164 
165 template <bool tThreadSafe>
166 void UnidirectionalCorrespondences::addCandidate(const unsigned int forwardIndex, const unsigned int backwardIndex)
167 {
168  const TemplatedScopedLock<tThreadSafe> scopedLock(lock_);
169 
170  candidates_.emplace_back(forwardIndex, backwardIndex);
171 
172  ocean_assert(forwardIndex < forwardCounters_.size());
173  ++forwardCounters_[forwardIndex];
174 
175  ocean_assert(backwardIndex < backwardCounters_.size());
176  ++backwardCounters_[backwardIndex];
177 }
178 
179 template <typename TDescriptor, typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
180 UnidirectionalCorrespondences::CorrespondencePairs UnidirectionalCorrespondences::determineCorrespondingDescriptors(const TDescriptor* forwardDescriptors, const size_t numberForwardDescriptors, const TDescriptor* backwardDescriptors, const size_t numberBackwardDescriptors, const TDistance maximalDistance, Worker* worker)
181 {
182  if (numberForwardDescriptors == 0 || numberBackwardDescriptors == 0)
183  {
184  return CorrespondencePairs();
185  }
186 
187  ocean_assert(forwardDescriptors != nullptr && backwardDescriptors != nullptr);
188 
189  Indices32 forwardIndicesForBackwardDescriptors(numberBackwardDescriptors, matchCountZero_); // in the beginning no backward descriptor has a matching forward descriptor
190 
191  if (worker != nullptr)
192  {
193  Lock locks[8];
194 
195  worker->executeFunction(Worker::Function::createStatic(&UnidirectionalCorrespondences::determineCorrespondingDescriptorsSubset<TDescriptor, TDistance, tDistanceFunction, 8u>, forwardDescriptors, numberForwardDescriptors, backwardDescriptors, numberBackwardDescriptors, maximalDistance, forwardIndicesForBackwardDescriptors.data(), locks, 0u, 0u), 0u, (unsigned int)(numberForwardDescriptors));
196  }
197  else
198  {
199  determineCorrespondingDescriptorsSubset<TDescriptor, TDistance, tDistanceFunction, 0u>(forwardDescriptors, numberForwardDescriptors, backwardDescriptors, numberBackwardDescriptors, maximalDistance, forwardIndicesForBackwardDescriptors.data(), nullptr, 0u, (unsigned int)(numberForwardDescriptors));
200  }
201 
202  CorrespondencePairs result;
203  result.reserve(min(numberForwardDescriptors, numberBackwardDescriptors));
204 
205  for (size_t indexBackward = 0; indexBackward < numberBackwardDescriptors; ++indexBackward)
206  {
207  if (forwardIndicesForBackwardDescriptors[indexBackward] < Index32(numberForwardDescriptors))
208  {
209  // we only accept a pair of forward/backward descriptors if both descriptors have been assigned exactly for one match
210 
211  result.emplace_back(forwardIndicesForBackwardDescriptors[indexBackward], Index32(indexBackward));
212  }
213  }
214 
215  return result;
216 }
217 
218 template <typename TDescriptor, typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
219 UnidirectionalCorrespondences::CorrespondencePairs UnidirectionalCorrespondences::determineCorrespondingFeatures(const AnyCamera& camera, const HomogenousMatrix4& world_T_camera, const Vector3* objectPoints, const TDescriptor* objectPointDescriptors, const size_t numberObjectPoints, const Vector2* imagePoints, const TDescriptor* imagePointDescriptors, const size_t numberImagePoints, const TDistance maximalDistance, const Scalar maximalProjectionError)
220 {
221  ocean_assert(camera.isValid() && world_T_camera.isValid());
222  ocean_assert(maximalProjectionError >= 0.0);
223 
224  ocean_assert(numberObjectPoints != 0 && numberImagePoints != 0);
225 
226  if (numberObjectPoints == 0 || numberImagePoints == 0 || maximalProjectionError < 0.0 || !camera.isValid() || !world_T_camera.isValid())
227  {
228  return CorrespondencePairs();
229  }
230 
231  ocean_assert(objectPoints != nullptr && objectPointDescriptors != nullptr);
232  ocean_assert(imagePoints != nullptr && imagePointDescriptors != nullptr);
233 
234  UnidirectionalCorrespondences candidates(numberImagePoints, numberObjectPoints);
235 
236  // first, we project the 3D feature points of the feature map into the camera image and distribute all (visible) features into a 2D grid
237 
238  const unsigned int horizontalBins = std::max(1u, (unsigned int)(Scalar(camera.width()) / maximalProjectionError + Scalar(0.5)));
239  const unsigned int verticalBins = std::max(1u, (unsigned int)(Scalar(camera.height()) / maximalProjectionError + Scalar(0.5)));
240 
241  Geometry::SpatialDistribution::DistributionArray projectedObjectPointsDistributionArray(Scalar(0), Scalar(0), Scalar(camera.width()), Scalar(camera.height()), horizontalBins, verticalBins);
242 
243  const HomogenousMatrix4 cameraFlipped_T_world = AnyCamera::standard2InvertedFlipped(world_T_camera);
244 
245  Vectors2 projectedObjectPoints(numberObjectPoints);
246  camera.projectToImageIF(cameraFlipped_T_world, objectPoints, numberObjectPoints, projectedObjectPoints.data());
247 
248  for (size_t n = 0; n < projectedObjectPoints.size(); ++n)
249  {
250  const Vector2& projectedObjectPoint = projectedObjectPoints[n];
251 
252  const int binX = projectedObjectPointsDistributionArray.horizontalBin(projectedObjectPoint.x());
253  const int binY = projectedObjectPointsDistributionArray.horizontalBin(projectedObjectPoint.y());
254 
255  if ((unsigned int)(binX) < horizontalBins && (unsigned int)(binY) < verticalBins)
256  {
257  ocean_assert(camera.isInside(projectedObjectPoint));
258 
259  projectedObjectPointsDistributionArray(binX, binY).emplace_back(Index32(n));
260  }
261  }
262 
263  // now, we apply a guided matching based on the 9-neighborhood within the 2D grid for each live feature point
264 
265  const Scalar sqrMaximalProjectionError = Numeric::sqr(maximalProjectionError);
266 
267  for (size_t indexImagePoint = 0; indexImagePoint < numberImagePoints; ++indexImagePoint)
268  {
269  const Vector2& imagePoint = imagePoints[indexImagePoint];
270  const TDescriptor& imagePointDescriptor = imagePointDescriptors[indexImagePoint];
271 
272  const int binX = projectedObjectPointsDistributionArray.horizontalBin(imagePoint.x());
273  const int binY = projectedObjectPointsDistributionArray.horizontalBin(imagePoint.y());
274  ocean_assert((unsigned int)(binX) < horizontalBins && (unsigned int)(binY) < verticalBins);
275 
276  TDistance bestDistance = NumericT<TDistance>::maxValue();
277  Index32 bestObjectPointIndex = Index32(-1);
278 
279  // we iterate over the 9-neighborhood in the distribution array
280 
281  for (unsigned int bY = (unsigned int)(std::max(0, binY - 1)); bY < std::min((unsigned int)(binY) + 2u, verticalBins); ++bY)
282  {
283  for (unsigned int bX = (unsigned int)std::max(0, binX - 1); bX < std::min((unsigned int)(binX) + 2u, horizontalBins); ++bX)
284  {
285  const Indices32& objectPointIndices = projectedObjectPointsDistributionArray(bX, bY);
286 
287  for (const Index32& objectPointIndex : objectPointIndices)
288  {
289  ocean_assert(size_t(objectPointIndex) < numberObjectPoints);
290  ocean_assert(size_t(objectPointIndex) < projectedObjectPoints.size());
291 
292  if (projectedObjectPoints[objectPointIndex].sqrDistance(imagePoint) <= sqrMaximalProjectionError)
293  {
294  const TDistance distance = tDistanceFunction(objectPointDescriptors[objectPointIndex], imagePointDescriptor);
295 
296  if (distance < bestDistance)
297  {
298  bestDistance = distance;
299  bestObjectPointIndex = objectPointIndex;
300  }
301  }
302  }
303  }
304  }
305 
306  if (bestObjectPointIndex != Index32(-1) && bestDistance <= maximalDistance)
307  {
308  candidates.addCandidate<false>(Index32(indexImagePoint), bestObjectPointIndex);
309  }
310  }
311 
312  return candidates.correspondences();
313 }
314 
315 template <typename TDescriptor, typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&), unsigned int tLocks>
316 void UnidirectionalCorrespondences::determineCorrespondingDescriptorsSubset(const TDescriptor* forwardDescriptors, const size_t numberForwardDescriptors, const TDescriptor* backwardDescriptors, const size_t numberBackwardDescriptors, const TDistance maximalDistance, Index32* forwardIndicesForBackwardDescriptors, Lock* locks, const unsigned int subsetFirstForwardDescriptor, const unsigned int subsetNumberForwardDescriptors)
317 {
318  ocean_assert(forwardDescriptors != nullptr && backwardDescriptors != nullptr && forwardIndicesForBackwardDescriptors != nullptr);
319 
320  for (unsigned int indexForward = subsetFirstForwardDescriptor; indexForward < subsetFirstForwardDescriptor + subsetNumberForwardDescriptors; ++indexForward)
321  {
322  ocean_assert_and_suppress_unused(indexForward < numberForwardDescriptors, numberForwardDescriptors);
323 
324  TDistance bestDistance = NumericT<TDistance>::maxValue();
325  Index32 bestBackwardIndex = Index32(-1);
326 
327  const TDescriptor& forwardDescriptor = forwardDescriptors[indexForward];
328 
329  for (unsigned int indexBackward = 0u; indexBackward < Index32(numberBackwardDescriptors); ++indexBackward)
330  {
331  const TDistance distance = tDistanceFunction(forwardDescriptor, backwardDescriptors[indexBackward]);
332 
333  if (distance < bestDistance)
334  {
335  bestDistance = distance;
336  bestBackwardIndex = indexBackward;
337  }
338  }
339 
340  if (bestDistance >= maximalDistance)
341  {
342  continue;
343  }
344 
345  // if we found a valid correspondence
346  if (bestBackwardIndex != Index32(-1))
347  {
348  Index32& forwardIndexForBackwardDescriptor = forwardIndicesForBackwardDescriptors[bestBackwardIndex];
349 
350  if constexpr (tLocks != 0u)
351  {
352  ocean_assert(locks != nullptr);
353  const ScopedLock scopedLock(locks[bestBackwardIndex % tLocks]);
354 
355  switch (forwardIndexForBackwardDescriptor)
356  {
357  // we have more than two matching feature point
358  case matchCounterTwo_:
359  break;
360 
361  // we have one feature point
362  case matchCountZero_:
363  forwardIndexForBackwardDescriptor = indexForward;
364  break;
365 
366  // we have more than one matching feature point
367  default:
368  forwardIndexForBackwardDescriptor = matchCounterTwo_;
369  break;
370  }
371  }
372  else
373  {
374  switch (forwardIndexForBackwardDescriptor)
375  {
376  // currently, no matching descriptor defined
377  case matchCountZero_:
378  forwardIndexForBackwardDescriptor = indexForward;
379  break;
380 
381  // this descriptor already had more than two matches
382  case matchCounterTwo_:
383  break;
384 
385  // currently, one matching descriptor is already defined, so we invalidate the match
386  default:
387  forwardIndexForBackwardDescriptor = matchCounterTwo_;
388  break;
389  }
390  }
391  }
392  }
393 }
394 
395 template <typename TFirst, typename TSecond>
396 void UnidirectionalCorrespondences::extractCorrespondenceElements(const CorrespondencePairs& correspondencePairs, const TFirst* firstElements, const size_t sizeFirstElements, const TSecond* secondElements, const size_t sizeSecondElements, std::vector<TFirst>& correspondenceFirstElements, std::vector<TSecond>& correspondenceSecondElements)
397 {
398  correspondenceFirstElements.clear();
399  correspondenceSecondElements.clear();
400 
401  correspondenceFirstElements.reserve(correspondencePairs.size());
402  correspondenceSecondElements.reserve(correspondencePairs.size());
403 
404  for (const CorrespondencePair& correspondencePair : correspondencePairs)
405  {
406  ocean_assert_and_suppress_unused(correspondencePair.first < sizeFirstElements, sizeFirstElements);
407  ocean_assert_and_suppress_unused(correspondencePair.second < sizeSecondElements, sizeSecondElements);
408 
409  correspondenceFirstElements.emplace_back(firstElements[correspondencePair.first]);
410  correspondenceSecondElements.emplace_back(secondElements[correspondencePair.second]);
411  }
412 }
413 
414 
415 }
416 
417 }
418 
419 #endif // META_OCEAN_TRACKING_UNIDIRECTIONAL_CORRESPONDENCES_H
This class implements the abstract base class for all AnyCamera objects.
Definition: AnyCamera.h:130
virtual unsigned int width() const =0
Returns the width of the camera image.
virtual VectorT2< T > projectToImageIF(const VectorT3< T > &objectPoint) const =0
Projects a 3D object point into the camera frame.
virtual unsigned int height() const =0
Returns the height of the camera image.
virtual bool isValid() const =0
Returns whether this camera is valid.
virtual bool isInside(const VectorT2< T > &imagePoint, const T signedBorder=T(0)) const =0
Returns whether a given 2D image point lies inside the camera frame.
static Caller< void > createStatic(typename StaticFunctionPointerMaker< 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 static function with no function parameter.
Definition: Caller.h:2876
static HomogenousMatrixT4< U > standard2InvertedFlipped(const HomogenousMatrixT4< U > &world_T_camera)
Transforms a standard homogenous 4x4 viewing (extrinsic camera) matrix into an inverted and flipped c...
Definition: Camera.h:734
int horizontalBin(const Scalar x) const
Returns the horizontal bin of a given horizontal position.
Definition: SpatialDistribution.h:1105
This class implements a distribution array.
Definition: SpatialDistribution.h:228
bool isValid() const
Returns whether this matrix is a valid homogeneous transformation.
Definition: HomogenousMatrix4.h:1806
This class implements a recursive lock object.
Definition: Lock.h:31
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition: Numeric.h:1495
static constexpr T maxValue()
Returns the max scalar value.
Definition: Numeric.h:3244
This class implements a scoped lock object for recursive lock objects.
Definition: Lock.h:135
This class implements a recursive scoped lock object that is activated by a boolean template paramete...
Definition: Lock.h:178
This class provides unidirectional feature correspondences.
Definition: UnidirectionalCorrespondences.h:32
static CorrespondencePairs determineCorrespondingFeatures(const AnyCamera &camera, const HomogenousMatrix4 &world_T_camera, const Vector3 *objectPoints, const TDescriptor *objectPointDescriptors, const size_t numberObjectFeatures, const Vector2 *imagePoints, const TDescriptor *imagePointDescriptors, const size_t numberImageFeatures, const TDistance maximalDistance, const Scalar maximalProjectionError)
Determines guided unidirectional correspondence pairs between image features and object features.
Definition: UnidirectionalCorrespondences.h:219
static void extractCorrespondenceElements(const CorrespondencePairs &correspondencePairs, const TFirst *firstElements, const size_t sizeFirstElements, const TSecond *secondElements, const size_t sizeSecondElements, std::vector< TFirst > &correspondenceFirstElements, std::vector< TSecond > &correspondenceSecondElements)
Extracts corresponding elements based on correspondence pairs.
Definition: UnidirectionalCorrespondences.h:396
std::pair< unsigned int, unsigned int > CorrespondencePair
Definition of a pair holding the indices of two corresponding features or descriptors.
Definition: UnidirectionalCorrespondences.h:38
static CorrespondencePairs determineCorrespondingDescriptors(const TDescriptor *forwardDescriptors, const size_t numberForwardDescriptors, const TDescriptor *backwardDescriptors, const size_t numberBackwardDescriptors, const TDistance maximalDistance, Worker *worker)
Determines unidirectional correspondences pairs between two sets of descriptors.
Definition: UnidirectionalCorrespondences.h:180
static void determineCorrespondingDescriptorsSubset(const TDescriptor *forwardDescriptors, const size_t numberForwardDescriptors, const TDescriptor *backwardDescriptors, const size_t numberBackwardDescriptors, const TDistance maximalDistance, Index32 *forwardIndicesForBackwardDescriptors, Lock *locks, const unsigned int subsetFirstForwardDescriptor, const unsigned int subsetNumberForwardDescriptors)
Determines a subset of all unidirectional correspondences pairs between two sets of descriptors.
Definition: UnidirectionalCorrespondences.h:316
CorrespondencePairs correspondences() const
Returns all unidirectional feature correspondences.
Indices32 backwardCounters_
Correspondence counter for backward features (or for the second features).
Definition: UnidirectionalCorrespondences.h:156
void addCandidate(const unsigned int forwardIndex, const unsigned int backwardIndex)
Adds a new feature correspondence candidate.
Definition: UnidirectionalCorrespondences.h:166
static constexpr Index32 matchCountZero_
Definition of a match count value for zero matches.
Definition: UnidirectionalCorrespondences.h:48
UnidirectionalCorrespondences(const size_t numberForward, const size_t numberBackward)
Creates a new unidirectional correspondences object.
Indices32 forwardCounters_
Correspondence counter for forward features (or for the first features).
Definition: UnidirectionalCorrespondences.h:153
CorrespondencePairs candidates_
Correspondence candidates.
Definition: UnidirectionalCorrespondences.h:159
Lock lock_
The object's lock.
Definition: UnidirectionalCorrespondences.h:162
static constexpr Index32 matchCounterTwo_
Definition of a match count value for two+ matches.
Definition: UnidirectionalCorrespondences.h:51
std::vector< CorrespondencePair > CorrespondencePairs
Definition of a vector holding correspondence pairs.
Definition: UnidirectionalCorrespondences.h:43
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
const T * data() const noexcept
Returns an pointer to the vector elements.
Definition: Vector3.h:842
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.
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition: base/Utilities.h:1089
std::vector< Index32 > Indices32
Definition of a vector holding 32 bit index values.
Definition: Base.h:96
uint32_t Index32
Definition of a 32 bit index value.
Definition: Base.h:84
float Scalar
Definition of a scalar type.
Definition: Math.h:128
std::vector< Vector2 > Vectors2
Definition of a vector holding Vector2 objects.
Definition: Vector2.h:64
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15