Ocean
JLinkage.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_GEOMETRY_JLINKAGE_H
9 #define META_OCEAN_GEOMETRY_JLINKAGE_H
10 
13 
15 #include "ocean/base/Subset.h"
16 
17 #include "ocean/math/Line2.h"
18 #include "ocean/math/Matrix.h"
19 
20 #include <iterator>
21 
22 namespace Ocean
23 {
24 
25 namespace Geometry
26 {
27 
28 /**
29  * This class implements several J-linkage functions for pose/homography determination.
30  * J-linkage aims to fit multiple models from data given
31  * The J-linkage algorithm is an agglomerative clustering that proceeds by linking elements with Jaccard distance smaller than 1 and stop as soon as there are no such elements left.
32  * @ingroup geometry
33  */
34 class OCEAN_GEOMETRY_EXPORT JLinkage
35 {
36  protected:
37 
38  /**
39  * Definition of a pair combining a point index with the distance to a reference.
40  */
41  typedef std::pair<Scalar, Index32> DistancePair;
42 
43  public:
44 
45  /**
46  * Calculates multiple homographies between two images transforming the projected planar object points between the two images using J-linkage
47  * The resulting homographies transform its image points defined in the left image to image points defined in the right image (rightPoint_i = H_i * leftPoint_i).<br>
48  * @param leftImagePoints Image points in the left camera, each point corresponds to one point in the right image
49  * @param rightImagePoints Image points in the right camera
50  * @param correspondences Number of points correspondences
51  * @param width The width of the left image in pixel
52  * @param height The height of the left image in pixel
53  * @param homographies Resulting valid homographies for each image plane
54  * @param testCandidates Number of candidates used in for minimum sample set, with range [4, correspondences]
55  * @param leftPointForInitialModels Initial image points, one per each sample set
56  * @param squarePixelErrorAssignmentThreshold Maximal square pixel error of a valid projection of a 3D point onto the 2D image plane, with range (0, infinity)
57  * @param usedIndicesPerHomography Optional set of indices which will receive the indices of the used image correspondences per model, if defined
58  * @param refineHomographies Determines whether a not linear least square algorithm is used to increase the pose accuracies after J-linkage
59  * @param approximatedNeighborSearch Defines if speeded up spatial neighbor search is used
60  * @param randomGenerator Random number generator. If is not nullptr, RANSAC is used for homography determination within initial minimum sample set
61  * @return True, if successfully completed
62  */
63  static bool homographyMatrices(const ImagePoint* leftImagePoints, const ImagePoint* rightImagePoints, const size_t correspondences, const unsigned int width, const unsigned int height, SquareMatrices3& homographies, const unsigned int testCandidates, const ImagePoints& leftPointForInitialModels, const Scalar squarePixelErrorAssignmentThreshold, std::vector<IndexSet32>* usedIndicesPerHomography = nullptr, bool refineHomographies = true, bool approximatedNeighborSearch = true, Ocean::RandomGenerator* randomGenerator = nullptr);
64 
65  /**
66  * Calculates multiple homographies between two images transforming the projected planar object points between the two images using J-linkage
67  * The resulting homographies transform its image points defined in the left image to image points defined in the right image (rightPoint_i = H_i * leftPoint_i).<br>
68  * @param leftImagePoints Image points in the left camera, each point corresponds to one point in the right image
69  * @param rightImagePoints Image points in the right camera
70  * @param correspondences Number of points correspondences
71  * @param width The width of the left image in pixel
72  * @param height The height of the left image in pixel
73  * @param homographies Resulting valid homographies for each image plane
74  * @param testCandidates Number of candidates used in for minimum sample set, with range [4, correspondences]
75  * @param leftPointIndicesForInitialModels Initial indices of image points, one per each sample set
76  * @param squarePixelErrorAssignmentThreshold Maximal square pixel error of a valid projection of a 3D point onto the 2D image plane, with range (0, infinity)
77  * @param usedIndicesPerHomography Optional set of indices which will receive the indices of the used image correspondences per model, if defined
78  * @param refineHomographies Determines whether a not linear least square algorithm is used to increase the pose accuracies after J-linkage
79  * @param approximatedNeighborSearch Defines if speeded up spatial neighbor search is used
80  * @param randomGenerator Random number generator. If is not nullptr, RANSAC is used for homography determination within initial minimum sample set
81  * @return True, if successfully completed
82  */
83  static inline bool homographyMatrices(const ImagePoint* leftImagePoints, const ImagePoint* rightImagePoints, const size_t correspondences, const unsigned int width, const unsigned int height, SquareMatrices3& homographies, const unsigned int testCandidates, const Indices32& leftPointIndicesForInitialModels, const Scalar squarePixelErrorAssignmentThreshold, std::vector<IndexSet32>* usedIndicesPerHomography = nullptr, bool refineHomographies = true, bool approximatedNeighborSearch = true, Ocean::RandomGenerator* randomGenerator = nullptr);
84 
85  /**
86  * Multiple line detector using J-linkage
87  * @param imagePoints image points
88  * @param pointCount Number of points
89  * @param width The width of the image in pixel
90  * @param height The height of the image in pixel
91  * @param lines Resulting valid line model
92  * @param testCandidates Number of candidates used in for minimum sample set, with range [2, correspondences]
93  * @param pointForInitialModels Initial image points, one per each sample set
94  * @param pixelErrorAssignmentThreshold Maximal pixel error of a point-line corresspodance (0, infinity)
95  * @param usedIndicesPerHomography Optional set of indices which will receive the indices of the used image correspondences per model, if defined
96  * @param approximatedNeighborSearch Defines if speeded up spatial neighbor search is used
97  * @return True, if successfully completed
98  */
99  static bool fitLines(const ImagePoint* imagePoints, const size_t pointCount, const unsigned int width, const unsigned int height, Lines2& lines, const unsigned int testCandidates, const ImagePoints& pointForInitialModels, const Scalar pixelErrorAssignmentThreshold, std::vector<IndexSet32>* usedIndicesPerHomography = nullptr, bool approximatedNeighborSearch = true);
100 
101  protected:
102 
103  /**
104  * Generates minimal sample set for J-/T-Linkage
105  * @param imagePoints Image points
106  * @param pointCount Number of points
107  * @param pointForInitialModels Initial points of minimal sample sets. Note: some maybe be discarded
108  * @param testCandidates Number of candidates used for each minimal sampling set, with range [1, correspondences]
109  * @param distributionImagePoints Spatial distribution for approximate search (if nullptr, brute force methode is used)
110  * @return List of minimal sample sets (represented by indices)
111  */
112  static std::vector<Indices32> buildingMinimalSampleSet(const ImagePoint* imagePoints, const size_t pointCount, const ImagePoints& pointForInitialModels, const unsigned int testCandidates, const SpatialDistribution::DistributionArray* distributionImagePoints = nullptr);
113 
114  /**
115  * Generates a homography per minimal sample set (for J-/T-Linkage)
116  * @param leftImagePoints Image points in the left camera, each point corresponds to one point in the right image
117  * @param rightImagePoints Image points in the right camera
118  * @param correspondences Number of points correspondences
119  * @param leftPointForInitialModels Initial points of minimal sample sets. Note: some maybe be discarded
120  * @param testCandidates Number of candidates used for each minimal sampling set, with range [4, correspondences]
121  * @param distributionImagePoints Spatial distribution for approximate search (if nullptr, brute force methode is used)
122  * @param randomRansac Random generator object to be used for creating random numbers, RANSAC is used if this is not null
123  * @return Resulting homographies for each minimal sample set (its count is possibly smaller then the given image points)
124  */
125  static SquareMatrices3 buildingMinimalSampleSetHomography(const ImagePoint* leftImagePoints, const ImagePoint* rightImagePoints, const size_t correspondences, const ImagePoints& leftPointForInitialModels, const unsigned int testCandidates, const SpatialDistribution::DistributionArray* distributionImagePoints = nullptr, RandomGenerator* randomRansac = nullptr);
126 
127  /**
128  * Generates a line model per minimal sample set (for J-/T-Linkage)
129  * @param imagePoints Image points
130  * @param pointCount Number of points
131  * @param pointForInitialModels Initial points of minimal sample sets. Note: some maybe be discarded
132  * @param testCandidates Number of candidates used for each minimal sampling set, with range [2, correspondences]
133  * @param distributionImagePoints Spatial distribution for approximate search (if nullptr, brute force methode is used)
134  * @return Resulting line for each minimal sample set (its count is possibly smaller then the given image points)
135  */
136  static Lines2 buildingMinimalSampleSetLine(const ImagePoint* imagePoints, const size_t pointCount, const ImagePoints& pointForInitialModels, const unsigned int testCandidates, const SpatialDistribution::DistributionArray* distributionImagePoints = nullptr);
137 
138  /**
139  * Calculates the jaccard distance
140  * d(A, B) = ( |union(A, B)| - |intersection(A, B)| ) / |union(A, B)|.
141  * @param setA first set of indices to compare
142  * @param setB second set of indices to compare
143  * @return Jaccard distance [0, 1]
144  */
145  static inline Scalar jaccardDistance(const IndexSet32& setA, const IndexSet32& setB);
146 
147  /**
148  * Sorts pairs of indices and their corresponding distances in ascending order regarding the distance values.
149  * @param firstPair First pair of distance and index
150  * @param seccondPair Second pair of distance and index
151  * @return True, if the distance value of the first pair is smaller than distance value of the second pair
152  */
153  static inline bool distancePairSortAscending(const DistancePair& firstPair, const DistancePair& seccondPair);
154 };
155 
156 /**
157  * This class implements L-linkage functions for pose/homography determination.
158  * T-linkage aims to fit multiple models from data given
159  * The T-linkage algorithm is an agglomerative clustering that proceeds by linking elements with tanimoto distance smaller than 1 and stop as soon as there are no such elements left.
160  * @ingroup geometry
161  */
162 class OCEAN_GEOMETRY_EXPORT TLinkage : JLinkage
163 {
164  public:
165 
166  /**
167  * Calculates multiple homographies between two images transforming the projected planar object points between the two images using T-linkage
168  * The resulting homographies transform its image points defined in the left image to image points defined in the right image (rightPoint_i = H_i * leftPoint_i).<br>
169  * @param leftImagePoints Image points in the left camera, each point corresponds to one point in the right image
170  * @param rightImagePoints Image points in the right camera
171  * @param correspondences Number of points correspondences
172  * @param homographies Resulting valid homographies for each image plane
173  * @param testCandidates Number of candidates used in for minimum sample set, with range [8, correspondences]
174  * @param leftPointForInitialModels Initial image points, one per each sample set
175  * @param pixelAssignmentRadius Maximal pixel radius of image points being considered [5, image width)
176  * @param usedIndicesPerHomography Optional set of indices which will receive the indices of the used image correspondences per model, if defined
177  * @param refineHomographies Determines whether a not linear least square algorithm is used to increase the pose accuracies after J-linkage
178  * @param randomGenerator Random number generator. If is not nullptr, RANSAC is used for homography refinement
179  * @return True, if successfully completed
180  */
181  static bool homographyMatrices(const ImagePoint* leftImagePoints, const ImagePoint* rightImagePoints, const size_t correspondences, SquareMatrices3& homographies, const unsigned int testCandidates, const ImagePoints& leftPointForInitialModels, const Scalar pixelAssignmentRadius, std::vector<IndexSet32>* usedIndicesPerHomography = nullptr, bool refineHomographies = true, Ocean::RandomGenerator* randomGenerator = nullptr);
182 
183  /**
184  * Multiple line detector using T-linkage
185  * @param imagePoints image points
186  * @param pointCount Number of points
187  * @param lines Resulting valid line model
188  * @param testCandidates Number of candidates used in for minimum sample set, with range [2, correspondences]
189  * @param pointForInitialModels Initial image points, one per each sample set
190  * @param pixelErrorAssignmentThreshold Maximal pixel error of a point-line corresspodance (0, infinity)
191  * @param usedIndicesPerHomography Optional set of indices which will receive the indices of the used image correspondences per model, if defined
192  * @return True, if successfully completed
193  */
194  static bool fitLines(const ImagePoint* imagePoints, const size_t pointCount, Lines2& lines, const unsigned int testCandidates, const ImagePoints& pointForInitialModels, const Scalar pixelErrorAssignmentThreshold, std::vector<IndexSet32>* usedIndicesPerHomography = nullptr);
195 
196  private:
197 
198  /**
199  * Calculates the tanimoto distance
200  * d(A, B) = 1 - A*B / (A*A + B*B - A*B).<BR>
201  * A and B must have the same amount of elements
202  * @param vectorA first vector to compare
203  * @param vectorB second vector to compare
204  * @return Tanimoto distance [0, 1]
205  */
206  static inline Scalar tanimotoDistance(const Matrix& vectorA, const Matrix& vectorB);
207 };
208 
209 inline bool JLinkage::homographyMatrices(const ImagePoint* leftImagePoints, const ImagePoint* rightImagePoints, const size_t correspondences, const unsigned int width, const unsigned int height, SquareMatrices3 & homographies, const unsigned int testCandidates, const Indices32& leftPointIndicesForInitialModels, const Scalar squarePixelErrorAssignmentThreshold, std::vector<IndexSet32>* usedIndicesPerHomography, bool refineHomographies, bool approximatedNeighborSearch, Ocean::RandomGenerator* randomGenerator)
210 {
211  const ImagePoints leftPointForInitialModels(Subset::subset(leftImagePoints, correspondences, leftPointIndicesForInitialModels));
212 
213  return homographyMatrices(leftImagePoints, rightImagePoints, correspondences, width, height, homographies, testCandidates, leftPointForInitialModels, squarePixelErrorAssignmentThreshold, usedIndicesPerHomography, refineHomographies, approximatedNeighborSearch, randomGenerator);
214 }
215 
216 inline Scalar JLinkage::jaccardDistance(const IndexSet32& setA, const IndexSet32& setB)
217 {
218  if (setA.empty() || setB.empty())
219  {
220  return 0;
221  }
222 
223  Indices32 intersectionSet;
224  std::set_intersection(setA.cbegin(), setA.cend(), setB.cbegin(), setB.cend(), std::back_inserter(intersectionSet));
225 
226  Indices32 unionSet;
227  std::set_union(setA.cbegin(), setA.cend(), setB.cbegin(), setB.cend(), std::back_inserter(unionSet));
228 
229  const Scalar numberIntersections = Scalar(intersectionSet.size());
230  const Scalar numberUnion = Scalar(unionSet.size());
231 
232  ocean_assert(unionSet.size() >= 1);
233  return (numberUnion - numberIntersections) / numberUnion;
234 }
235 
236 inline bool JLinkage::distancePairSortAscending(const DistancePair& firstPair, const DistancePair& seccondPair)
237 {
238  return firstPair.first < seccondPair.first;
239 }
240 
241 inline Scalar TLinkage::tanimotoDistance(const Matrix& vectorA, const Matrix& vectorB)
242 {
243  ocean_assert((vectorA.columns() == 1u || vectorA.rows() == 1u) && (vectorB.columns() == 1u || vectorB.rows() == 1u));
244  ocean_assert(vectorA.elements() == vectorB.elements());
245 
246  size_t length = vectorA.elements();
247 
248  Scalar squaredNormAB(0);
249  Scalar squaredNormA(0);
250  Scalar squaredNormB(0);
251 
252  for (size_t n = 0u; n < length; ++n)
253  {
254  squaredNormA += Numeric::sqr(vectorA.data()[n]);
255  squaredNormB += Numeric::sqr(vectorB.data()[n]);
256  squaredNormAB += vectorA.data()[n] * vectorB.data()[n];
257  }
258 
259  return (1 - Numeric::ratio(squaredNormAB, squaredNormA + squaredNormB - squaredNormAB));
260 }
261 
262 }
263 
264 }
265 
266 #endif // META_OCEAN_GEOMETRY_JLINKAGE_H
This class implements several J-linkage functions for pose/homography determination.
Definition: JLinkage.h:35
static Scalar jaccardDistance(const IndexSet32 &setA, const IndexSet32 &setB)
Calculates the jaccard distance d(A, B) = ( |union(A, B)| - |intersection(A, B)| ) / |union(A,...
Definition: JLinkage.h:216
static bool distancePairSortAscending(const DistancePair &firstPair, const DistancePair &seccondPair)
Sorts pairs of indices and their corresponding distances in ascending order regarding the distance va...
Definition: JLinkage.h:236
static bool fitLines(const ImagePoint *imagePoints, const size_t pointCount, const unsigned int width, const unsigned int height, Lines2 &lines, const unsigned int testCandidates, const ImagePoints &pointForInitialModels, const Scalar pixelErrorAssignmentThreshold, std::vector< IndexSet32 > *usedIndicesPerHomography=nullptr, bool approximatedNeighborSearch=true)
Multiple line detector using J-linkage.
static std::vector< Indices32 > buildingMinimalSampleSet(const ImagePoint *imagePoints, const size_t pointCount, const ImagePoints &pointForInitialModels, const unsigned int testCandidates, const SpatialDistribution::DistributionArray *distributionImagePoints=nullptr)
Generates minimal sample set for J-/T-Linkage.
static Lines2 buildingMinimalSampleSetLine(const ImagePoint *imagePoints, const size_t pointCount, const ImagePoints &pointForInitialModels, const unsigned int testCandidates, const SpatialDistribution::DistributionArray *distributionImagePoints=nullptr)
Generates a line model per minimal sample set (for J-/T-Linkage)
static bool homographyMatrices(const ImagePoint *leftImagePoints, const ImagePoint *rightImagePoints, const size_t correspondences, const unsigned int width, const unsigned int height, SquareMatrices3 &homographies, const unsigned int testCandidates, const ImagePoints &leftPointForInitialModels, const Scalar squarePixelErrorAssignmentThreshold, std::vector< IndexSet32 > *usedIndicesPerHomography=nullptr, bool refineHomographies=true, bool approximatedNeighborSearch=true, Ocean::RandomGenerator *randomGenerator=nullptr)
Calculates multiple homographies between two images transforming the projected planar object points b...
static SquareMatrices3 buildingMinimalSampleSetHomography(const ImagePoint *leftImagePoints, const ImagePoint *rightImagePoints, const size_t correspondences, const ImagePoints &leftPointForInitialModels, const unsigned int testCandidates, const SpatialDistribution::DistributionArray *distributionImagePoints=nullptr, RandomGenerator *randomRansac=nullptr)
Generates a homography per minimal sample set (for J-/T-Linkage)
std::pair< Scalar, Index32 > DistancePair
Definition of a pair combining a point index with the distance to a reference.
Definition: JLinkage.h:41
This class implements a distribution array.
Definition: SpatialDistribution.h:228
This class implements L-linkage functions for pose/homography determination.
Definition: JLinkage.h:163
static bool homographyMatrices(const ImagePoint *leftImagePoints, const ImagePoint *rightImagePoints, const size_t correspondences, SquareMatrices3 &homographies, const unsigned int testCandidates, const ImagePoints &leftPointForInitialModels, const Scalar pixelAssignmentRadius, std::vector< IndexSet32 > *usedIndicesPerHomography=nullptr, bool refineHomographies=true, Ocean::RandomGenerator *randomGenerator=nullptr)
Calculates multiple homographies between two images transforming the projected planar object points b...
static bool fitLines(const ImagePoint *imagePoints, const size_t pointCount, Lines2 &lines, const unsigned int testCandidates, const ImagePoints &pointForInitialModels, const Scalar pixelErrorAssignmentThreshold, std::vector< IndexSet32 > *usedIndicesPerHomography=nullptr)
Multiple line detector using T-linkage.
static Scalar tanimotoDistance(const Matrix &vectorA, const Matrix &vectorB)
Calculates the tanimoto distance d(A, B) = 1 - A*B / (A*A + B*B - A*B).
Definition: JLinkage.h:241
size_t columns() const
Returns the count of columns.
Definition: Matrix.h:698
const T * data() const
Returns a pointer to the internal values.
Definition: Matrix.h:798
size_t elements() const
Returns the number of entire elements, which is the product of rows and columns.
Definition: Matrix.h:704
size_t rows() const
Returns the count of rows.
Definition: Matrix.h:692
static constexpr T ratio(const T nominator, const T denominator, const T fallback=T(1))
Returns the ratio between two values if the denominator is not equal a small epsilon.
Definition: Numeric.h:2076
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition: Numeric.h:1495
This class implements a generator for random numbers.
Definition: RandomGenerator.h:42
static std::vector< T > subset(const std::vector< T > &objects, const std::vector< TIndex > &indices)
Extracts a subset of a given set of objects by usage of an index vector holding the indices of all ob...
Definition: Subset.h:751
std::set< Index32 > IndexSet32
Definition of a set holding 32 bit indices.
Definition: Base.h:114
std::vector< Index32 > Indices32
Definition of a vector holding 32 bit index values.
Definition: Base.h:96
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
std::vector< Line2 > Lines2
Definition of a vector holding Line2 objects.
Definition: Line2.h:57
std::vector< SquareMatrix3 > SquareMatrices3
Definition of a vector holding SquareMatrix3 objects.
Definition: SquareMatrix3.h:71
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15