Ocean
cv/detector/qrcodes/Utilities.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 
16 
17 #include "ocean/base/Worker.h"
18 
19 #include "ocean/cv/Bresenham.h"
20 #include "ocean/cv/Canvas.h"
21 
22 #include "ocean/math/AnyCamera.h"
23 #include "ocean/math/Vector2.h"
24 
25 namespace Ocean
26 {
27 
28 namespace CV
29 {
30 
31 namespace Detector
32 {
33 
34 namespace QRCodes
35 {
36 
37 /**
38  * Definition of utility functions related to the detection of QR codes
39  * @ingroup cvdetectorqrcodes
40  */
41 class OCEAN_CV_DETECTOR_QRCODES_EXPORT Utilities
42 {
43  public:
44 
45  /**
46  * Definition of return codes of the parsing function for the Wi-Fi configurations
47  */
48  enum ParsingStatus : uint32_t
49  {
50  /// Indicates that parsing was successful
51  PS_SUCCESS = 0u,
52  /// Indicates that the input has an invalid prefix
54  /// Indicates that a field uses an invalid format, for example it isn't closed correctly
56  /// Indicates that the content of a field is invalid, missing, or could not be processed correctly
58  /// Indicates that field type is unknown or invalid
60  /// Indicates that a field has been found multiple times when it should have been unique
62  /// Indicates that the config is terminated correctly
63  PS_ERROR_INVALID_TERMINATION
64  };
65 
66  /**
67  * Definition of a helper class to convert between the coordinate systems that are used for QR codes.
68  *
69  * The default coordinate system (code space) for the 2D locations of the modules is defined as follows (similar to images):
70  * * the x-axis points right,
71  * * the y-axis points down, and
72  * * the origin is in the top-left corner of the QR code
73  * * the pixel origin is in the top-left corner of each pixel
74  *
75  * In the example below, `s` is the number of modules per side:
76  *
77  * <pre>
78  * (0, 0) (s, 0)
79  * o-------+----> x-axis
80  * | |
81  * | |
82  * | |
83  * +-------+
84  * (0, s) | (s, s)
85  * v
86  * y-axis
87  * </pre>
88  *
89  * The coordinate system for 3D locations of modules in its (normalized) object space is defined as follows:
90  * * the x-axis points right in the QR code plane
91  * * the y-axis points up in the QR code plane
92  * * the z-axis points upwards (normal of the QR code plane, pointing towards the camera)
93  * * the origin is in the center of the QR code
94  * * the pixel origin is in the center of each pixel
95  *
96  * <pre>
97  * y
98  * (-1, 1, 0) ^ (1, 1, 0)
99  * +---|---+
100  * | | |
101  * | o-----> x
102  * | |
103  * +-------+
104  * (-1, -1, 0) (1, -1, 0)
105  * </pre>
106  *
107  * The conversion from the first coordinate system (2D) to normalized object space (3D) is defined as follows:
108  *
109  * <pre>
110  * x' = ((2 / s) * x) - 1
111  * y' = ((-2 / s) * y) + 1
112  * z' = 0
113  * </pre>
114  */
115  class OCEAN_CV_DETECTOR_QRCODES_EXPORT CoordinateSystemBase
116  {
117  public:
118 
119  /**
120  * The default constructor
121  */
122  virtual ~CoordinateSystemBase() = default;
123 
124  /**
125  * Returns the scaling factor that is used for coordinate scaling
126  * @return The scaling factor
127  */
128  inline Scalar scale() const;
129 
130  /**
131  * Converts an x-coordinate from code space to object space
132  * @param xCodeSpace The coordinate that will be converted from code to object space, pixel origin is assumed to be in the pixel center (add 0.5, if applicable)
133  * @return The coordinate converted to object space
134  */
135  inline Scalar convertCodeSpaceToObjectSpaceX(const Scalar xCodeSpace) const;
136 
137  /**
138  * Converts an y-coordinate from code space to object space
139  * @param yCodeSpace The coordinate that will be converted from code to object space, pixel origin is assumed to be in the pixel center (add 0.5, if applicable)
140  * @return The coordinate converted to object space
141  */
142  inline Scalar convertCodeSpaceToObjectSpaceY(const Scalar yCodeSpace) const;
143 
144  /**
145  * Compute the locations of the four corners of a code in object space
146  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
147  * @param scale Optional scaling factor for the coordinates in the object space, range: (0, infinity)
148  * @return The 4 corners in object space in the order top-left, bottom-left, bottom-right, and top-right.
149  */
150  static inline Vectors3 computeCornersInObjectSpace(const Scalar scale = Scalar(1));
151 
152  protected:
153 
154  /**
155  * Constructs an coordinate system object
156  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
157  * @param modulesPerSide The number of modules per side of the QR code, range: [11, 177]
158  * @param scale Optional scaling factor for the coordinates in the object space, range: (0, infinity)
159  */
160  explicit CoordinateSystemBase(const unsigned int modulesPerSide, const Scalar scale = Scalar(1));
161 
162  /// The number of modules per side of the QR code, range: [11, 177]
163  unsigned int modulesPerSide_;
164 
165  /// Global factor for coordinate scaling
167 
168  /// The scale factor for x-coordinates
170 
171  /// The scale factor for y-coordinates
173  };
174 
175  /**
176  * Definition of a helper class to convert between the coordinate systems that are used for QR codes.
177  */
178  class OCEAN_CV_DETECTOR_QRCODES_EXPORT CoordinateSystem : public CoordinateSystemBase
179  {
180  public:
181 
182  /**
183  * Constructs a coordinate system object
184  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
185  * @param version The version for which the coordinate system should be prepared, range: [1, 40]
186  * @param scale Optional scaling factor for the coordinates in the object space, range: (0, infinity)
187  */
188  explicit CoordinateSystem(const unsigned int version, const Scalar scale = Scalar(1));
189 
190  /**
191  * Computes the locations of the centers of the 3 finder patterns for a specific QR code version in object space
192  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
193  * @param version The version for which the locations of the finder pattern centers will be computed, range: [1, 40]
194  * @param scale Optional scaling factor for the coordinates in the object space, range: (0, infinity)
195  * @return The 3D locations of the finder pattern centers in object space, will have 3 elements
196  */
197  static Vectors3 computeFinderPatternCentersInObjectSpace(const unsigned int version, const Scalar scale = Scalar(1));
198 
199  /**
200  * Computes the locations of alignment patterns for a specific QR code version in object space
201  * Coordinates are normalized to the range `[-1, 1]`.
202  * @param version The version for which the locations of the alignment patterns will be computed, range: [1, 40]
203  * @param scale Optional scaling factor for the coordinates in the object space, range: (0, infinity)
204  * @return The 3D locations of the alignment patterns in object space in row-wise order
205  */
206  static std::vector<Vectors3> computeAlignmentPatternsInObjectSpace(const unsigned int version, const Scalar scale = Scalar(1));
207 
208  /**
209  * Computes the locations of the version information fields for a specific QR code version in object space
210  * Coordinates are normalized to the range `[-1, 1]`.
211  * <pre>
212  * version information 1 (6 x 3 modules)
213  * |
214  * v
215  * ############## 0 1 2 ##############
216  * ## ## 3 4 5 ## ##
217  * ## ###### ## 6 7 8 ## ###### ##
218  * ## ###### ## 9 A B ## ###### ##
219  * ## ###### ## C D E ## ###### ##
220  * ## ## F G H ## ##
221  * ############## ## ## ## ## ##############
222  *
223  * ##
224  *
225  * ##
226  *
227  * 0 3 6 9 C F ##
228  * 1 4 7 A D G <-- version information 2 (3 x 6 modules)
229  * 2 5 8 B E H ##
230  *
231  * ##############
232  * ## ##
233  * ## ###### ##
234  * ## ###### ##
235  * ## ###### ##
236  * ## ##
237  * ##############
238  * </pre>
239  *
240  * @param version The version for which the locations of the version information fields will be computed, range: [1, 40]
241  * @param versionInformation1 If true, the module locations of the first field in the top right corner will be returned, otherwise the ones of the second field in the lower left corner
242  * @return The 3D locations of the 18 modules of the selected version information field in object space (in the order that they will need to be read)
243  */
244  static Vectors3 computeVersionInformationModulesInObjectSpace(const unsigned int version, const bool versionInformation1);
245  };
246 
247  /**
248  * Definition of a helper class to convert between the coordinate systems that are used for Micro QR codes.
249  */
250  class OCEAN_CV_DETECTOR_QRCODES_EXPORT MicroQRCoordinateSystem : public CoordinateSystemBase
251  {
252  public:
253 
254  /**
255  * Constructs a Micro QR coordinate system object
256  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
257  * @param version The version for which the coordinate system should be prepared, range: [1, 4]
258  * @param scale Optional scaling factor for the coordinates in the object space, range: (0, infinity)
259  */
260  explicit MicroQRCoordinateSystem(const unsigned int version, const Scalar scale = Scalar(1));
261 
262  /**
263  * Computes the location of the center of the finder pattern
264  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
265  * @return The 3D location of the finder pattern center in object space
266  */
268 
269  /**
270  * Computes the locations of the modules in the horizontal (top edge) timing pattern
271  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
272  * @return The 3D locations of the timing pattern modules in object space
273  */
275 
276  /**
277  * Computes the locations of the modules in the vertical (left edge) timing pattern
278  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
279  * @return The 3D locations of the timing pattern modules in object space
280  */
282 
283  /**
284  * Computes the locations of the corners of the finder pattern for a specific Micro QR code version in object space
285  * Coordinates are normalized to the range `[-1, 1]` or `[-scale, scale]` for `scale != 1`.
286  * @param version The version for which the locations of the finder pattern corners will be computed, range: [1, 4]
287  * @param scale Optional scaling factor for the coordinates in the object space, range: (0, infinity)
288  * @return The 3D locations of the finder pattern corners in object space
289  */
291  };
292 
293  public:
294 
295  /**
296  * Draws an unscaled image of a QR code (FORMAT_Y8), i.e. one modules corresponds to one pixel
297  * @param code The QR code that will be drawn, must be valid
298  * @param border The border that should be drawn around the QR codes in multiples of modules, range: [0, infinity)
299  * @param foregroundColor The color that the foreground modules (i.e. module value is 1) should have, range: [0, 255], this value must differ from `backgroundColor` by at least 30 intensity steps
300  * @param backgroundColor The color that the background modules (i.e. module value is 0) should have, range: [0, 255], this value must differ from `foregroundColor` by at least 30 intensity steps
301  * @return The frame holding the image of the QR code, will be invalid in case of a failure
302  */
303  static Frame draw(const QRCodeBase& code, const unsigned int border, const uint8_t foregroundColor = 0u, const uint8_t backgroundColor = 255u);
304 
305  /**
306  * Draws a scaled image of a QR code (FORMAT_Y8)
307  * @param code The QR code that will be drawn, must be valid
308  * @param frameSize The width and height of the resulting frame, range: [qrcode.modulesCount() + 2u * border, infinity)
309  * @param allowTrueMultiple True, then the value of `frameSize` may be increased to smallest multiple of `qrcode.modulesCount() + 2u * border` that is larger or equal to `frameSize`, otherwise the specified value of `frameSize` will be used
310  * @param border The border that should be drawn around the QR codes in multiple of modules, range: [0, infinity)
311  * @param worker Optional worker that is used to draw the QR code
312  * @param foregroundColor The color that the foreground modules (i.e. module value is 1) should have, range: [0, 255], this value must differ from `backgroundColor` by at least 30 intensity steps
313  * @param backgroundColor The color that the background modules (i.e. module value is 0) should have, range: [0, 255], this value must differ from `foregroundColor` by at least 30 intensity steps
314  * @return The frame holding the image of the QR code, will be invalid in case of a failure
315  */
316  static Frame draw(const QRCodeBase& code, const unsigned int frameSize, const bool allowTrueMultiple, const unsigned int border, Worker* worker = nullptr, const uint8_t foregroundColor = 0u, const uint8_t backgroundColor = 255u);
317 
318  /**
319  * Draws an observation of a QR code into a given frame.
320  * @param frame The frame in which the observation of a QR codes will be drawn, must be valid
321  * @param observation The observation of a QR codes that will be drawn, must be valid
322  * @param code The corresponding QR code
323  */
324  static inline void drawObservation(Frame& frame, const LegacyQRCodeDetector2D::Observation& observation, const QRCode& code);
325 
326  /**
327  * Draws an observation of a QR code into a given frame.
328  * @param frame The frame in which the observation of a QR codes will be drawn, must be valid
329  * @param frame_H_code The homography transformation that maps from the coordinate frame of the code into the frame, i.e. `pointInFrame = frame_H_code pointInCode`, must be valid
330  * @param finderPatterns The three detected finder patterns that are part of the QR code and which will be drawn into the frame
331  * @param version The version of the QR code, range: [1, 40]
332  * @param modules The modules of the QR codes that will be drawn into the frame, must `QRCode::modulesPerSide(version) * QRCode::modulesPerSide(version)` elements
333  */
334  static void drawObservation(Frame& frame, const SquareMatrix3& frame_H_code, const FinderPatternTriplet& finderPatterns, const unsigned int version, const std::vector<uint8_t>& modules);
335 
336  /**
337  * Draws observations of QR codes into a given frame.
338  * @param frame The frame in which the observations of the QR codes will be drawn, must be valid
339  * @param observations The observations of QR codes that will be drawn, must be valid
340  * @param codes The corresponding QR codes, must have the same size as `observations`
341  */
342  static inline void drawObservations(Frame& frame, const LegacyQRCodeDetector2D::Observations& observations, const QRCodes& codes);
343 
344  /**
345  * Draws observations of QR codes into a given frame.
346  * @param anyCamera The camera that was used for the detection of the QR codes, must be valid
347  * @param frame The frame into which observations of the QR codes will be drawn, must be valid, match the camera size, have its origin in the upper left corner, and have a pixel format that is compatible with RGB24
348  * @param observations The observations of QR codes that will be drawn, must have the same size as `codes`
349  * @param codes The corresponding QR codes, must have the same size as `observations`
350  */
351  static void drawObservations(const AnyCamera& anyCamera, Frame& frame, const QRCodeDetector2D::Observations& observations, const QRCodes& codes);
352 
353  /**
354  * Draws observations of Micro QR codes into a given frame.
355  * @param anyCamera The camera that was used for the detection of the Micro QR codes, must be valid
356  * @param frame The frame into which observations of the Micro QR codes will be drawn, must be valid, match the camera size, have its origin in the upper left corner, and have a pixel format that is compatible with RGB24
357  * @param observations The observations of Micro QR codes that will be drawn, must have the same size as `codes`
358  * @param codes The corresponding Micro QR codes, must have the same size as `observations`
359  */
360  static void drawObservations(const AnyCamera& anyCamera, Frame& frame, const MicroQRCodeDetector2D::Observations& observations, const MicroQRCodes& codes);
361 
362  /**
363  * Draw the location of a finder pattern in a given frame.
364  * @param frame The frame in which the finder pattern will be drawn, must be valid
365  * @param finderPattern The finder pattern that will be drawn
366  * @param color The color to be used for drawing, one value for each channel of `frame`, must be valid
367  */
368  static void drawFinderPattern(Frame& frame, const FinderPattern& finderPattern, const uint8_t* color);
369 
370  /**
371  * Draws a line between two 2D points into a frame with lens distortion
372  * @param anyCamera The camera profile that will be used to draw the line, must be valid
373  * @param frame The frame into which the line will be drawn, must be valid, match the camera size, have its origin in the upper left corner, and have a pixel format that is compatible with RGB24
374  * @param pointA The first end point of the line segment
375  * @param pointB The second end point of the line segment
376  * @param color Optional color of the line segments
377  * @param steps Optional number of segments that the line will be split into, range: [1, infinity)
378  * @tparam tLineWidth The line of the width, range: [1, infinity), must be an odd value
379  */
380  template <unsigned int tLineWidth>
381  static void drawLine(const AnyCamera& anyCamera, Frame& frame, const Vector2& pointA, const Vector2& pointB, const uint8_t* color = nullptr, const size_t steps = 10);
382 
383  /**
384  * Draws a line between two 3D points into a frame with lens distortion
385  * @param anyCamera The camera profile that will be used to draw the line, must be valid
386  * @param frame The frame into which the line will be drawn, must be valid, match the camera size, have its origin in the upper left corner, and have a pixel format that is compatible with RGB24
387  * @param pointA The first end point of the line segment
388  * @param pointB The second end point of the line segment
389  * @param color Optional color of the line segments
390  * @param steps Optional number of segments that the line will be split into, range: [1, infinity)
391  * @tparam tLineWidth The line of the width, range: [1, infinity), must be an odd value
392  */
393  template <unsigned int tLineWidth>
394  static void drawLine(const AnyCamera& anyCamera, Frame& frame, const Vector3& pointA, const Vector3& pointB, const uint8_t* color = nullptr, const size_t steps = 10);
395 
396  /**
397  * Draws a (projected) 3D line into a given frame.
398  * @param frame The frame in which the line will be painted, must be valid
399  * @param flippedCamera_T_world The transformation transforming world to the flipped camera, the flipped camera points towards the positive z-space with y-axis down, must be valid
400  * @param anyCamera The camera profile defining the projection, must be valid
401  * @param objectPoint0 The start 3D object point of the 3D line, defined in world
402  * @param objectPoint1 The end 3D object point of the 3D line, defined in world
403  * @param segments The number of segments in which the line will be separated, with range [1, infinity), the more segments the better the adjustment to the camera distortion (if any)
404  * @param foregroundColor The foreground color of the line, nullptr to skip the painting with the foreground color
405  * @param backgroundColor The background color of the line, nullptr to skip the painting with the background color
406  * @tparam tForegroundLineWidth The line width of the foreground line, range: [1, infinity); must be an odd value
407  * @tparam tBackgroundLineWidth The line width of the background line, range: [0, infinity); for value 0 no background line is drawn, otherwise this value should be larger than `tForegroundLineWidth` and must be an odd value,
408  */
409  template <unsigned int tForegroundLineWidth, unsigned int tBackgroundLineWidth>
410  static void drawLineIF(Frame& frame, const HomogenousMatrix4& flippedCamera_T_world, const AnyCamera& anyCamera, const Vector3& objectPoint0, const Vector3& objectPoint1, const unsigned int segments, const uint8_t* foregroundColor, const uint8_t* backgroundColor);
411 
412  /**
413  * Draws a 3D coordinate system (projected) into a frame.
414  * If the frame is an RGB 24bit frame, than the axes are painted in red (x), green (y), and blue (z); otherwise the axes are painted black.<br>
415  * @param frame The frame in which the coordinate system is painted, must be valid
416  * @param flippedCamera_T_world The camera pose converting world to the flipped camera coordinate system (a camera coordinate system pointing towards the positive z-space), must be valid
417  * @param anyCamera The camera profile that is used to render the coordinate system
418  * @param world_T_coordinateSystem The transformation of the coordinate system that transforms points defined in the local coordinate system (which will be rendered) into points defined in the world coordinate system, must be valid
419  * @param length The length of the three axes of the coordinate system, defined in the units of the local coordinate system (coordinateSystem)
420  * @tparam tForegroundLineWidth The line width of the foreground line, range: [1, infinity); must be an odd value
421  * @tparam tBackgroundLineWidth The line width of the background line, range: [0, infinity); for value 0 no background line is drawn, otherwise this value should larger than `tForegroundLineWidth` and must be an odd value,
422  */
423  template <unsigned int tForegroundLineWidth, unsigned int tBackgroundLineWidth>
424  static void drawCoordinateSystemIF(Frame& frame, const HomogenousMatrix4& flippedCamera_T_world, const AnyCamera& anyCamera, const HomogenousMatrix4& world_T_coordinateSystem, const Scalar length);
425 
426 #if defined(OCEAN_QRCODES_QRCODEDEBUGELEMENTS_ENABLED)
427 
428  /**
429  * Draws the outline of a QR code given its pose and version
430  * @note This function is only for development purposes; do not use it in production code because it will be removed again
431  * @param anyCamera The camera profile that will be used for drawing, must be valid
432  * @param frame The frame into which the line will be drawn, must be valid, match the camera size, have its origin in the upper left corner, and have a pixel format that is compatible with RGB24
433  * @param version The version number of the QR code, range: [1, 40]
434  * @param code_T_camera The transformation that maps coordinates in the reference frame of the camera to that of the code, must be valid
435  */
436  static void drawQRCodeOutline(const AnyCamera& anyCamera, Frame& frame, const unsigned int version, const HomogenousMatrix4& code_T_camera);
437 
438 #endif // OCEAN_QRCODES_QRCODEDEBUGELEMENTS_ENABLED
439 
440  /**
441  * Converts a QR code into string (aka ASCII art)
442  * @param code The QR code that will be converted into string, must be valid
443  * @param border The border in multiples of modules around the ASCII representation of the QR code, range: [0, infinity)
444  * @return The QR code in ASCII representation; will be empty in case of a failure
445  */
446  static std::string toString(const QRCodeBase& code, const unsigned int border);
447 
448  /**
449  * Computes the number of pixel per module for a given observation of a QR code
450  * @param anyCamera The camera what was used for this observation, must be valid.
451  * @param world_T_camera The world pose of the camera, must be valid
452  * @param world_T_code The world pose of the QR code, must be valid
453  * @param codeSize The (display) size of the code in the real world (in meters), range: (0, infinity)
454  * @param version The version number of the QR code, range: [1, 40]
455  * @param minNumberPixelsPerModule The resulting minimum value for the number of pixels per module that has been found, will be ignored if `nullptr`
456  * @param maxNumberPixelsPerModule The resulting maximum value for the number of pixels per module that has been found, will be ignored if `nullptr`
457  * @param medianNumberPixelsPerModule The resulting median of all values for the number of pixels per module, will be ignored if `nullptr`
458  * @param avgNumberPixelsPerModule The resulting average of all values for the number of pixels per module, will be ignored if `nullptr`
459  * @return True if the computation was successful, otherwise false
460  */
461  static bool computeNumberPixelsPerModule(const AnyCamera& anyCamera, const HomogenousMatrix4& world_T_camera, const HomogenousMatrix4& world_T_code, const Scalar codeSize, const unsigned int version, Scalar* minNumberPixelsPerModule, Scalar* maxNumberPixelsPerModule, Scalar* medianNumberPixelsPerModule, Scalar* avgNumberPixelsPerModule);
462 
463  /**
464  * Computes the average diagonal length of a module in pixels for a given coordinate system of a QR code
465  * @param anyCamera The camera what was used for this observation, must be valid
466  * @param flippedCamera_T_code The flipped camera pose of the code, must be valid
467  * @param coordinateSystem The coordinate system of the QR code, must be valid
468  * @param xModule The horizontal coordinate of the module, range: [0, no. modules of the corresponding code)
469  * @param yModule The vertical coordinate of the module, range: [0, no. modules of the corresponding code)
470  * @return The length of the module diagonal in pixels, range: [0, infinity)
471  */
472  static Scalar computeModuleDiagonalLength(const AnyCamera& anyCamera, const HomogenousMatrix4& flippedCamera_T_code, const CoordinateSystemBase& coordinateSystem, const unsigned int xModule, const unsigned int yModule);
473 
474  /**
475  * Computes the contrast between fore- and background modules for a given observation of a QR code.
476  * @param anyCamera The camera what was used for this observation, must be valid.
477  * @param yFrame The grayscale frame in which the QR code has been observed, must be valid
478  * @param world_T_camera The world pose of the camera, must be valid
479  * @param code The code for which the contrast will be computed, must be valid
480  * @param world_T_code The world pose of the QR code, must be valid
481  * @param codeSize The (display) size of the code in the real world (in meters), range: (0, infinity)
482  * @param medianContrast The resulting construct of the median fore- and background values, will be ignored if `nullptr`
483  * @param averageContrast The resulting construct of the average fore- and background values, will be ignored if `nullptr`
484  * @return True if the computation was successful, otherwise false
485  */
486  static bool computeContrast(const AnyCamera& anyCamera, const Frame& yFrame, const HomogenousMatrix4& world_T_camera, const QRCodeBase& code, const HomogenousMatrix4& world_T_code, const Scalar codeSize, unsigned int* medianContrast, unsigned int* averageContrast);
487 
488  /**
489  * Computes the tilt and view angles for an observation of a QR code
490  * The tilt angle is defined as the angle, `A`, between the normal on the code and the direction from the code center to the camera origin.
491  * \code
492  * camera x
493  * origin .
494  * .
495  * * * code normal
496  * \ |
497  * direction to \ +-|--------+
498  * camera origin \ A| /
499  * / \ | /
500  * / x /
501  * / code /
502  * / center /
503  * +----------+
504  * \endcode
505  * The view angle, `A`, is defined as the angle between the ray pointing from the camera center to the code center and the view direction of the camera.
506  * \code
507  * camera x------* view direction (neg. z-axis)
508  * origin \ A
509  * \
510  * \
511  * direction to *
512  * code center .+----------+
513  * . /
514  * / . /
515  * / x /
516  * / code /
517  * / center /
518  * +----------+
519  * \endcode
520  * @param world_T_camera The world pose of the camera, must be valid
521  * @param world_T_code The world pose of the QR code, must be valid
522  * @param tiltAngle The resulting angle at which the QR code is tilted away from the camera center, in radian
523  * @param viewAngle The resulting angle at which the camera is looking at the QR code, in radian
524  * @param distance The optionally resulting distance from the camera center to the code center, will be ignored if `nullptr`
525  * @return True if the computation was successful, otherwise false
526  */
527  static bool computeCodeTiltAndViewAngles(const HomogenousMatrix4& world_T_camera, const HomogenousMatrix4& world_T_code, Scalar& tiltAngle, Scalar& viewAngle, Scalar* distance = nullptr);
528 
529  /**
530  * Checks if a given QR code exists in a list of QR codes given their 6DOF poses and a stereo camera
531  * This function will check if the payload of a new code is identical with the payload of any code in a list of codes; for pairs of codes with
532  * identical payload, function checks if the projection of a new code overlaps with the projection of the other QR code. If both checks are true
533  * the function will return `true`.
534  * @param sharedAnyCameras The cameras that produced the input images, must have 2 elements, all elements must be valid
535  * @param world_T_device The transformation that maps points in the device coordinate system points to world points, must be valid
536  * @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
537  * @param codes The list of existing QR codes that will be checked against, each element must be a valid QR code
538  * @param world_T_codes The world poses the of the above list of QR codes, number of elements will be identical to `codes`
539  * @param codeSizes The edge lengths of the above list of QR codes in meters, number of elements will be identical to `codes`, range of each value: (0, infinity)
540  * @param newCode The new QR code that will be checked, must be valid
541  * @param world_T_newCode The world pose the of the above QR code, must be valid
542  * @param newCodeSize The edge length of the above QR code in meters, range: (0, infinity)
543  * @param index The optionally returned index of the code in `codes` that is identical to `newCode`, will be ignored if `nullptr`
544  * @return True if an identical code was found, otherwise false
545  */
546  static bool containsCodeStereo(const SharedAnyCameras& sharedAnyCameras, const HomogenousMatrix4& world_T_device, const HomogenousMatrices4& device_T_cameras, const QRCodes& codes, const HomogenousMatrices4& world_T_codes, const Scalars& codeSizes, const QRCode& newCode, const HomogenousMatrix4& world_T_newCode, const Scalar newCodeSize, unsigned int* index = nullptr);
547 
548  /**
549  * Checks if a given QR code exists in a list of QR codes given their 6DOF poses and a mono camera
550  * This function will check if the payload of a new code is identical with the payload of any code in a list of codes; for pairs of codes with
551  * identical payload, function checks if the projection of a new code overlaps with the projection of the other QR code. If both checks are true
552  * the function will return `true`.
553  * @param anyCamera The camera that produced the input image, must be valid
554  * @param world_T_camera The transformation that maps points in the camera coordinate system points to world points, must be valid
555  * @param codes The list of existing QR codes that will be checked against, each element must be a valid QR code
556  * @param world_T_codes The world poses the of the above list of QR codes, number of elements will be identical to `codes`
557  * @param codeSizes The edge lengths of the above list of QR codes in meters, number of elements will be identical to `codes`, range of each value: (0, infinity)
558  * @param newCode The new QR code that will be checked, must be valid
559  * @param world_T_newCode The world pose the of the above QR code, must be valid
560  * @param newCodeSize The edge length of the above QR code in meters, range: (0, infinity)
561  * @param index The optionally returned index of the code in `codes` that is identical to `newCode`, will be ignored if `nullptr`
562  * @return True if an identical code was found, otherwise false
563  */
564  static bool containsCodeMono(const AnyCamera& anyCamera, const HomogenousMatrix4& world_T_camera, const QRCodes& codes, const HomogenousMatrices4& world_T_codes, const Scalars& codeSizes, const QRCode& newCode, const HomogenousMatrix4& world_T_newCode, const Scalar newCodeSize, unsigned int* index = nullptr);
565 
566  /**
567  * Checks if a given QR code exists in a list of QR codes
568  * This function will check if the payload of a new code is identical with the payload of any code in a list of codes; if any is found, the function will return `true`.
569  * @param codes The list of existing QR codes that will be checked against, each element must be a valid QR code
570  * @param newCode The new QR code that will be checked, must be valid
571  * @return True if an identical code was found, otherwise false
572  */
573  static bool containsCode(const QRCodes& codes, const QRCode& newCode);
574 
575  /**
576  * Parses a Wi-Fi configuration from a QR code
577  * The following format is expected:
578  *
579  * <pre>
580  * WIFI:S:<SSID>;T:<WEP|WPA|blank>;P:<PASSWORD>;H:<true|false|blank>;;
581  * </pre>
582  *
583  * Special characters \;,": should be escaped with a backslash (\\‍). More details can be found
584  * here: https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
585  * @param configString The string containing the configuration, must be valid and of the format mentioned above
586  * @param ssid The resulting SSID of the Wi-Fi network
587  * @param password The resulting password of the Wi-Fi network
588  * @param encryption The optionally resulting encryption type of the Wi-Fi network (either "", "WEP", or "WPA")
589  * @param isSsidHidden The optionally resulting value whether the SSID of the Wi-Fi network is hidden
590  * @return `PS_SUCCESS` if parsing finished successfully, otherwise a correspond error code
591  */
592  static ParsingStatus parseWifiConfig(const std::string& configString, std::string& ssid, std::string& password, std::string* encryption = nullptr, bool* isSsidHidden = nullptr);
593 
594  /**
595  * Returns a human-readable string for each possible parsing status
596  * @param status The status to be converted to a string
597  * @return The human-readable string
598  */
599  static std::string parsingStatusToString(const ParsingStatus status);
600 
601  protected:
602 
603  /**
604  * Escapes selected characters in a string
605  * @param string The string which will be checked for characters that need escaping, must be valid
606  * @param specialCharacters The string defining which characters to escape; duplicates will be ignored; must be valid
607  * @return A string with escaped characters
608  * @sa parseWifiConfig()
609  */
610  static std::string escapeSpecialCharacters(const std::string& string, const std::string& specialCharacters = "\\;,\":");
611 
612  /**
613  * Unescapes selected character from a string
614  * @param escapedString The string to be unescaped, must be valid
615  * @param string The resulting string without escaped characters
616  * @param specialCharacters The string defining which characters to unescape; duplicates will be ignored; must be valid
617  * @return True if the unescaping process was successful, otherwise false
618  * @sa parseWifiConfig()
619  */
620  static bool unescapeSpecialCharacters(const std::string& escapedString, std::string& string, const std::string& specialCharacters = "\\;,\":");
621 
622  /**
623  * Computes the image location of the center of a QR code given its world pose
624  * @param anyCamera The camera profile that will be used to draw the line, must be valid
625  * @param world_T_camera The transformation that maps points in the camera coordinate system points to world points, must be valid
626  * @param code The code for which the image location will be computed, must be valid
627  * @param world_T_code The world pose the QR code, must be valid
628  * @param codeSize The edge lengths of the QR code in meters, range: (0, infinity)
629  * @param imageCodeCenter The returning image location of the center of a QR code; value is only valid if this function returns `true`
630  * @param maxSquareRadius The optionally returning maximum square distance in pixels of the image location of the code and its four corners; value is only valid if this function returns `true`
631  * @return True, if code is in front of the camera and the image location of its center is inside the image boundaries, otherwise false
632  */
633  static bool computeCodeCenterInImage(const AnyCamera& anyCamera, const HomogenousMatrix4& world_T_camera, const QRCode& code, const HomogenousMatrix4& world_T_code, const Scalar codeSize, Vector2& imageCodeCenter, Scalar* maxSquareRadius = nullptr);
634 };
635 
637 {
638  return scale_;
639 }
640 
642 {
643  const Scalar xObjectSpace = xScale_ * xCodeSpace - Scalar(scale_);
644  ocean_assert(Numeric::isInsideRange(Scalar(-scale_), xObjectSpace, Scalar(scale_)));
645 
646  return xObjectSpace;
647 }
648 
650 {
651  const Scalar yObjectSpace = yScale_ * yCodeSpace + Scalar(scale_);
652  ocean_assert(Numeric::isInsideRange(Scalar(-scale_), yObjectSpace, Scalar(scale_)));
653 
654  return yObjectSpace;
655 }
656 
658 {
659  ocean_assert(scale > Scalar(0));
660 
661  Vectors3 corners =
662  {
663  Vector3(-Scalar(scale), Scalar(scale), Scalar(0)), // top-left
664  Vector3(-Scalar(scale), -Scalar(scale), Scalar(0)), // bottom-left
665  Vector3( Scalar(scale), -Scalar(scale), Scalar(0)), // bottom-right
666  Vector3( Scalar(scale), Scalar(scale), Scalar(0)), // top-right
667  };
668 
669  return corners;
670 }
671 
672 inline void Utilities::drawObservation(Frame& frame, const LegacyQRCodeDetector2D::Observation& observation, const QRCode& code)
673 {
674  ocean_assert(frame.isValid());
675  ocean_assert(code.isValid());
676 
677  drawObservation(frame, observation.frame_H_code(), observation.finderPatterns(), code.version(), code.modules());
678 }
679 
680 inline void Utilities::drawObservations(Frame& frame, const LegacyQRCodeDetector2D::Observations& observations, const QRCodes& codes)
681 {
682  ocean_assert(frame.isValid());
683 
684  if (observations.size() != codes.size())
685  {
686  ocean_assert(false && "This should never happen!");
687  return;
688  }
689 
690  for (size_t i = 0; i < observations.size(); ++i)
691  {
692  drawObservation(frame, observations[i].frame_H_code(), observations[i].finderPatterns(), codes[i].version(), codes[i].modules());
693  }
694 }
695 
696 template <unsigned int tLineWidth>
697 void Utilities::drawLine(const AnyCamera& anyCamera, Frame& frame, const Vector2& pointA, const Vector2& pointB, const uint8_t* color, const size_t steps)
698 {
699  ocean_assert(anyCamera.isValid());
700  ocean_assert(frame.isValid());
701  ocean_assert(steps != 0);
702 
703  return Utilities::drawLine<tLineWidth>(anyCamera, frame, anyCamera.vector(pointA), anyCamera.vector(pointB), color, steps);
704 }
705 
706 template <unsigned int tLineWidth>
707 void Utilities::drawLine(const AnyCamera& anyCamera, Frame& frame, const Vector3& pointA, const Vector3& pointB, const uint8_t* color, const size_t steps)
708 {
709  static_assert(tLineWidth != 0 && tLineWidth % 2u == 1u, "Line width must be non-zero and odd");
710 
711  ocean_assert(anyCamera.isValid());
713  ocean_assert(steps != 0);
714 
715  const Vector3 step = (pointB - pointA) * (Scalar(1) / Scalar(steps));
716  ocean_assert(!step.isNull());
717 
718  color = color == nullptr ? CV::Canvas::green(frame.pixelFormat()) : color;
719 
720  Vector3 previousPlanePoint = pointA;
721  Vector2 previousImagePoint = anyCamera.projectToImage(previousPlanePoint);
722 
723  for (size_t s = 0; s < steps; ++s)
724  {
725  const Vector3 currentPlanePoint = previousPlanePoint + step;
726  const Vector2 currentImagePoint = anyCamera.projectToImage(currentPlanePoint);
727 
728  CV::Canvas::line<tLineWidth>(frame, previousImagePoint, currentImagePoint, color);
729 
730  previousPlanePoint = currentPlanePoint;
731  previousImagePoint = currentImagePoint;
732  }
733 }
734 
735 template <unsigned int tForegroundLineWidth, unsigned int tBackgroundLineWidth>
736 void Utilities::drawLineIF(Frame& frame, const HomogenousMatrix4& flippedCamera_T_world, const AnyCamera& anyCamera, const Vector3& objectPoint0, const Vector3& objectPoint1, const unsigned int segments, const uint8_t* foregroundColor, const uint8_t* backgroundColor)
737 {
738  static_assert(tForegroundLineWidth != 0u && tForegroundLineWidth % 2u == 1u, "The line width must be non-zero and odd.");
739  static_assert(tBackgroundLineWidth == 0u || tBackgroundLineWidth % 2u == 1u, "The line width must be either zero (in which case it will not be drawn) or non-zero and odd.");
740 
741  ocean_assert(frame && flippedCamera_T_world.isValid() && anyCamera.isValid());
742  ocean_assert(frame.width() == anyCamera.width() && frame.height() == anyCamera.height());
743  ocean_assert(segments >= 1u);
744 
745  const Scalar segmentFactor = Scalar(1) / Scalar(segments);
746 
747  if (backgroundColor && tBackgroundLineWidth != 0u)
748  {
749  Vector2 projectedStart = anyCamera.projectToImageIF(flippedCamera_T_world, objectPoint0);
750 
751  for (unsigned int n = 0u; n < segments; ++n)
752  {
753  const Vector3 end = objectPoint0 + (objectPoint1 - objectPoint0) * Scalar(n + 1) * segmentFactor;
754  const Vector2 projectedEnd = anyCamera.projectToImageIF(flippedCamera_T_world, end);
755 
756  CV::Canvas::line<tBackgroundLineWidth>(frame, projectedStart.x(), projectedStart.y(), projectedEnd.x(), projectedEnd.y(), backgroundColor);
757 
758  projectedStart = projectedEnd;
759  }
760  }
761 
762  if (foregroundColor)
763  {
764  Vector2 projectedStart = anyCamera.projectToImageIF(flippedCamera_T_world, objectPoint0);
765 
766  for (unsigned int n = 0u; n < segments; ++n)
767  {
768  const Vector3 end = objectPoint0 + (objectPoint1 - objectPoint0) * Scalar(n + 1) * segmentFactor;
769  const Vector2 projectedEnd = anyCamera.projectToImageIF(flippedCamera_T_world, end);
770 
771  CV::Canvas::line<tForegroundLineWidth>(frame, projectedStart.x(), projectedStart.y(), projectedEnd.x(), projectedEnd.y(), foregroundColor);
772 
773  projectedStart = projectedEnd;
774  }
775  }
776 }
777 
778 template <unsigned int tForegroundLineWidth, unsigned int tBackgroundLineWidth>
779 void Utilities::drawCoordinateSystemIF(Frame& frame, const HomogenousMatrix4& flippedCamera_T_world, const AnyCamera& anyCamera, const HomogenousMatrix4& world_T_coordinateSystem, const Scalar length)
780 {
781  static_assert(tForegroundLineWidth != 0u && tForegroundLineWidth % 2u == 1u, "The line width must be non-zero and odd.");
782  static_assert(tBackgroundLineWidth == 0u || tBackgroundLineWidth % 2u == 1u, "The line width must be either zero (in which case it will not be drawn) or non-zero and odd.");
783 
784  ocean_assert(frame && flippedCamera_T_world.isValid() && anyCamera.isValid() && world_T_coordinateSystem.isValid());
785  ocean_assert(frame.width() == anyCamera.width() && frame.height() == frame.height());
786 
787  const uint8_t* const red = CV::Canvas::red(frame.pixelFormat());
788  const uint8_t* const green = CV::Canvas::green(frame.pixelFormat());
789  const uint8_t* const blue = CV::Canvas::blue(frame.pixelFormat());
790  const uint8_t* const black = CV::Canvas::black(frame.pixelFormat());
791 
792  if (AnyCamera::isObjectPointInFrontIF(flippedCamera_T_world, world_T_coordinateSystem.translation()))
793  {
794  const Vector3 xAxis = world_T_coordinateSystem * Vector3(length, 0, 0);
795  const Vector3 yAxis = world_T_coordinateSystem * Vector3(0, length, 0);
796  const Vector3 zAxis = world_T_coordinateSystem * Vector3(0, 0, length);
797 
798  if (AnyCamera::isObjectPointInFrontIF(flippedCamera_T_world, xAxis))
799  {
800  drawLineIF<tForegroundLineWidth, tBackgroundLineWidth>(frame, flippedCamera_T_world, anyCamera, world_T_coordinateSystem.translation(), xAxis, /* segments */ 15u, red, black);
801  }
802 
803  if (AnyCamera::isObjectPointInFrontIF(flippedCamera_T_world, yAxis))
804  {
805  drawLineIF<tForegroundLineWidth, tBackgroundLineWidth>(frame, flippedCamera_T_world, anyCamera, world_T_coordinateSystem.translation(), yAxis, /* segments */ 15u, green, black);
806  }
807 
808  if (AnyCamera::isObjectPointInFrontIF(flippedCamera_T_world, zAxis))
809  {
810  drawLineIF<tForegroundLineWidth, tBackgroundLineWidth>(frame, flippedCamera_T_world, anyCamera, world_T_coordinateSystem.translation(), zAxis, /* segments */ 15u, blue, black);
811  }
812  }
813 }
814 
815 } // namespace QRCodes
816 
817 } // namespace Detector
818 
819 } // namespace CV
820 
821 } // namespace Ocean
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 VectorT2< T > projectToImage(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 VectorT3< T > vector(const VectorT2< T > &distortedImagePoint, const bool makeUnitVector=true) const =0
Returns a vector starting at the camera's center and intersecting a given 2D point in the image.
static const uint8_t * green(const FrameType::PixelFormat pixelFormat=FrameType::FORMAT_RGB24)
Returns the color values for a green color.
static const uint8_t * red(const FrameType::PixelFormat pixelFormat=FrameType::FORMAT_RGB24)
Returns the color values for a red color.
static const uint8_t * black(const FrameType::PixelFormat pixelFormat=FrameType::FORMAT_RGB24)
Returns the color values for a black color.
static const uint8_t * blue(const FrameType::PixelFormat pixelFormat=FrameType::FORMAT_RGB24)
Returns the color values for a blue color.
Definition of a class for finder patterns of QR codes (squares in the top-left, top-right and bottom-...
Definition: FinderPatternDetector.h:58
Definition of an observation of QR code in 2D.
Definition: LegacyQRCodeDetector2D.h:73
const FinderPatternTriplet & finderPatterns() const
Returns a pointer to the finder patterns.
Definition: LegacyQRCodeDetector2D.h:275
const SquareMatrix3 & frame_H_code() const
Returns the homography that maps coordinates in the QR code grid to image coordinates.
Definition: LegacyQRCodeDetector2D.h:270
std::vector< Observation > Observations
Definition of a vector of observations.
Definition: LegacyQRCodeDetector2D.h:116
std::vector< Observation > Observations
Definition of a vector of observations.
Definition: MicroQRCodeDetector2D.h:88
Base class for QR code implementations.
Definition: QRCodeBase.h:32
const std::vector< uint8_t > & modules() const
Returns the modules of this QR code The modules are stored in a vector and will have modulesPerSide()...
Definition: QRCodeBase.h:290
unsigned int version() const
Returns the version of the QR code.
Definition: QRCodeBase.h:305
std::vector< Observation > Observations
Definition of a vector of observations.
Definition: QRCodeDetector2D.h:92
Definition of a QR code.
Definition: QRCode.h:35
bool isValid() const override
Returns whether this is a valid QR code instance.
Definition: QRCode.h:93
Definition of a helper class to convert between the coordinate systems that are used for QR codes.
Definition: cv/detector/qrcodes/Utilities.h:116
virtual ~CoordinateSystemBase()=default
The default constructor.
CoordinateSystemBase(const unsigned int modulesPerSide, const Scalar scale=Scalar(1))
Constructs an coordinate system object Coordinates are normalized to the range [-1,...
Scalar yScale_
The scale factor for y-coordinates.
Definition: cv/detector/qrcodes/Utilities.h:172
Scalar convertCodeSpaceToObjectSpaceX(const Scalar xCodeSpace) const
Converts an x-coordinate from code space to object space.
Definition: cv/detector/qrcodes/Utilities.h:641
Scalar convertCodeSpaceToObjectSpaceY(const Scalar yCodeSpace) const
Converts an y-coordinate from code space to object space.
Definition: cv/detector/qrcodes/Utilities.h:649
Scalar xScale_
The scale factor for x-coordinates.
Definition: cv/detector/qrcodes/Utilities.h:169
Scalar scale_
Global factor for coordinate scaling.
Definition: cv/detector/qrcodes/Utilities.h:166
unsigned int modulesPerSide_
The number of modules per side of the QR code, range: [11, 177].
Definition: cv/detector/qrcodes/Utilities.h:163
Scalar scale() const
Returns the scaling factor that is used for coordinate scaling.
Definition: cv/detector/qrcodes/Utilities.h:636
static Vectors3 computeCornersInObjectSpace(const Scalar scale=Scalar(1))
Compute the locations of the four corners of a code in object space Coordinates are normalized to the...
Definition: cv/detector/qrcodes/Utilities.h:657
Definition of a helper class to convert between the coordinate systems that are used for QR codes.
Definition: cv/detector/qrcodes/Utilities.h:179
static std::vector< Vectors3 > computeAlignmentPatternsInObjectSpace(const unsigned int version, const Scalar scale=Scalar(1))
Computes the locations of alignment patterns for a specific QR code version in object space Coordinat...
static Vectors3 computeVersionInformationModulesInObjectSpace(const unsigned int version, const bool versionInformation1)
Computes the locations of the version information fields for a specific QR code version in object spa...
CoordinateSystem(const unsigned int version, const Scalar scale=Scalar(1))
Constructs a coordinate system object Coordinates are normalized to the range [-1,...
static Vectors3 computeFinderPatternCentersInObjectSpace(const unsigned int version, const Scalar scale=Scalar(1))
Computes the locations of the centers of the 3 finder patterns for a specific QR code version in obje...
Definition of a helper class to convert between the coordinate systems that are used for Micro QR cod...
Definition: cv/detector/qrcodes/Utilities.h:251
Vector3 computeFinderPatternCenterInObjectSpace() const
Computes the location of the center of the finder pattern Coordinates are normalized to the range [-1...
Vectors3 computeHorizontalTimingPatternModulesInObjectSpace() const
Computes the locations of the modules in the horizontal (top edge) timing pattern Coordinates are nor...
Vectors3 computeFinderPatternCornersInObjectSpace() const
Computes the locations of the corners of the finder pattern for a specific Micro QR code version in o...
MicroQRCoordinateSystem(const unsigned int version, const Scalar scale=Scalar(1))
Constructs a Micro QR coordinate system object Coordinates are normalized to the range [-1,...
Vectors3 computeVerticalTimingPatternModulesInObjectSpace() const
Computes the locations of the modules in the vertical (left edge) timing pattern Coordinates are norm...
Definition of utility functions related to the detection of QR codes.
Definition: cv/detector/qrcodes/Utilities.h:42
static void drawObservation(Frame &frame, const SquareMatrix3 &frame_H_code, const FinderPatternTriplet &finderPatterns, const unsigned int version, const std::vector< uint8_t > &modules)
Draws an observation of a QR code into a given frame.
static bool computeCodeTiltAndViewAngles(const HomogenousMatrix4 &world_T_camera, const HomogenousMatrix4 &world_T_code, Scalar &tiltAngle, Scalar &viewAngle, Scalar *distance=nullptr)
Computes the tilt and view angles for an observation of a QR code The tilt angle is defined as the an...
static void drawLineIF(Frame &frame, const HomogenousMatrix4 &flippedCamera_T_world, const AnyCamera &anyCamera, const Vector3 &objectPoint0, const Vector3 &objectPoint1, const unsigned int segments, const uint8_t *foregroundColor, const uint8_t *backgroundColor)
Draws a (projected) 3D line into a given frame.
Definition: cv/detector/qrcodes/Utilities.h:736
static std::string parsingStatusToString(const ParsingStatus status)
Returns a human-readable string for each possible parsing status.
static ParsingStatus parseWifiConfig(const std::string &configString, std::string &ssid, std::string &password, std::string *encryption=nullptr, bool *isSsidHidden=nullptr)
Parses a Wi-Fi configuration from a QR code The following format is expected:
static bool containsCode(const QRCodes &codes, const QRCode &newCode)
Checks if a given QR code exists in a list of QR codes This function will check if the payload of a n...
static Frame draw(const QRCodeBase &code, const unsigned int border, const uint8_t foregroundColor=0u, const uint8_t backgroundColor=255u)
Draws an unscaled image of a QR code (FORMAT_Y8), i.e.
static bool containsCodeStereo(const SharedAnyCameras &sharedAnyCameras, const HomogenousMatrix4 &world_T_device, const HomogenousMatrices4 &device_T_cameras, const QRCodes &codes, const HomogenousMatrices4 &world_T_codes, const Scalars &codeSizes, const QRCode &newCode, const HomogenousMatrix4 &world_T_newCode, const Scalar newCodeSize, unsigned int *index=nullptr)
Checks if a given QR code exists in a list of QR codes given their 6DOF poses and a stereo camera Thi...
static bool computeContrast(const AnyCamera &anyCamera, const Frame &yFrame, const HomogenousMatrix4 &world_T_camera, const QRCodeBase &code, const HomogenousMatrix4 &world_T_code, const Scalar codeSize, unsigned int *medianContrast, unsigned int *averageContrast)
Computes the contrast between fore- and background modules for a given observation of a QR code.
static bool containsCodeMono(const AnyCamera &anyCamera, const HomogenousMatrix4 &world_T_camera, const QRCodes &codes, const HomogenousMatrices4 &world_T_codes, const Scalars &codeSizes, const QRCode &newCode, const HomogenousMatrix4 &world_T_newCode, const Scalar newCodeSize, unsigned int *index=nullptr)
Checks if a given QR code exists in a list of QR codes given their 6DOF poses and a mono camera This ...
static Frame draw(const QRCodeBase &code, const unsigned int frameSize, const bool allowTrueMultiple, const unsigned int border, Worker *worker=nullptr, const uint8_t foregroundColor=0u, const uint8_t backgroundColor=255u)
Draws a scaled image of a QR code (FORMAT_Y8)
static Scalar computeModuleDiagonalLength(const AnyCamera &anyCamera, const HomogenousMatrix4 &flippedCamera_T_code, const CoordinateSystemBase &coordinateSystem, const unsigned int xModule, const unsigned int yModule)
Computes the average diagonal length of a module in pixels for a given coordinate system of a QR code...
static bool unescapeSpecialCharacters(const std::string &escapedString, std::string &string, const std::string &specialCharacters="\\;,\":")
Unescapes selected character from a string.
static void drawObservations(Frame &frame, const LegacyQRCodeDetector2D::Observations &observations, const QRCodes &codes)
Draws observations of QR codes into a given frame.
Definition: cv/detector/qrcodes/Utilities.h:680
static void drawLine(const AnyCamera &anyCamera, Frame &frame, const Vector2 &pointA, const Vector2 &pointB, const uint8_t *color=nullptr, const size_t steps=10)
Draws a line between two 2D points into a frame with lens distortion.
Definition: cv/detector/qrcodes/Utilities.h:697
static void drawFinderPattern(Frame &frame, const FinderPattern &finderPattern, const uint8_t *color)
Draw the location of a finder pattern in a given frame.
static bool computeNumberPixelsPerModule(const AnyCamera &anyCamera, const HomogenousMatrix4 &world_T_camera, const HomogenousMatrix4 &world_T_code, const Scalar codeSize, const unsigned int version, Scalar *minNumberPixelsPerModule, Scalar *maxNumberPixelsPerModule, Scalar *medianNumberPixelsPerModule, Scalar *avgNumberPixelsPerModule)
Computes the number of pixel per module for a given observation of a QR code.
static void drawObservation(Frame &frame, const LegacyQRCodeDetector2D::Observation &observation, const QRCode &code)
Draws an observation of a QR code into a given frame.
Definition: cv/detector/qrcodes/Utilities.h:672
static bool computeCodeCenterInImage(const AnyCamera &anyCamera, const HomogenousMatrix4 &world_T_camera, const QRCode &code, const HomogenousMatrix4 &world_T_code, const Scalar codeSize, Vector2 &imageCodeCenter, Scalar *maxSquareRadius=nullptr)
Computes the image location of the center of a QR code given its world pose.
static void drawObservations(const AnyCamera &anyCamera, Frame &frame, const QRCodeDetector2D::Observations &observations, const QRCodes &codes)
Draws observations of QR codes into a given frame.
static std::string escapeSpecialCharacters(const std::string &string, const std::string &specialCharacters="\\;,\":")
Escapes selected characters in a string.
static void drawCoordinateSystemIF(Frame &frame, const HomogenousMatrix4 &flippedCamera_T_world, const AnyCamera &anyCamera, const HomogenousMatrix4 &world_T_coordinateSystem, const Scalar length)
Draws a 3D coordinate system (projected) into a frame.
Definition: cv/detector/qrcodes/Utilities.h:779
static void drawObservations(const AnyCamera &anyCamera, Frame &frame, const MicroQRCodeDetector2D::Observations &observations, const MicroQRCodes &codes)
Draws observations of Micro QR codes into a given frame.
static void drawQRCodeOutline(const AnyCamera &anyCamera, Frame &frame, const unsigned int version, const HomogenousMatrix4 &code_T_camera)
Draws the outline of a QR code given its pose and version.
ParsingStatus
Definition of return codes of the parsing function for the Wi-Fi configurations.
Definition: cv/detector/qrcodes/Utilities.h:49
@ PS_ERROR_INVALID_FIELD_DATA
Indicates that the content of a field is invalid, missing, or could not be processed correctly.
Definition: cv/detector/qrcodes/Utilities.h:57
@ PS_ERROR_DUPLICATE_FIELD_TYPE
Indicates that a field has been found multiple times when it should have been unique.
Definition: cv/detector/qrcodes/Utilities.h:61
@ PS_ERROR_INVALID_PREFIX
Indicates that the input has an invalid prefix.
Definition: cv/detector/qrcodes/Utilities.h:53
@ PS_ERROR_INVALID_FIELD_TYPE
Indicates that field type is unknown or invalid.
Definition: cv/detector/qrcodes/Utilities.h:59
@ PS_ERROR_INVALID_FIELD_FORMAT
Indicates that a field uses an invalid format, for example it isn't closed correctly.
Definition: cv/detector/qrcodes/Utilities.h:55
static std::string toString(const QRCodeBase &code, const unsigned int border)
Converts a QR code into string (aka ASCII art)
static bool isObjectPointInFrontIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const VectorT3< T > &objectPoint, const T epsilon=NumericT< T >::eps())
Determines whether a given 3D object point lies in front of a camera while the location of the camera...
Definition: Camera.h:811
This class implements Ocean's image class.
Definition: Frame.h:1792
bool isValid() const
Returns whether this frame is valid.
Definition: Frame.h:4448
@ FORMAT_RGB24
Pixel format with byte order RGB and 24 bits per pixel.
Definition: Frame.h:315
unsigned int width() const
Returns the width of the frame format in pixel.
Definition: Frame.h:3143
PixelOrigin pixelOrigin() const
Returns the pixel origin of the frame.
Definition: Frame.h:3188
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:3153
@ ORIGIN_UPPER_LEFT
The first pixel lies in the upper left corner, the last pixel in the lower right corner.
Definition: Frame.h:1050
unsigned int height() const
Returns the height of the frame in pixel.
Definition: Frame.h:3148
VectorT3< T > translation() const
Returns the translation of the transformation.
Definition: HomogenousMatrix4.h:1381
bool isValid() const
Returns whether this matrix is a valid homogeneous transformation.
Definition: HomogenousMatrix4.h:1806
static constexpr bool isInsideRange(const T lower, const T value, const T upper, const T epsilon=NumericT< T >::eps())
Returns whether a value lies between a given range up to a provided epsilon border.
Definition: Numeric.h:2872
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
bool isNull() const
Returns whether this vector is a null vector up to a small epsilon.
Definition: Vector3.h:854
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
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::vector< Scalar > Scalars
Definition of a vector holding Scalar objects.
Definition: Math.h:144
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition: Vector3.h:22
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< MicroQRCode > MicroQRCodes
Definition of a vector of Micro QR codes.
Definition: MicroQRCode.h:25
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