Ocean
QRCodeDetector3D.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 #pragma once
9 
11 
14 
15 #if defined(OCEAN_QRCODES_QRCODEDEBUGELEMENTS_ENABLED)
17 #endif
18 
19 #include "ocean/base/Frame.h"
20 
21 #include "ocean/math/AnyCamera.h"
22 #include "ocean/math/Vector2.h"
23 
24 namespace Ocean
25 {
26 
27 namespace CV
28 {
29 
30 namespace Detector
31 {
32 
33 namespace QRCodes
34 {
35 
36 /**
37  * This class implements a 6-DOF detector for QR codes.
38  * @ingroup cvdetectorqrcodes
39  */
40 class OCEAN_CV_DETECTOR_QRCODES_EXPORT QRCodeDetector3D : public QRCodeDetector
41 {
42  public:
43 
44  /**
45  * Detects QR codes their 6-DOF poses in two synchronized 8-bit grayscale images
46  * @param sharedAnyCameras The cameras that produced the input images, must have 2 elements, all elements must be valid
47  * @param yFrames The frames in which QR codes will be detected, must be valid, must have 2 elements, origin must be in the upper left corner, and have a pixel format that is compatible with Y8, minimum size is 29 x 29 pixels
48  * @param world_T_device The transformation that maps points in the device coordinate system points to world points, must be valid
49  * @param device_T_cameras The transformation that converts points in the camera coordinate systems to device coordinates, `devicePoint = device_T_cameras[i] * cameraPoint`, must have the same number of elements as `yFrames`, all elements must be valid
50  * @param codes The resulting list of detected QR codes
51  * @param world_T_codes The resulting 6-DOF poses the detected QR codes, number of elements will be identical to `codes`
52  * @param codeSizes The resulting edge lengths of the detected QR codes in meters, number of elements will be identical to `codes`
53  * @param worker Optional worker instance for parallelization
54  * @param allow2DCodes If true, the detector will also report back QR codes which have been detected in only one camera (2D detections), however, their 6-DOF pose and size (edge length) will not be accurate; otherwise only 3D detection will be reported
55  * @return True if one or more QR code has been detected, otherwise false
56  */
57  static bool detectQRCodes(const SharedAnyCameras& sharedAnyCameras, const Frames& yFrames, const HomogenousMatrix4& world_T_device, const HomogenousMatrices4& device_T_cameras, QRCodes& codes, HomogenousMatrices4& world_T_codes, Scalars& codeSizes, Worker* worker = nullptr, const bool allow2DCodes = false);
58 
59  /**
60  * Detects QR codes their 6-DOF poses in two synchronized 8-bit grayscale images
61  * @param sharedAnyCameras The cameras that produced the input images, must have 2 elements, all elements must be valid
62  * @param yFrames The frames in which QR codes will be detected, must be valid, must have 2 elements, origin must be in the upper left corner, and have a pixel format that is compatible with Y8, minimum size is 29 x 29 pixels
63  * @param world_T_device The transformation that maps points in the device coordinate system points to world points, must be valid
64  * @param device_T_cameras The transformation that converts points in the camera coordinate systems to device coordinates, `devicePoint = device_T_cameras[i] * cameraPoint`, must have the same number of elements as `yFrames`, all elements must be valid
65  * @param codes The resulting list of detected QR codes
66  * @param world_T_codes The resulting 6-DOF poses the detected QR codes, number of elements will be identical to `codes`
67  * @param codeSizes The resulting edge lengths of the detected QR codes in meters, number of elements will be identical to `codes`
68  * @param worker Optional worker instance for parallelization
69  * @param allow2DCodes If true, the detector will also report back QR codes which have been detected in only one camera (2D detections), however, their 6-DOF pose and size (edge length) will not be accurate; otherwise only 3D detection will be reported
70  * @return True if one or more QR code has been detected, otherwise false
71  */
72  static bool detectQRCodesWithPyramids(const SharedAnyCameras& sharedAnyCameras, const Frames& yFrames, const HomogenousMatrix4& world_T_device, const HomogenousMatrices4& device_T_cameras, QRCodes& codes, HomogenousMatrices4& world_T_codes, Scalars& codeSizes, Worker* worker = nullptr, const bool allow2DCodes = false);
73 
74  /**
75  * Returns an invalid size for QR codes
76  * @return The invalid size value
77  */
78  static inline Scalar getInvalidCodeSize();
79 
80  /**
81  * Returns an invalid 6-DOF pose for a QR codes
82  * @return The invalid size value
83  */
84  static inline const HomogenousMatrix4& getInvalidWorld_T_code();
85 
86  protected:
87 
88  /**
89  * Triangulates the centers of corresponding observations of finder patterns from two different views
90  * @param sharedAnyCameraA The camera that produced the observation of the first finder pattern, must be valid
91  * @param sharedAnyCameraB The camera that produced the observation of the second finder pattern, must be valid
92  * @param world_T_device The transformation that maps points in the device coordinate system points to world points, must be valid
93  * @param device_T_cameraA The transformation that converts points in the coordinate systems of the first camera to device coordinates, must be valid
94  * @param device_T_cameraB The transformation that converts points in the coordinate systems of the first camera to device coordinates, must be valid
95  * @param finderPatternTripletA The first finder pattern of the corresponding pair, must be valid
96  * @param finderPatternTripletB The second finder pattern of the corresponding pair, must be valid
97  * @param worldPoints The resulting locations of the finder pattern centers in world coordinates, will have three elements
98  * @param averageFinderPatternCenterDistance The average distance between the centers of the top-left and top-right as well as the top-left and the bottom-left finder patterns
99  * @return True if the centers of the finder patterns have been triangulated successfully, otherwise false
100  */
101  static bool triangulateFinderPatternsStereo(const SharedAnyCamera& sharedAnyCameraA, const SharedAnyCamera& sharedAnyCameraB, const HomogenousMatrix4& world_T_device, const HomogenousMatrix4& device_T_cameraA, const HomogenousMatrix4& device_T_cameraB, const FinderPatternTriplet& finderPatternTripletA, const FinderPatternTriplet& finderPatternTripletB, Vectors3& worldPoints, Scalar& averageFinderPatternCenterDistance);
102 
103  /**
104  * Computes the pose of a QR code and extracts it payload given a pair of corresponding finder patterns
105  * @param yFrameA The frame that contain the observation of the first finder pattern, must be valid
106  * @param yFrameB The frame that contain the observation of the second finder pattern, must be valid
107  * @param sharedAnyCameraA The camera that produced the observation of the first finder pattern, must be valid
108  * @param sharedAnyCameraB The camera that produced the observation of the second finder pattern, must be valid
109  * @param world_T_device The transformation that maps points in the device coordinate system points to world points, must be valid
110  * @param device_T_cameraA The transformation that converts points in the coordinate systems of the first camera to device coordinates, must be valid
111  * @param device_T_cameraB The transformation that converts points in the coordinate systems of the first camera to device coordinates, must be valid
112  * @param finderPatternTripletA The first finder pattern of the corresponding pair, must be valid
113  * @param finderPatternTripletB The second finder pattern of the corresponding pair, must be valid
114  * @param worldPoints The locations of the finder pattern centers in world coordinates, will have three elements
115  * @param averageFinderPatternCenterDistance The average distance between the centers of the top-left and top-right as well as the top-left and the bottom-left finder patterns
116  * @param code The resulting QR code that was extracted
117  * @param world_T_code The resulting pose of the code in world coordinates
118  * @param codeSize The resulting (display) size of the extracted code in the physical world (in meters)
119  * @param version Optional indicator of the version number that the code might have (e.g. if it has been observed before), range: [1, 40] or -1 to determine it automatically
120  * @return True if the extraction of the code and computation its pose was successful, otherwise false
121  * @sa triangulateFinderPatternsStereo()
122  */
123  static bool computePoseAndExtractQRCodeStereo(const Frame& yFrameA, const Frame& yFrameB, const SharedAnyCamera& sharedAnyCameraA, const SharedAnyCamera& sharedAnyCameraB, const HomogenousMatrix4& world_T_device, const HomogenousMatrix4& device_T_cameraA, const HomogenousMatrix4& device_T_cameraB, const FinderPatternTriplet& finderPatternTripletA, const FinderPatternTriplet& finderPatternTripletB, const Vectors3& worldPoints, const Scalar& averageFinderPatternCenterDistance, CV::Detector::QRCodes::QRCode& code, HomogenousMatrix4& world_T_code, Scalar& codeSize, const unsigned int version = (unsigned int)(-1));
124 
125  /**
126  * Computes the 6DOF pose of a QR code from a pair of cameras
127  * @param sharedAnyCameraA The first camera that will be used to compute the pose of a code, must be valid
128  * @param sharedAnyCameraB The second camera that will be used to compute the pose of a code, must be valid
129  * @param yFrameA The first image frame that contains an image of the code, must be valid
130  * @param yFrameB The second image frame that contains an image of the code, must be valid
131  * @param world_T_device The transformation that maps points in the device coordinate system points to world points, must be valid
132  * @param device_T_cameraA The transformation that converts points in the coordinate systems of the first camera to device coordinates, must be valid
133  * @param device_T_cameraB The transformation that converts points in the coordinate systems of the second camera to device coordinates, must be valid
134  * @param finderPatternTripletA The triplets of finder patterns of the code in the first image, must be valid
135  * @param finderPatternTripletB The triplets of finder patterns of the code in the second image, must be valid
136  * @param worldPoints The world points from the triangulation of the two finder pattern triplets, must have three elements and be in front of the camera
137  * @param version The version number that the code is believed to have, range: [1, 40]
138  * @param codeSize The code size (in meters) that the code is believed to have, range: (0, infinity)
139  * @param world_T_code The resulting 6DOF pose of the code; in the code space the x- and y-axis range from [-codeSize/2, codeSize/2] and z = 0 (> 0 will be above the code, < 0 will be below the code)
140  * @return True if a pose was computed successfully, otherwise false
141  */
142  static bool computePoseStereo(const SharedAnyCamera& sharedAnyCameraA, const SharedAnyCamera& sharedAnyCameraB, const Frame& yFrameA, const Frame& yFrameB, const HomogenousMatrix4& world_T_device, const HomogenousMatrix4& device_T_cameraA, const HomogenousMatrix4& device_T_cameraB, const FinderPatternTriplet& finderPatternTripletA, const FinderPatternTriplet& finderPatternTripletB, const Vector3* worldPoints, const unsigned int version, const Scalar codeSize, HomogenousMatrix4& world_T_code);
143 
144  /**
145  * Computes the square projection error given a 6DOF pose of a code
146  * @param anyCamera The camera into which the code will be projected, must be valid
147  * @param world_T_camera The 6DOF pose of the camera in world coordinates, must be valid
148  * @param world_T_code The 6DOF pose of the code that will be used to project the code, must be valid
149  * @param finderPatternTriplet The triplet of finder patterns of which the center points will be used to compute the projection error, must be valid
150  * @param version The version number of the code that is project, range: [1, 40]
151  * @param codeSize_2 The half value of the code (in meters) that is projected, range: (0, infinity)
152  * @return The square sum of the projection error
153  */
154  static Scalar computeSquaredProjectionError(const SharedAnyCamera& anyCamera, const HomogenousMatrix4& world_T_camera, const HomogenousMatrix4& world_T_code, const FinderPatternTriplet& finderPatternTriplet, const unsigned int version, const Scalar codeSize_2);
155 };
156 
158 {
159  return Scalar(-1.0);
160 }
161 
163 {
164  const static HomogenousMatrix4 invalidWorld_T_code(false);
165 
166  return invalidWorld_T_code;
167 }
168 
169 } // namespace QRCodes
170 
171 } // namespace Detector
172 
173 } // namespace CV
174 
175 } // namespace Ocean
This class implements a 6-DOF detector for QR codes.
Definition: QRCodeDetector3D.h:41
static bool detectQRCodesWithPyramids(const SharedAnyCameras &sharedAnyCameras, const Frames &yFrames, const HomogenousMatrix4 &world_T_device, const HomogenousMatrices4 &device_T_cameras, QRCodes &codes, HomogenousMatrices4 &world_T_codes, Scalars &codeSizes, Worker *worker=nullptr, const bool allow2DCodes=false)
Detects QR codes their 6-DOF poses in two synchronized 8-bit grayscale images.
static bool computePoseStereo(const SharedAnyCamera &sharedAnyCameraA, const SharedAnyCamera &sharedAnyCameraB, const Frame &yFrameA, const Frame &yFrameB, const HomogenousMatrix4 &world_T_device, const HomogenousMatrix4 &device_T_cameraA, const HomogenousMatrix4 &device_T_cameraB, const FinderPatternTriplet &finderPatternTripletA, const FinderPatternTriplet &finderPatternTripletB, const Vector3 *worldPoints, const unsigned int version, const Scalar codeSize, HomogenousMatrix4 &world_T_code)
Computes the 6DOF pose of a QR code from a pair of cameras.
static bool computePoseAndExtractQRCodeStereo(const Frame &yFrameA, const Frame &yFrameB, const SharedAnyCamera &sharedAnyCameraA, const SharedAnyCamera &sharedAnyCameraB, const HomogenousMatrix4 &world_T_device, const HomogenousMatrix4 &device_T_cameraA, const HomogenousMatrix4 &device_T_cameraB, const FinderPatternTriplet &finderPatternTripletA, const FinderPatternTriplet &finderPatternTripletB, const Vectors3 &worldPoints, const Scalar &averageFinderPatternCenterDistance, CV::Detector::QRCodes::QRCode &code, HomogenousMatrix4 &world_T_code, Scalar &codeSize, const unsigned int version=(unsigned int)(-1))
Computes the pose of a QR code and extracts it payload given a pair of corresponding finder patterns.
static const HomogenousMatrix4 & getInvalidWorld_T_code()
Returns an invalid 6-DOF pose for a QR codes.
Definition: QRCodeDetector3D.h:162
static bool detectQRCodes(const SharedAnyCameras &sharedAnyCameras, const Frames &yFrames, const HomogenousMatrix4 &world_T_device, const HomogenousMatrices4 &device_T_cameras, QRCodes &codes, HomogenousMatrices4 &world_T_codes, Scalars &codeSizes, Worker *worker=nullptr, const bool allow2DCodes=false)
Detects QR codes their 6-DOF poses in two synchronized 8-bit grayscale images.
static Scalar computeSquaredProjectionError(const SharedAnyCamera &anyCamera, const HomogenousMatrix4 &world_T_camera, const HomogenousMatrix4 &world_T_code, const FinderPatternTriplet &finderPatternTriplet, const unsigned int version, const Scalar codeSize_2)
Computes the square projection error given a 6DOF pose of a code.
static bool triangulateFinderPatternsStereo(const SharedAnyCamera &sharedAnyCameraA, const SharedAnyCamera &sharedAnyCameraB, const HomogenousMatrix4 &world_T_device, const HomogenousMatrix4 &device_T_cameraA, const HomogenousMatrix4 &device_T_cameraB, const FinderPatternTriplet &finderPatternTripletA, const FinderPatternTriplet &finderPatternTripletB, Vectors3 &worldPoints, Scalar &averageFinderPatternCenterDistance)
Triangulates the centers of corresponding observations of finder patterns from two different views.
static Scalar getInvalidCodeSize()
Returns an invalid size for QR codes.
Definition: QRCodeDetector3D.h:157
This class implements common functionality of QR code detectors but is not a stand-alone detector.
Definition: QRCodeDetector.h:33
Definition of a QR code.
Definition: QRCode.h:35
This class implements Ocean's image class.
Definition: Frame.h:1792
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:1755
std::array< FinderPattern, 3 > FinderPatternTriplet
Definition of a 3-tuple of finder patterns.
Definition: FinderPatternDetector.h:198
float Scalar
Definition of a scalar type.
Definition: Math.h:128
std::vector< HomogenousMatrix4 > HomogenousMatrices4
Definition of a vector holding HomogenousMatrix4 objects.
Definition: HomogenousMatrix4.h:73
std::shared_ptr< AnyCamera > SharedAnyCamera
Definition of a shared pointer holding an AnyCamera object with Scalar precision.
Definition: AnyCamera.h:60
std::vector< Scalar > Scalars
Definition of a vector holding Scalar objects.
Definition: Math.h:144
SharedAnyCamerasT< Scalar > SharedAnyCameras
Definition of a vector holding AnyCamera objects.
Definition: AnyCamera.h:90
std::vector< Vector3 > Vectors3
Definition of a vector holding Vector3 objects.
Definition: Vector3.h:65
std::vector< QRCode > QRCodes
Definition of a vector of QR codes.
Definition: QRCode.h:25
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15