Ocean
Loading...
Searching...
No Matches
BullseyeDetectorStereo.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 OCEAN_CV_DETECTOR_BULLSEYES_BULLSEYEDETECTORSTEREO_H
9#define OCEAN_CV_DETECTOR_BULLSEYES_BULLSEYEDETECTORSTEREO_H
10
14
15#include "ocean/base/Frame.h"
16#include "ocean/base/Worker.h"
18
20#include "ocean/math/Matrix.h"
21#include "ocean/math/Vector3.h"
22
23#include <array>
24
25namespace Ocean
26{
27
28namespace CV
29{
30
31namespace Detector
32{
33
34namespace Bullseyes
35{
36
37/**
38 * This class implements a stereo detector for bullseye patterns.
39 * @ingroup cvdetectorbullseyes
40 */
41class OCEAN_CV_DETECTOR_BULLSEYES_EXPORT BullseyeDetectorStereo
42{
43 public:
44
45 /**
46 * Definition of a pair of bullseyes.
47 */
48 using BullseyePair = std::pair<Bullseye, Bullseye>;
49
50 /**
51 * Definition of a vector holding bullseye pairs.
52 */
53 using BullseyePairs = std::vector<BullseyePair>;
54
55 /**
56 * Definition of a pair of vectors of bullseyes, one from each camera.
57 */
58 using BullseyeGroup = std::array<Bullseyes, 2>;
59
60 /**
61 * This class holds the most important parameters for the stereo detector.
62 * Currently, this class inherits all parameters from the monocular detector.
63 */
64 class OCEAN_CV_DETECTOR_BULLSEYES_EXPORT Parameters : public BullseyeDetectorMono::Parameters
65 {
66 public:
67
68 /**
69 * Creates a new parameter object with default parameters.
70 */
71 Parameters() = default;
72
73 /**
74 * Returns the maximum frame width before downscaling is applied.
75 * Input frames wider than this value will be downscaled for efficiency.
76 * @return The maximum frame width in pixels, with range [1, infinity)
77 */
78 unsigned int maxFrameWidth() const noexcept;
79
80 /**
81 * Sets the maximum frame width before downscaling is applied.
82 * Input frames wider than this value will be downscaled for efficiency.
83 * @param maxFrameWidth The maximum frame width in pixels, with range [1, infinity)
84 */
85 void setMaxFrameWidth(unsigned int maxFrameWidth) noexcept;
86
87 /**
88 * Returns the default parameters for the stereo detector.
89 * @return The default parameters
90 */
91 static Parameters defaultParameters();
92
93 protected:
94
95 /// The maximum frame width before downscaling is applied, with range [1, infinity)
96 unsigned int maxFrameWidth_ = 720u;
97 };
98
99 protected:
100
101 /**
102 * This class represents a candidate bullseye match between two stereo cameras.
103 * A candidate includes the triangulated 3D center position and the reprojection errors for
104 * both cameras. The indices of the matched bullseyes are stored separately as keys in the
105 * CandidateMap. Candidates are used during the matching process before final validation and
106 * selection.
107 */
109 {
110 public:
111
112 /**
113 * Creates a default (invalid) candidate.
114 */
115 Candidate() = default;
116
117 /**
118 * Creates a new candidate with the specified parameters.
119 * The indices of the matched bullseyes are not stored in the candidate itself,
120 * but rather as keys in the CandidateMap that holds this candidate.
121 * @param center The triangulated 3D center position in world coordinates
122 * @param reprojectionErrorA The reprojection error for camera A, in pixels
123 * @param reprojectionErrorB The reprojection error for camera B, in pixels
124 */
125 Candidate(const Vector3& center, const Scalar reprojectionErrorA, const Scalar reprojectionErrorB);
126
127 /**
128 * Returns whether this candidate is valid.
129 * @return True if the candidate has valid indices and center position, otherwise false
130 */
131 bool isValid() const;
132
133 /**
134 * Returns the triangulated 3D center position.
135 * @return The 3D center position in world coordinates
136 */
137 const Vector3& center() const;
138
139 /**
140 * Returns the reprojection error for camera A.
141 * @return The reprojection error in pixels
142 */
144
145 /**
146 * Returns the reprojection error for camera B.
147 * @return The reprojection error in pixels
148 */
150
151 /**
152 * Returns an invalid bullseye center value used as a sentinel for uninitialized positions.
153 * @return The invalid center position
154 */
156
157 protected:
158
159 /// The triangulated 3D center position in world coordinates
160 Vector3 center_ = invalidBullseyeCenter();
161
162 /// The reprojection error for camera A, in pixels
163 Scalar reprojectionErrorA_ = Numeric::minValue();
164
165 /// The reprojection error for camera B, in pixels
166 Scalar reprojectionErrorB_ = Numeric::minValue();
167 };
168
169 /**
170 * Definition of an unordered map holding candidate bullseyes.
171 * The key is a pair of indices (indexA, indexB) where indexA corresponds to a bullseye in camera A
172 * and indexB corresponds to a bullseye in camera B. The value is the Candidate object containing
173 * the triangulated 3D position and reprojection errors for this match.
174 */
175 using CandidateMap = std::unordered_map<IndexPair32, Candidate, PairHash>;
176
177 public:
178
179 /**
180 * Detects bullseyes in a pair of stereo frames.
181 * @param cameras The camera profiles for the stereo pair, must contain exactly 2 valid cameras
182 * @param yFrames The stereo frames in which bullseyes will be detected, must contain exactly 2 valid 8-bit grayscale frames
183 * @param world_T_device The transformation from the device coordinate system to the world coordinate system, must be valid
184 * @param device_T_cameras The transformations from each camera coordinate system to the device coordinate system, must contain exactly 2 valid transformations
185 * @param bullseyePairs The resulting pairs of detected bullseyes, one from each camera
186 * @param bullseyeCenters The resulting 3D positions of the triangulated bullseye centers in world coordinates
187 * @param parameters The parameters for the detector, must be valid
188 * @param worker Optional worker to distribute the computation
189 * @return True, if succeeded
190 */
191 static bool detectBullseyes(const SharedAnyCameras& cameras, const Frames& yFrames, const HomogenousMatrix4& world_T_device, const HomogenousMatrices4& device_T_cameras, BullseyePairs& bullseyePairs, Vectors3& bullseyeCenters, const Parameters& parameters = Parameters::defaultParameters(), Worker* worker = nullptr);
192
193 protected:
194
195 /**
196 * Extracts and validates candidate bullseye matches between two stereo cameras.
197 * This function triangulates all possible bullseye pairs and returns those that produce valid 3D positions.
198 * The returned map uses index pairs (indexA, indexB) as keys, where indexA corresponds to a bullseye in camera A
199 * and indexB corresponds to a bullseye in camera B. The values are Candidate objects containing the triangulated
200 * 3D positions and reprojection errors for each matched pair.
201 * @param cameraA The camera profile for the first camera, must be valid
202 * @param cameraB The camera profile for the second camera, must be valid
203 * @param world_T_cameraA The transformation from camera A coordinate system to world coordinate system, must be valid
204 * @param world_T_cameraB The transformation from camera B coordinate system to world coordinate system, must be valid
205 * @param bullseyesA The bullseyes detected in camera A, may be empty
206 * @param bullseyesB The bullseyes detected in camera B, may be empty
207 * @return The map of valid candidate matches; may be empty if no valid matches were found
208 */
209 static CandidateMap extractBullseyeCandidates(const AnyCamera& cameraA, const AnyCamera& cameraB, const HomogenousMatrix4& world_T_cameraA, const HomogenousMatrix4& world_T_cameraB, const Bullseyes& bullseyesA, const Bullseyes& bullseyesB);
210
211 /**
212 * Extracts the final bullseye pairs and their 3D centers from candidate matches.
213 * This function uses the candidate map to retrieve the original bullseye objects and their triangulated positions.
214 * @param cameraA The camera profile for the first camera, must be valid
215 * @param cameraB The camera profile for the second camera, must be valid
216 * @param bullseyesA The bullseyes detected in camera A, must not be empty
217 * @param bullseyesB The bullseyes detected in camera B, must not be empty
218 * @param candidateMap The map of candidate matches with index pairs as keys and triangulated positions as values, must not be empty
219 * @param bullseyePairs The resulting validated bullseye pairs
220 * @param bullseyeCenters The resulting 3D positions of the bullseye centers in world coordinates
221 * @return True if extraction succeeded, otherwise false
222 */
223 static bool extractBullseyes(const AnyCamera& cameraA, const AnyCamera& cameraB, const Bullseyes& bullseyesA, const Bullseyes& bullseyesB, const CandidateMap& candidateMap, BullseyePairs& bullseyePairs, Vectors3& bullseyeCenters);
224
225 /**
226 * Computes a cost matrix for matching bullseyes based on candidate triangulation results.
227 * The cost matrix dimensions are (numBullseyesA x numBullseyesB), where each element (i, j)
228 * contains the cost of matching bullseye i from camera A with bullseye j from camera B.
229 * Costs are based on the triangulation quality (reprojection errors) and geometric consistency
230 * (comparing bullseye radii across cameras using the camera scale factor).
231 * @param cameraA The camera profile for the first camera, must be valid
232 * @param cameraB The camera profile for the second camera, must be valid
233 * @param bullseyesA The bullseyes detected in camera A, must not be empty
234 * @param bullseyesB The bullseyes detected in camera B, must not be empty
235 * @param candidateMap The map of candidate matches to evaluate, must not be empty
236 * @param costMatrix The resulting cost matrix with dimensions (numBullseyesA x numBullseyesB)
237 * @return True if the cost matrix was successfully computed, otherwise false
238 */
239 static bool computeCostMatrix(const AnyCamera& cameraA, const AnyCamera& cameraB, const Bullseyes& bullseyesA, const Bullseyes& bullseyesB, const CandidateMap& candidateMap, Matrix& costMatrix);
240
241 /**
242 * Returns an invalid (arbitrarily large) matching cost value used to indicate that two bullseyes cannot be matched.
243 * This value is large enough to prevent matching but not so large as to cause numerical issues.
244 * @return The invalid matching cost value
245 */
246 constexpr static Scalar invalidMatchingCost();
247
248 /**
249 * Triangulates a single matched bullseye pair to compute its 3D position in world coordinates.
250 * This function casts rays from both camera centers through the bullseye positions and finds their nearest point
251 * to determine the 3D location. It also computes reprojection errors to assess triangulation quality.
252 * @param cameraA The camera profile for the first camera, must be valid
253 * @param cameraB The camera profile for the second camera, must be valid
254 * @param world_T_cameraA The transformation from camera A coordinate system to world coordinate system, must be valid
255 * @param world_T_cameraB The transformation from camera B coordinate system to world coordinate system, must be valid
256 * @param bullseyeA The bullseye from camera A, must be valid and within camera A's field of view
257 * @param bullseyeB The bullseye from camera B, must be valid and within camera B's field of view
258 * @param bullseyeCenter The resulting 3D position of the bullseye center in world coordinates
259 * @param reprojectionErrorA The resulting reprojection error for camera A, in pixels
260 * @param reprojectionErrorB The resulting reprojection error for camera B, in pixels
261 * @return True if triangulation succeeded and the 3D point is in front of both cameras, otherwise false
262 */
263 static bool triangulateBullseye(const AnyCamera& cameraA, const AnyCamera& cameraB, const HomogenousMatrix4& world_T_cameraA, const HomogenousMatrix4& world_T_cameraB, const Bullseye& bullseyeA, const Bullseye& bullseyeB, Vector3& bullseyeCenter, Scalar& reprojectionErrorA, Scalar& reprojectionErrorB);
264
265 /**
266 * Downscales frames and cameras if they exceed the maximum frame width.
267 * For frames that don't exceed the threshold, the original frame and camera are used (no copy is made).
268 * @param cameras The input camera profiles, must contain exactly 2 valid cameras
269 * @param yFrames The input frames, must contain exactly 2 valid 8-bit grayscale frames
270 * @param maxFrameWidth The maximum allowed frame width before downscaling is applied, with range [1, infinity)
271 * @param downscaledCameras The resulting cameras (downscaled or original), will contain exactly 2 cameras
272 * @param downscaledYFrames The resulting frames (downscaled or referencing original), will contain exactly 2 frames
273 * @param scaleFactors The scale factors applied to each frame (1.0 if no downscaling), will contain exactly 2 values
274 * @param worker Optional worker to distribute the computation
275 * @return True if successful, false on error
276 */
277 static bool downscaleFramesAndCameras(const SharedAnyCameras& cameras, const Frames& yFrames, unsigned int maxFrameWidth, SharedAnyCameras& downscaledCameras, Frames& downscaledYFrames, std::array<Scalar, 2>& scaleFactors, Worker* worker);
278};
279
280constexpr Scalar BullseyeDetectorStereo::invalidMatchingCost()
281{
282 // Arbitrarily large value that doesn't cause numerical issues.
283 return Scalar(1000);
284}
285
286} // namespace Bullseyes
287
288} // namespace Detector
289
290} // namespace CV
291
292} // namespace Ocean
293
294#endif // OCEAN_CV_DETECTOR_BULLSEYES_BULLSEYEDETECTORSTEREO_H
This class implements the abstract base class for all AnyCamera objects.
Definition AnyCamera.h:131
This class holds the most important parameters for the detector.
Definition BullseyeDetectorMono.h:71
This class represents a candidate bullseye match between two stereo cameras.
Definition BullseyeDetectorStereo.h:109
static Vector3 invalidBullseyeCenter()
Returns an invalid bullseye center value used as a sentinel for uninitialized positions.
const Vector3 & center() const
Returns the triangulated 3D center position.
bool isValid() const
Returns whether this candidate is valid.
Candidate()=default
Creates a default (invalid) candidate.
Candidate(const Vector3 &center, const Scalar reprojectionErrorA, const Scalar reprojectionErrorB)
Creates a new candidate with the specified parameters.
Scalar reprojectionErrorA() const
Returns the reprojection error for camera A.
Scalar reprojectionErrorB() const
Returns the reprojection error for camera B.
This class holds the most important parameters for the stereo detector.
Definition BullseyeDetectorStereo.h:65
Parameters()=default
Creates a new parameter object with default parameters.
unsigned int maxFrameWidth() const noexcept
Returns the maximum frame width before downscaling is applied.
This class implements a stereo detector for bullseye patterns.
Definition BullseyeDetectorStereo.h:42
static CandidateMap extractBullseyeCandidates(const AnyCamera &cameraA, const AnyCamera &cameraB, const HomogenousMatrix4 &world_T_cameraA, const HomogenousMatrix4 &world_T_cameraB, const Bullseyes &bullseyesA, const Bullseyes &bullseyesB)
Extracts and validates candidate bullseye matches between two stereo cameras.
std::vector< BullseyePair > BullseyePairs
Definition of a vector holding bullseye pairs.
Definition BullseyeDetectorStereo.h:53
static bool triangulateBullseye(const AnyCamera &cameraA, const AnyCamera &cameraB, const HomogenousMatrix4 &world_T_cameraA, const HomogenousMatrix4 &world_T_cameraB, const Bullseye &bullseyeA, const Bullseye &bullseyeB, Vector3 &bullseyeCenter, Scalar &reprojectionErrorA, Scalar &reprojectionErrorB)
Triangulates a single matched bullseye pair to compute its 3D position in world coordinates.
std::unordered_map< IndexPair32, Candidate, PairHash > CandidateMap
Definition of an unordered map holding candidate bullseyes.
Definition BullseyeDetectorStereo.h:175
static bool detectBullseyes(const SharedAnyCameras &cameras, const Frames &yFrames, const HomogenousMatrix4 &world_T_device, const HomogenousMatrices4 &device_T_cameras, BullseyePairs &bullseyePairs, Vectors3 &bullseyeCenters, const Parameters &parameters=Parameters::defaultParameters(), Worker *worker=nullptr)
Detects bullseyes in a pair of stereo frames.
std::pair< Bullseye, Bullseye > BullseyePair
Definition of a pair of bullseyes.
Definition BullseyeDetectorStereo.h:48
static bool downscaleFramesAndCameras(const SharedAnyCameras &cameras, const Frames &yFrames, unsigned int maxFrameWidth, SharedAnyCameras &downscaledCameras, Frames &downscaledYFrames, std::array< Scalar, 2 > &scaleFactors, Worker *worker)
Downscales frames and cameras if they exceed the maximum frame width.
std::array< Bullseyes, 2 > BullseyeGroup
Definition of a pair of vectors of bullseyes, one from each camera.
Definition BullseyeDetectorStereo.h:58
static bool computeCostMatrix(const AnyCamera &cameraA, const AnyCamera &cameraB, const Bullseyes &bullseyesA, const Bullseyes &bullseyesB, const CandidateMap &candidateMap, Matrix &costMatrix)
Computes a cost matrix for matching bullseyes based on candidate triangulation results.
static bool extractBullseyes(const AnyCamera &cameraA, const AnyCamera &cameraB, const Bullseyes &bullseyesA, const Bullseyes &bullseyesB, const CandidateMap &candidateMap, BullseyePairs &bullseyePairs, Vectors3 &bullseyeCenters)
Extracts the final bullseye pairs and their 3D centers from candidate matches.
Definition of a bullseye composed of a location and a radius.
Definition Bullseye.h:32
This class implements a worker able to distribute function calls over different threads.
Definition Worker.h:33
std::vector< Frame > Frames
Definition of a vector holding padding frames.
Definition Frame.h:1842
float Scalar
Definition of a scalar type.
Definition Math.h:129
std::vector< HomogenousMatrix4 > HomogenousMatrices4
Definition of a vector holding HomogenousMatrix4 objects.
Definition HomogenousMatrix4.h:73
std::vector< Vector3 > Vectors3
Definition of a vector holding Vector3 objects.
Definition Vector3.h:65
SharedAnyCamerasT< Scalar > SharedAnyCameras
Definition of a vector holding AnyCamera objects.
Definition AnyCamera.h:91
std::vector< Bullseye > Bullseyes
Definition of a vector holding bullseyes.
Definition Bullseye.h:113
The namespace covering the entire Ocean framework.
Definition Accessor.h:15