Ocean
Loading...
Searching...
No Matches
QRCodeDetector2D.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
15
16#if defined(OCEAN_QRCODES_QRCODEDEBUGELEMENTS_ENABLED)
18#endif
19
20#include "ocean/base/Frame.h"
21
23#include "ocean/math/Vector2.h"
24
25namespace Ocean
26{
27
28namespace CV
29{
30
31namespace Detector
32{
33
34namespace QRCodes
35{
36
37/**
38 * This class implements a detector for QR Codes.
39 * @ingroup cvdetectorqrcodes
40 */
41class OCEAN_CV_DETECTOR_QRCODES_EXPORT QRCodeDetector2D : public QRCodeDetector
42{
43 public:
44
45 /**
46 * Definition of an observation of QR code in 2D
47 */
49 {
50 public:
51
52 /**
53 * Creates an invalid observation
54 */
55 Observation() = default;
56
57 /**
58 * Creates an valid observation
59 * @param code_T_camera The transformation that maps 3D coordinates in the QR code grid to the camera frame of reference, i.e., `imagePoint = anyCamera.projectToImage(code_T_camera, codePoint)`
60 * @param finderPatterns The three finder patterns of the QR Codes, elements must be in the order: top-left, bottom-left, top-right
61 */
62 inline explicit Observation(const HomogenousMatrix4& code_T_camera, FinderPatternTriplet&& finderPatterns);
63
64 /**
65 * Returns if the observation is valid
66 * @return True if the observation is valid, otherwise false
67 */
68 inline bool isValid() const;
69
70 /**
71 * Returns the transformation that maps coordinates in the QR code grid to coordinates in the reference frame of the camera
72 * @return The transformation
73 */
74 inline const HomogenousMatrix4& code_T_camera() const;
75
76 /**
77 * Returns a pointer to the finder patterns
78 * @return The finder patterns
79 */
80 inline const FinderPatternTriplet& finderPatterns() const;
81
82 protected:
83
84 /// The transformation that maps 3D coordinates in the QR code grid to the camera frame of reference, i.e., `imagePoint = anyCamera.projectToImage(code_T_camera, codePoint)`
85 HomogenousMatrix4 code_T_camera_ = HomogenousMatrix4(false);
86
87 /// The finder patterns of the QR code, order: top-left, bottom-left, top-right
89 };
90
91 /// Definition of a vector of observations
92 using Observations = std::vector<Observation>;
93
94 public:
95
96 /**
97 * Detects QR codes in an 8-bit grayscale image without lens distortion.
98 * Use this function for images without lens distortion, for example from pinhole cameras, screenshots, or similar.
99 * @param yFrame The frame in which QR codes will be detected, must be valid, have its origin in the upper left corner, and have a pixel format that is compatible with Y8, minimum size is 29 x 29 pixels
100 * @param observations Optional observations of the detected QR codes that will be returned, will be ignored for `nullptr`
101 * @param worker Optional worker instance for parallelization
102 * @param anyCamera The optionally returned camera profile that has been assumed internally
103 * @param detectInvertedReflectance True to additionally detect bright QR codes on a dark background
104 * @return The list of detected QR codes
105 */
106 static inline QRCodes detectQRCodes(const Frame& yFrame, Observations* observations = nullptr, Worker* worker = nullptr, SharedAnyCamera* anyCamera = nullptr, const bool detectInvertedReflectance = false);
107
108 /**
109 * Detects QR codes in an 8-bit grayscale image with lens distortions
110 * Use this function for images with lens distortions, for example fisheye lenses on head-mounted devices (HMD). This requires a calibrated camera.
111 * @param anyCamera The camera profile that produced the input image, must be valid
112 * @param yFrame The frame in which QR codes will be detected, must be valid, match the camera size, have its origin in the upper left corner, and have a pixel format that is compatible with Y8, minimum size is 29 x 29 pixels
113 * @param observations Optional observations of the detected QR codes that will be returned, will be ignored for `nullptr`
114 * @param worker Optional worker instance for parallelization
115 * @param detectInvertedReflectance True to additionally detect bright QR codes on a dark background
116 * @return The list of detected QR codes
117 */
118 static inline QRCodes detectQRCodes(const AnyCamera& anyCamera, const Frame& yFrame, Observations* observations = nullptr, Worker* worker = nullptr, const bool detectInvertedReflectance = false);
119
120 /**
121 * Detects QR codes in an 8-bit grayscale image
122 * @param anyCamera The camera profile that produced the input image, must be valid
123 * @param yFrame The frame in which QR codes will be detected, must be valid, match the camera size, have its origin in the upper left corner, and have a pixel format that is compatible with Y8
124 * @param width The width of the input frame, range: [29, infinity)
125 * @param height The height of the input frame, range: [29, infinity)
126 * @param paddingElements The number of padding elements of the input frame, range: [0, infinity)
127 * @param observations Optional observations of the detected QR codes that will be returned, will be ignored for `nullptr`
128 * @param worker Optional worker instance for parallelization
129 * @param detectInvertedReflectance True to additionally detect bright QR codes on a dark background
130 * @return The list of detected QR codes
131 */
132 static QRCodes detectQRCodes(const AnyCamera& anyCamera, const uint8_t* const yFrame, const unsigned int width, const unsigned int height, const unsigned int paddingElements, Observations* observations = nullptr, Worker* worker = nullptr, const bool detectInvertedReflectance = false);
133};
134
136 code_T_camera_(code_T_camera),
137 finderPatterns_(std::move(finderPatterns))
138{
139 ocean_assert(isValid());
140}
141
143{
144 return code_T_camera_.isValid() &&
145 // Finder pattern locations must be different
146 Numeric::isNotEqualEps(finderPatterns_[1].position().sqrDistance(finderPatterns_[0].position())) &&
147 Numeric::isNotEqualEps(finderPatterns_[2].position().sqrDistance(finderPatterns_[1].position())) &&
148 Numeric::isNotEqualEps(finderPatterns_[0].position().sqrDistance(finderPatterns_[2].position())) &&
149 // Ensure counter-clockwise order of the finder patterns
150 (finderPatterns_[1].position() - finderPatterns_[0].position()).cross(finderPatterns_[0].position() - finderPatterns_[2].position()) >= Scalar(0) &&
151 (finderPatterns_[2].position() - finderPatterns_[1].position()).cross(finderPatterns_[1].position() - finderPatterns_[0].position()) >= Scalar(0) &&
152 (finderPatterns_[0].position() - finderPatterns_[2].position()).cross(finderPatterns_[2].position() - finderPatterns_[1].position()) >= Scalar(0);
153}
154
156{
157 return code_T_camera_;
158}
159
161{
162 return finderPatterns_;
163}
164
165inline QRCodes QRCodeDetector2D::detectQRCodes(const Frame& yFrame, Observations* observations, Worker* worker, SharedAnyCamera* sharedAnyCamera, const bool detectInvertedReflectance)
166{
168 {
169 ocean_assert(false && "Frame must be valid and an 8 bit grayscale image and the pixel origin must be the upper left corner");
170 return QRCodes();
171 }
172
173 Scalar fovX = Numeric::deg2rad(60);
174
175 if (yFrame.height() > yFrame.width())
176 {
177 // Avoid large FOV values for pinhole cameras.
178 fovX = AnyCamera::fovY2X(fovX, Scalar(yFrame.width()) / Scalar(yFrame.height()));
179 }
180
181 ocean_assert(fovX > Scalar(0));
182
183 AnyCameraPinhole anyCamera(PinholeCamera(yFrame.width(), yFrame.height(), fovX));
184
185 QRCodes codes = detectQRCodes(anyCamera, yFrame, observations, worker, detectInvertedReflectance);
186
187 if (sharedAnyCamera)
188 {
189 *sharedAnyCamera = std::make_shared<AnyCameraPinhole>(std::move(anyCamera));
190 }
191
192 return codes;
193}
194
195inline QRCodes QRCodeDetector2D::detectQRCodes(const AnyCamera& anyCamera, const Frame& yFrame, Observations* observations, Worker* worker, const bool detectInvertedReflectance)
196{
198 {
199 ocean_assert(false && "Frame must be valid and an 8 bit grayscale image and the pixel origin must be the upper left corner");
200 return QRCodes();
201 }
202
203 return detectQRCodes(anyCamera, yFrame.constdata<uint8_t>(), yFrame.width(), yFrame.height(), yFrame.paddingElements(), observations, worker, detectInvertedReflectance);
204}
205
206} // namespace QRCodes
207
208} // namespace Detector
209
210} // namespace CV
211
212} // namespace Ocean
This class implements the abstract base class for all AnyCamera objects.
Definition AnyCamera.h:131
This class implements a specialized AnyCamera object wrapping the actual camera model.
Definition AnyCamera.h:638
Definition of an observation of QR code in 2D.
Definition QRCodeDetector2D.h:49
FinderPatternTriplet finderPatterns_
The finder patterns of the QR code, order: top-left, bottom-left, top-right.
Definition QRCodeDetector2D.h:88
const FinderPatternTriplet & finderPatterns() const
Returns a pointer to the finder patterns.
Definition QRCodeDetector2D.h:160
Observation()=default
Creates an invalid observation.
const HomogenousMatrix4 & code_T_camera() const
Returns the transformation that maps coordinates in the QR code grid to coordinates in the reference ...
Definition QRCodeDetector2D.h:155
bool isValid() const
Returns if the observation is valid.
Definition QRCodeDetector2D.h:142
This class implements a detector for QR Codes.
Definition QRCodeDetector2D.h:42
std::vector< Observation > Observations
Definition of a vector of observations.
Definition QRCodeDetector2D.h:92
static QRCodes detectQRCodes(const AnyCamera &anyCamera, const uint8_t *const yFrame, const unsigned int width, const unsigned int height, const unsigned int paddingElements, Observations *observations=nullptr, Worker *worker=nullptr, const bool detectInvertedReflectance=false)
Detects QR codes in an 8-bit grayscale image.
static QRCodes detectQRCodes(const Frame &yFrame, Observations *observations=nullptr, Worker *worker=nullptr, SharedAnyCamera *anyCamera=nullptr, const bool detectInvertedReflectance=false)
Detects QR codes in an 8-bit grayscale image without lens distortion.
Definition QRCodeDetector2D.h:165
This class implements common functionality of QR code detectors but is not a stand-alone detector.
Definition QRCodeDetector.h:33
static T fovY2X(const T fovY, const T aspectRatio)
Calculates the horizontal FOV from the vertical FOV and the aspect ratio of the camera image.
Definition Camera.h:462
This class implements Ocean's image class.
Definition Frame.h:1969
const T * constdata(const unsigned int planeIndex=0u) const
Returns a pointer to the read-only pixel data of a specific plane.
Definition Frame.h:4425
bool isValid() const
Returns whether this frame is valid.
Definition Frame.h:4705
unsigned int paddingElements(const unsigned int planeIndex=0u) const
Returns the optional number of padding elements at the end of each row for a specific plane.
Definition Frame.h:4299
@ FORMAT_Y8
Pixel format for grayscale images with byte order Y and 8 bits per pixel.
Definition Frame.h:596
unsigned int width() const
Returns the width of the frame format in pixel.
Definition Frame.h:3334
PixelOrigin pixelOrigin() const
Returns the pixel origin of the frame.
Definition Frame.h:3379
static bool arePixelFormatsCompatible(const PixelFormat pixelFormatA, const PixelFormat pixelFormatB)
Returns whether two given pixel formats are compatible.
PixelFormat pixelFormat() const
Returns the pixel format of the frame.
Definition Frame.h:3344
@ ORIGIN_UPPER_LEFT
The first pixel lies in the upper left corner, the last pixel in the lower right corner.
Definition Frame.h:1140
unsigned int height() const
Returns the height of the frame in pixel.
Definition Frame.h:3339
static constexpr T deg2rad(const T deg)
Converts deg to rad.
Definition Numeric.h:3241
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2246
This class implements a worker able to distribute function calls over different threads.
Definition Worker.h:33
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition base/Utilities.h:1159
std::array< FinderPattern, 3 > FinderPatternTriplet
Definition of a 3-tuple of finder patterns.
Definition FinderPatternDetector.h:198
PinholeCameraT< Scalar > PinholeCamera
Definition of an pinhole camera object with Scalar precision.
Definition PinholeCamera.h:39
float Scalar
Definition of a scalar type.
Definition Math.h:129
std::shared_ptr< AnyCamera > SharedAnyCamera
Definition of a shared pointer holding an AnyCamera object with Scalar precision.
Definition AnyCamera.h:61
std::vector< QRCode > QRCodes
Definition of a vector of QR codes.
Definition QRCode.h:28
The namespace covering the entire Ocean framework.
Definition Accessor.h:15