Ocean
BarcodeDetector2D.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 
12 
13 #include "ocean/base/DataType.h"
14 #include "ocean/base/Worker.h"
15 
16 #include "ocean/cv/PixelPosition.h"
17 
18 #include "ocean/math/FiniteLine2.h"
19 #include "ocean/math/Line2.h"
20 
21 namespace Ocean
22 {
23 
24 namespace CV
25 {
26 
27 namespace Detector
28 {
29 
30 namespace Barcodes
31 {
32 
33 /**
34  * This class converts raw pixel data into binary segments.
35  *
36  * The process starts by searching for an intensity jump from background intensity to foreground intensity values.
37  * Once a transition has been found, it will determine a gray value that's used to threshold the following pixels.
38  * When requested, the segmenter can prepare the N segments in advance. Once done, the segmenter will advance to
39  * the next intensity jump. This process continues until all raw pixels have been processed.
40  *
41  * Suggested use:
42  * <pre>
43  * const bool isNormalReflectance = ...;
44  * const uint8_t gradientThreshold = 20u;
45  * const uint8_t* buffer = ...;
46  * const size_t bufferSize = ...;
47  *
48  * RowSegmenter rowSegmenter(buffer, bufferSize, gradientThreshold, isNormalReflectance);
49  *
50  * while (rowSegmenter.findNextTransitionToForeground())
51  * {
52  * rowSegmenter.prepareSegments(maxNumberRequiredSegments);
53  *
54  * if (rowSegmenter.size() < minNumberRequiredSegments)
55  * {
56  * // There aren't enough segments.
57  * continue;
58  * }
59  *
60  * // work with the segments ...
61  * }
62  * </pre>
63  * @ingroup cvdetectorbarcodes
64  * @tparam TPixel The type of the raw pixels that will be processed, e.g. `uint8_t`.
65  */
66 template <typename TPixel>
68 {
69  public:
70 
71  // The type that is used for the image gradient.
73 
74  protected:
75 
76  /**
77  * This class implements a simple history for previous pixel transitions (a sliding window of pixel transitions).
78  */
80  {
81  public:
82 
83  /**
84  * Creates a new history object.
85  */
86  TransitionHistory() = default;
87 
88  /**
89  * Returns the history with window size N.
90  * @return The sum of the most recent delta
91  */
92  inline TGradient history1();
93 
94  /**
95  * Returns the history with window size N.
96  * @return The sum of the most recent delta
97  */
98  inline TGradient history2();
99 
100  /**
101  * Returns the history with window size N.
102  * @return The sum of the most recent delta
103  */
104  inline TGradient history3();
105 
106  /**
107  * Adds a new delta object as most recent history.
108  * Existing history objects will be moved by one pixel.
109  * @param newDelta The new delta object to be added
110  */
111  inline void push(const TGradient newDelta);
112 
113  /**
114  * Resets the history object.
115  */
116  inline void reset();
117 
118  protected:
119 
120  /// The most recent deltas.
121  TGradient deltas_[3] = {0, 0, 0};
122  };
123 
124  /// Definition of a function pointer for function that determine intensity transitions between back- and foreground pixels.
125  typedef bool (*IsTransitionFunc)(const TPixel*, const TGradient, TransitionHistory&);
126 
127  public:
128 
129  /**
130  * Creates a segmenter object for a buffer of raw pixel data.
131  * @param pixelData The pointer to the raw pixel data that will be processed, must be valid
132  * @param pixelDataSize The size of the raw pixel data, range: [1, infinity)
133  * @param minimumGradient The minimum value of the pixel gradient required to count as a transition, range: (-infinity, infinity)
134  * @param isNormalReflectance Indicates whether the segmenter should look for transitions with normal or inverted reflectance
135  */
136  RowSegmenter(const TPixel* pixelData, const size_t pixelDataSize, const TGradient minimumGradient, const bool isNormalReflectance);
137 
138  /**
139  * Returns if this segmenter is valid
140  * @return True if this segmenter is valid, otherwise false
141  */
142  bool isValid() const;
143 
144  /**
145  * Finds the next transition from background to foreground in the raw pixel data
146  * @return True if a transition has been found, otherwise false
147  */
149 
150  /**
151  * Prepares a batch of segments
152  * @note: Calling this function without having `findNextTransitionToForeground()` first (with `true` as return value) results in undefined behavior!
153  * @param numberSegments The number of segments that should be prepared, range: (1, infinity)
154  * @return True if the number of requested segments are available, otherwise false
155  */
156  bool prepareSegments(const size_t numberSegments);
157 
158  /**
159  * Returns the current segment data
160  * @return The current segment data
161  */
162  const SegmentData& segmentData() const;
163 
164  /**
165  * Returns the size of the raw pixel data that is handled by this object
166  * @return The size of the raw pixel data in elements
167  */
168  size_t size() const;
169 
170  /**
171  * Returns the current position of the segmenter in the raw pixel data
172  * @return The current position
173  */
174  size_t position() const;
175 
176  /**
177  * Sets the position of the segmenter in the raw pixel data
178  * @param position The index position to where the segmenter should be set, range: [0, size())
179  */
180  bool setPosition(const size_t position);
181 
182  protected:
183 
184  /**
185  * Checks if the specified pixel is a transition from light to dark pixels
186  * @param pixel The pointer to the pixel that will be checked, must be valid
187  * @param minimumGradient The minimum value of the pixel gradient that must be exceed for it count as a intensity transition, range: (-infinity, infinity)
188  * @param history The object holding the recent pixel history, must be valid
189  */
190  static bool isTransitionLightToDark(const TPixel* pixel, const TGradient minimumGradient, TransitionHistory& history);
191 
192  /**
193  * Checks if the specified pixel is a transition from dark to light pixels
194  * @param pixel The pointer to the pixel that will be checked, must be valid
195  * @param minimumGradient The minimum value of the pixel gradient that must be exceed for it count as a intensity transition, range: (-infinity, infinity)
196  * @param history The object holding the recent pixel history, must be valid
197  */
198  static bool isTransitionDarkToLight(const TPixel* pixel, const TGradient minimumGradient, TransitionHistory& history);
199 
200  protected:
201 
202  /// A pointer to the function that checks if there is a transition from background to foreground (this depends on the reflectance type)
204 
205  /// A pointer to the function that checks if there is a transition from foreground to background (this depends on the reflectance type)
207 
208  /// The pointer to the raw pixel data that will be processed by this object.
209  const TPixel* pixelData_ = nullptr;
210 
211  /// The size of the raw pixel data in elements.
212  size_t size_ = 0;
213 
214  /// The minimum value of the pixel gradient that must be exceed for it count as a intensity transition.
216 
217  /// The current position of the segmenter in the raw pixel data.
218  size_t position_ = 0;
219 
220  /// The position of the segmenter in the raw pixel data when creating new segments (thresholding), this is `segmentPosition_ = position_ + X`
221  size_t segmentPosition_ = 0;
222 
223  /// The memory holding the current segments
225 
226  /// The object that holds the recent pixel history.
228 };
229 
230 template <typename TPixel>
232 {
233  return deltas_[0];
234 }
235 
236 template <typename TPixel>
238 {
239  return deltas_[0] + deltas_[1];
240 }
241 
242 template <typename TPixel>
244 {
245  return deltas_[0] + deltas_[1] + deltas_[2];
246 }
247 
248 template <typename TPixel>
250 {
251  deltas_[2] = deltas_[1];
252  deltas_[1] = deltas_[0];
253  deltas_[0] = newDelta;
254 }
255 
256 template <typename TPixel>
258 {
259  deltas_[0] = 0;
260  deltas_[1] = 0;
261  deltas_[2] = 0;
262 }
263 
264 template <typename TPixel>
265 RowSegmenter<TPixel>::RowSegmenter(const TPixel* pixelData, const size_t pixelDataSize, const TGradient minimumGradient, const bool isNormalReflectance) :
266  pixelData_(pixelData),
267  size_(pixelDataSize),
268  minimumGradient_(minimumGradient)
269 {
270  if (isNormalReflectance)
271  {
274  }
275  else
276  {
279  }
280 
281  ocean_assert(isValid());
282 }
283 
284 template <typename TPixel>
286 {
287  return pixelData_ != nullptr && size_ != 0 && minimumGradient_ > TGradient(0) && isTransitionToForeground_ != nullptr && isTransitionToBackground_ != nullptr;
288 }
289 
290 template <typename TPixel>
292 {
293  if (!isValid())
294  {
295  return false;
296  }
297 
298  // Delete any previous segments
299  segmentData_.clear();
300 
301  transitionHistory_.reset();
302  ++position_;
303 
304  ocean_assert(position_ != 0);
305 
306  while (position_ < size_ && !isTransitionToForeground_(pixelData_ + position_, minimumGradient_, transitionHistory_))
307  {
308  ++position_;
309  }
310 
311  if (position_ < size_)
312  {
313  segmentPosition_ = position_;
314 
315  return true;
316  }
317 
318  return false;
319 }
320 
321 template <typename TPixel>
322 bool RowSegmenter<TPixel>::prepareSegments(const size_t numberSegments)
323 {
324  if (!isValid())
325  {
326  return false;
327  }
328 
329  if (numberSegments <= segmentData_.size())
330  {
331  // There are sufficient segments already, no need to find additional ones
332  return true;
333  }
334 
335 #if 1
336  // Use a gray threshold to determine the next segments.
337 
338  // Use the midpoint between the previous (background) and the current (foreground) pixel as gray threshold.
339  const TPixel grayThreshold_ = (pixelData_[position_ - 1] + pixelData_[position_]) / 2u;
340 
341  while (segmentPosition_ < size_ && numberSegments > segmentData_.size())
342  {
343  const bool atForeground = segmentData_.size() % 2 == 0;
344 
345  size_t nextSegmentPosition = segmentPosition_ + 1;
346 
347  if (atForeground)
348  {
349  while (nextSegmentPosition < size_ && pixelData_[nextSegmentPosition] < grayThreshold_)
350  {
351  nextSegmentPosition++;
352  }
353  }
354  else
355  {
356  while (nextSegmentPosition < size_ && pixelData_[nextSegmentPosition] >= grayThreshold_)
357  {
358  nextSegmentPosition++;
359  }
360  }
361 
362  ocean_assert(nextSegmentPosition >= segmentPosition_);
363  const uint32_t segmentSize = uint32_t(nextSegmentPosition - segmentPosition_); // nextSegmentPosition is the first element of the next segment, so no +1 necessary
364 
365  if (segmentSize == 0)
366  {
367  return false;
368  }
369 
370  segmentData_.emplace_back(segmentSize);
371  segmentPosition_ = nextSegmentPosition;
372  }
373 #else
374  // Determine the next segments by searching for intensity transitions, i.e. locations where the gradient exceeds a certain threshold.
375 
376  // Note: after experimentation, this seems to be easily affected by pixel noise. Using a longer transition history (smoothing) to reduce noise increases the minimum number of pixels per module.
377 
378  while (segmentPosition_ < pixelDataSize_ && numberSegments > segmentData_.size())
379  {
380  // Segment data alternates between foreground and background data. The first element is a foreground segment.
381  const bool atForeground = segmentData_.size() % 2 == 0;
382 
383  IsTransitionFunc isNextTransition = nullptr;
384 
385  if (atForeground)
386  {
387  isNextTransition = isTransitionToBackground_;
388  }
389  else
390  {
391  isNextTransition = isTransitionToForeground_;
392  }
393 
394  size_t nextSegmentPosition = segmentPosition_ + 1u;
395 
396  while (nextSegmentPosition < pixelDataSize_ && !isNextTransition(pixelData_ + nextSegmentPosition, minimumGradient_, transitionHistory_))
397  {
398  ++nextSegmentPosition;
399  }
400 
401  ocean_assert(nextSegmentPosition >= segmentPosition_);
402  const uint32_t segmentSize = uint32_t(nextSegmentPosition - segmentPosition_); // nextSegmentPosition is the first element of the next segment, so no +1 necessary
403 
404  if (segmentSize == 0)
405  {
406  return false;
407  }
408 
409  segmentData_.emplace_back(segmentSize);
410  segmentPosition_ = nextSegmentPosition;
411  }
412 #endif
413 
414  if (numberSegments <= segmentData_.size())
415  {
416  return true;
417  }
418 
419  return false;
420 }
421 
422 /**
423  * This class implements a detector for barcodes.
424  * @ingroup cvdetectorbarcodes
425  */
426 class OCEAN_CV_DETECTOR_BARCODES_EXPORT BarcodeDetector2D
427 {
428  public:
429 
430  /**
431  * Definition of optional detection features.
432  * @note Enabling additional features will reduce the runtime performance of the detector.
433  */
434  enum DetectionFeatures : uint32_t
435  {
436  /// Standard features that should be sufficient for most cases (excluding all the cases below).
437  DF_STANDARD = 0u,
438  /// Enables additional scan line directions, i.e. besides horizontal lines, there will also be scan lines at 45, 90, and 135 degrees around the image center.
439  DF_ENABLE_MULTIPLE_SCANLINE_DIRECTIONS = 1u << 0u,
440  /// Enables the search for barcodes that use inverted reflectance.
441  DF_ENABLE_INVERTED_REFLECTANCE = 1u << 1u,
442  /// Enables the detection of barcodes which are mirrored (e.g. when held up-side-down).
443  DF_ENABLE_SCANLINE_MIRRORING = 1u << 2u,
444  /// Enable the detection of multiple codes, otherwise the detection will stop after the first detected barcode.
445  DF_ENABLE_MULTI_CODE_DETECTION = 1u << 3u,
446  /// Enable the detection of duplicate codes; this will also enable the detection of multiple codes.
447  DF_ENABLE_MULTI_CODE_DETECTION_WITH_DUPLICATES = 1u << 4u | DF_ENABLE_MULTI_CODE_DETECTION,
448  /// Enable all of the available extra features.
449  DF_ENABLE_EVERYTHING = 0xFFFFFFFFu
450  };
451 
452  /**
453  * Definition of an observation of a barcode in 2D.
454  */
455  class OCEAN_CV_DETECTOR_BARCODES_EXPORT Observation
456  {
457  public:
458 
459  /**
460  * Creates an invalid observation.
461  */
462  Observation() = default;
463 
464  /**
465  * Create an observation from points.
466  */
467  Observation(const Vector2& startPoint, const Vector2& endPoint);
468 
469  /**
470  * Returns the location of the observation.
471  * @return The location of the observation.
472  */
473  const FiniteLine2& location() const;
474 
475  protected:
476 
477  /// The location of the observation.
479  };
480 
481  /// Definition of a vector of observations.
482  typedef std::vector<Observation> Observations;
483 
484  /// Definition of a function pointer for parser functions which detect the actual barcodes.
485  typedef bool (*ParserFunction)(const uint32_t* segmentData, const size_t size, Barcode& barcode, IndexPair32& xCoordinates);
486 
487  /// Definition of a set of parser functions.
488  typedef std::unordered_set<ParserFunction> ParserFunctionSet;
489 
490  public:
491 
492  /**
493  * Detects barcodes in an 8-bit grayscale image.
494  * @param yFrame The frame in which barcodes 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 70 x 70 pixels.
495  * @param detectionFeatures Optional flag to enable certain additional detection features.
496  * @param enabledBarcodeTypes A set of barcode types that will be detected; if empty, every supported barcode will be detected.
497  * @param scanlineSpacing The spacing between parallel scan lines in pixels, range: [1, infinity).
498  * @param observations Optional observations of the detected barcodes that will be returned, will be ignored if `nullptr`.
499  * @param scanlines Optionally resulting scan lines that were used during the detection, will be ignored if `nullptr`.
500  * @return The list of detected barcodes.
501  */
502  static Barcodes detectBarcodes(const Frame& yFrame, const uint32_t detectionFeatures = DF_STANDARD, const BarcodeTypeSet& enabledBarcodeTypes = BarcodeTypeSet(), const unsigned int scanlineSpacing = 25u, Observations* observations = nullptr, FiniteLines2* scanlines = nullptr);
503 
504  protected:
505 
506  /**
507  * Computes a vector pointing at a specific angle on a unit circle.
508  * @param angle The angle on the unit circle for which a corresponding vector is computed, range: [0, 2*PI].
509  * @param length The length that the resulting vector will have, range: (0, infinity).
510  * @return The vector
511  */
512  static Vector2 computeDirectionVector(const Scalar angle, const Scalar length = Scalar(1));
513 
514  /**
515  * Computes the intersection points of a frame and an intersecting infinite line.
516  * @param frameWidth The width of the frame that is intersected by the infinite line, range: [1, infinity).
517  * @param frameHeight The height of the frame that is intersected by the infinite line, range: [1, infinity).
518  * @param frameBorder The border on the inside of the frame that should be enforced between the frame and the intersection points, range: [0, min(frameWidth, frameHeight) / 2).
519  * @param line The infinite line to intersect with the frame, must be valid.
520  * @param point0 The resulting first intersection point.
521  * @param point1 The resulting second intersection point.
522  * @return True if an intersection has been found, otherwise false.
523  */
524  static bool computeFrameIntersection(const unsigned int frameWidth, const unsigned frameHeight, const unsigned int frameBorder, const Line2& line, CV::PixelPositionI& point0, CV::PixelPositionI& point1);
525 
526  /**
527  * Computes the locations of the scan lines for a given direction.
528  * The first scan line will intersect the frame center. All other scan lines will then be added alternatingly above and below the first scan line with increasing distance (`scanlineSpacing`) until they are outside the frame or below a minimum size.
529  * @param frameWidth The width of the frame that is intersected by the infinite line, range: [1, infinity).
530  * @param frameHeight The height of the frame that is intersected by the infinite line, range: [1, infinity).
531  * @param scanlineDirection The direction for which scan lines should be extracted, must be valid.
532  * @param scanlineSpacing The spacing between parallel scan lines in pixels, range: [1, infinity).
533  * @param frameBorder The border on the inside of the frame that should be enforced between the frame and the intersection points, range: [0, min(frameWidth, frameHeight) / 2).
534  * @param minimumScanlineLength The minimum length of scan lines that will be accepted, range: [1, infinity).
535  * @return The locations of the scan lines in the image, each defined by its end points in pixel coordinates.
536  */
537  static FiniteLines2 computeScanlines(const unsigned int frameWidth, const unsigned frameHeight, const Vector2& scanlineDirection, const unsigned int scanlineSpacing, const unsigned int frameBorder, const unsigned int minimumScanlineLength);
538 
539  /**
540  * Extracts the data of scan line specified by two points.
541  * Uses the Bresenham algorithm to extract the data between two points (scan line).
542  * @param yFrame The frame from which a scan line will be extracted, must be valid, have its origin in the upper left corner, and have a pixel format that is compatible with Y8.
543  * @param scanline The scan line for which image data will be extracted, must be inside the image boundary.
544  * @param scanlineData The resulting scan line data; it is suggested to reserve its memory before calling this function.
545  * @param scanlinePositions The resulting pixel positions of the elements of the scan line, will have the same size as `scanline`.
546  * @param minimumScanlineLength An optional minimum value of the size of the scan line; scan lines with fewer elements will be discarded and the function will return false; will be ignored if set to 0.
547  * @return True if a scan line has been successfully extracted and it has at least the minimum number of elements, otherwise false.
548  */
549  static bool extractScanlineData(const Frame& yFrame, const FiniteLine2& scanline, ScanlineData& scanlineData, CV::PixelPositionsI& scanlinePositions, const unsigned int minimumScanlineLength = 0u);
550 
551  /**
552  * Checks if a given pixel is a foreground pixel.
553  * @param pixelValue The pixel value that will be checked.
554  * @param grayThreshold The value of the gray threshold that is used to determine if the pixel is a foreground pixel.
555  * @return True if the pixel a is a foreground pixel, otherwise false.
556  * @tparam tIsNormalReflectance Indicates whether to consider foreground for normal or inverted reflectance.
557  */
558  template <bool tIsNormalReflectance>
559  static bool isForegroundPixel(const uint8_t pixelValue, const uint8_t grayThreshold);
560 
561  /**
562  * Returns the set of all available parser function pointers.
563  * @return The set of all available parser function pointers.
564  */
565  static ParserFunctionSet getParserFunctions(const BarcodeTypeSet& barcodeTypeSet);
566 };
567 
568 template <typename TPixel>
570 {
571  return segmentData_;
572 }
573 
574 template <typename TPixel>
576 {
577  return size_;
578 }
579 
580 template <typename TPixel>
582 {
583  return position_;
584 }
585 
586 template <typename TPixel>
587 bool RowSegmenter<TPixel>::setPosition(const size_t position)
588 {
589  if (position >= size_)
590  {
591  ocean_assert(false && "Invalid position value");
592  return false;
593  }
594 
595  position_ = position;
596  segmentPosition_ = position_;
597  transitionHistory_.reset();
598 
599  return true;
600 }
601 
602 template <typename TPixel>
603 bool RowSegmenter<TPixel>::isTransitionLightToDark(const TPixel* pixel, const TGradient gradientThreshold, TransitionHistory& history)
604 {
605  ocean_assert(pixel != nullptr);
606  ocean_assert(gradientThreshold > TGradient(0));
607 
608  const TGradient gradient = TGradient(*pixel) - TGradient(*(pixel - 1));
609 
610  bool isTransition = false;
611 
612  if (gradient < -gradientThreshold)
613  {
614  isTransition = true;
615  }
616  else
617  {
618  if (gradient + history.history1() < -gradientThreshold ||
619  gradient + history.history2() < -(gradientThreshold * 5 / 4)||
620  gradient + history.history3() < -(gradientThreshold * 6 / 4))
621  {
622  isTransition = true;
623  }
624  }
625 
626  history.push(gradient);
627 
628  return isTransition;
629 }
630 
631 template <typename TPixel>
632 bool RowSegmenter<TPixel>::isTransitionDarkToLight(const TPixel* pixel, const TGradient gradientThreshold, TransitionHistory& history)
633 {
634  ocean_assert(pixel != nullptr);
635  ocean_assert(gradientThreshold > TGradient(0));
636 
637  const TGradient gradient = TGradient(*pixel) - TGradient(*(pixel - 1));
638 
639  bool isTransition = false;
640 
641  if (gradient > gradientThreshold)
642  {
643  isTransition = true;
644  }
645  else
646  {
647  if (gradient + history.history1() > gradientThreshold ||
648  gradient + history.history2() > (gradientThreshold * 5 / 4)||
649  gradient + history.history3() > (gradientThreshold * 6 / 4))
650  {
651  isTransition = true;
652  }
653  }
654 
655  history.push(gradient);
656 
657  return isTransition;
658 }
659 
660 } // namespace Barcodes
661 
662 } // namespace Detector
663 
664 } // namespace CV
665 
666 } // namespace Ocean
Definition of an observation of a barcode in 2D.
Definition: BarcodeDetector2D.h:456
Observation()=default
Creates an invalid observation.
const FiniteLine2 & location() const
Returns the location of the observation.
FiniteLine2 location_
The location of the observation.
Definition: BarcodeDetector2D.h:478
Observation(const Vector2 &startPoint, const Vector2 &endPoint)
Create an observation from points.
This class implements a detector for barcodes.
Definition: BarcodeDetector2D.h:427
static FiniteLines2 computeScanlines(const unsigned int frameWidth, const unsigned frameHeight, const Vector2 &scanlineDirection, const unsigned int scanlineSpacing, const unsigned int frameBorder, const unsigned int minimumScanlineLength)
Computes the locations of the scan lines for a given direction.
static Vector2 computeDirectionVector(const Scalar angle, const Scalar length=Scalar(1))
Computes a vector pointing at a specific angle on a unit circle.
std::vector< Observation > Observations
Definition of a vector of observations.
Definition: BarcodeDetector2D.h:482
static bool isForegroundPixel(const uint8_t pixelValue, const uint8_t grayThreshold)
Checks if a given pixel is a foreground pixel.
static ParserFunctionSet getParserFunctions(const BarcodeTypeSet &barcodeTypeSet)
Returns the set of all available parser function pointers.
static Barcodes detectBarcodes(const Frame &yFrame, const uint32_t detectionFeatures=DF_STANDARD, const BarcodeTypeSet &enabledBarcodeTypes=BarcodeTypeSet(), const unsigned int scanlineSpacing=25u, Observations *observations=nullptr, FiniteLines2 *scanlines=nullptr)
Detects barcodes in an 8-bit grayscale image.
std::unordered_set< ParserFunction > ParserFunctionSet
Definition of a set of parser functions.
Definition: BarcodeDetector2D.h:488
static bool extractScanlineData(const Frame &yFrame, const FiniteLine2 &scanline, ScanlineData &scanlineData, CV::PixelPositionsI &scanlinePositions, const unsigned int minimumScanlineLength=0u)
Extracts the data of scan line specified by two points.
DetectionFeatures
Definition of optional detection features.
Definition: BarcodeDetector2D.h:435
static bool computeFrameIntersection(const unsigned int frameWidth, const unsigned frameHeight, const unsigned int frameBorder, const Line2 &line, CV::PixelPositionI &point0, CV::PixelPositionI &point1)
Computes the intersection points of a frame and an intersecting infinite line.
Definition of a barcode.
Definition: Barcode.h:52
This class implements a simple history for previous pixel transitions (a sliding window of pixel tran...
Definition: BarcodeDetector2D.h:80
TGradient history2()
Returns the history with window size N.
Definition: BarcodeDetector2D.h:237
TGradient history3()
Returns the history with window size N.
Definition: BarcodeDetector2D.h:243
TGradient history1()
Returns the history with window size N.
Definition: BarcodeDetector2D.h:231
void reset()
Resets the history object.
Definition: BarcodeDetector2D.h:257
TransitionHistory()=default
Creates a new history object.
void push(const TGradient newDelta)
Adds a new delta object as most recent history.
Definition: BarcodeDetector2D.h:249
TGradient deltas_[3]
The most recent deltas.
Definition: BarcodeDetector2D.h:121
This class converts raw pixel data into binary segments.
Definition: BarcodeDetector2D.h:68
RowSegmenter(const TPixel *pixelData, const size_t pixelDataSize, const TGradient minimumGradient, const bool isNormalReflectance)
Creates a segmenter object for a buffer of raw pixel data.
Definition: BarcodeDetector2D.h:265
size_t size_
The size of the raw pixel data in elements.
Definition: BarcodeDetector2D.h:212
static bool isTransitionLightToDark(const TPixel *pixel, const TGradient minimumGradient, TransitionHistory &history)
Checks if the specified pixel is a transition from light to dark pixels.
Definition: BarcodeDetector2D.h:603
bool prepareSegments(const size_t numberSegments)
Prepares a batch of segments.
Definition: BarcodeDetector2D.h:322
bool isValid() const
Returns if this segmenter is valid.
Definition: BarcodeDetector2D.h:285
TransitionHistory transitionHistory_
The object that holds the recent pixel history.
Definition: BarcodeDetector2D.h:227
DifferenceValueTyper< TPixel >::Type TGradient
Definition: BarcodeDetector2D.h:72
size_t size() const
Returns the size of the raw pixel data that is handled by this object.
Definition: BarcodeDetector2D.h:575
const TPixel * pixelData_
The pointer to the raw pixel data that will be processed by this object.
Definition: BarcodeDetector2D.h:209
SegmentData segmentData_
The memory holding the current segments.
Definition: BarcodeDetector2D.h:224
bool(* IsTransitionFunc)(const TPixel *, const TGradient, TransitionHistory &)
Definition of a function pointer for function that determine intensity transitions between back- and ...
Definition: BarcodeDetector2D.h:125
bool findNextTransitionToForeground()
Finds the next transition from background to foreground in the raw pixel data.
Definition: BarcodeDetector2D.h:291
IsTransitionFunc isTransitionToBackground_
A pointer to the function that checks if there is a transition from foreground to background (this de...
Definition: BarcodeDetector2D.h:206
size_t position_
The current position of the segmenter in the raw pixel data.
Definition: BarcodeDetector2D.h:218
bool setPosition(const size_t position)
Sets the position of the segmenter in the raw pixel data.
Definition: BarcodeDetector2D.h:587
static bool isTransitionDarkToLight(const TPixel *pixel, const TGradient minimumGradient, TransitionHistory &history)
Checks if the specified pixel is a transition from dark to light pixels.
Definition: BarcodeDetector2D.h:632
size_t position() const
Returns the current position of the segmenter in the raw pixel data.
Definition: BarcodeDetector2D.h:581
size_t segmentPosition_
The position of the segmenter in the raw pixel data when creating new segments (thresholding),...
Definition: BarcodeDetector2D.h:221
IsTransitionFunc isTransitionToForeground_
A pointer to the function that checks if there is a transition from background to foreground (this de...
Definition: BarcodeDetector2D.h:203
const SegmentData & segmentData() const
Returns the current segment data.
Definition: BarcodeDetector2D.h:569
TGradient minimumGradient_
The minimum value of the pixel gradient that must be exceed for it count as a intensity transition.
Definition: BarcodeDetector2D.h:215
This class implements a 2D pixel position with pixel precision.
Definition: PixelPosition.h:65
This class is a helper class allowing to define the signed difference data type of a given type.
Definition: DataType.h:169
This class implements Ocean's image class.
Definition: Frame.h:1792
This class implements an infinite line in 2D space.
Definition: Line2.h:83
std::pair< Index32, Index32 > IndexPair32
Definition of a pair holding 32 bit indices.
Definition: Base.h:138
std::vector< PixelPositionI > PixelPositionsI
Definition of a vector holding pixel positions (with positive and negative coordinate values).
Definition: PixelPosition.h:55
std::vector< uint32_t > SegmentData
Definition of segment data, i.e., a sequence of lengths of binary, alternating foreground and backgro...
Definition: Barcodes.h:65
std::vector< uint8_t > ScanlineData
Definition of scan line data, i.e., a sequence of raw pixel data.
Definition: Barcodes.h:59
float Scalar
Definition of a scalar type.
Definition: Math.h:128
std::vector< FiniteLine2 > FiniteLines2
Definition of a vector holding FiniteLine2 objects.
Definition: FiniteLine2.h:57
std::unordered_set< BarcodeType > BarcodeTypeSet
Definition of a set of barcode types.
Definition: Barcode.h:45
std::vector< Barcode > Barcodes
Definition of a vector of barcodes.
Definition: Barcode.h:25
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15