Ocean
Loading...
Searching...
No Matches
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
17
19#include "ocean/math/Line2.h"
20
21namespace Ocean
22{
23
24namespace CV
25{
26
27namespace Detector
28{
29
30namespace 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 */
66template <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 using IsTransitionFunc = bool (*)(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 /// True, if the foreground is darker than the background; false, if the reflectance is inverted
219
220 /// The current position of the segmenter in the raw pixel data.
221 size_t position_ = 0;
222
223 /// The position of the segmenter in the raw pixel data when creating new segments (thresholding), this is `segmentPosition_ = position_ + X`
225
226 /// The memory holding the current segments
228
229 /// The object that holds the recent pixel history.
231};
232
233template <typename TPixel>
238
239template <typename TPixel>
241{
242 return deltas_[0] + deltas_[1];
243}
244
245template <typename TPixel>
247{
248 return deltas_[0] + deltas_[1] + deltas_[2];
249}
250
251template <typename TPixel>
253{
254 deltas_[2] = deltas_[1];
255 deltas_[1] = deltas_[0];
256 deltas_[0] = newDelta;
257}
258
259template <typename TPixel>
261{
262 deltas_[0] = 0;
263 deltas_[1] = 0;
264 deltas_[2] = 0;
265}
266
267template <typename TPixel>
268RowSegmenter<TPixel>::RowSegmenter(const TPixel* pixelData, const size_t pixelDataSize, const TGradient minimumGradient, const bool isNormalReflectance) :
269 pixelData_(pixelData),
270 size_(pixelDataSize),
271 minimumGradient_(minimumGradient),
272 isNormalReflectance_(isNormalReflectance)
273{
274 if (isNormalReflectance)
275 {
278 }
279 else
280 {
283 }
284
285 ocean_assert(isValid());
286}
287
288template <typename TPixel>
290{
291 return pixelData_ != nullptr && size_ != 0 && minimumGradient_ > TGradient(0) && isTransitionToForeground_ != nullptr && isTransitionToBackground_ != nullptr;
292}
293
294template <typename TPixel>
296{
297 if (!isValid())
298 {
299 return false;
300 }
301
302 // Delete any previous segments
303 segmentData_.clear();
304
305 transitionHistory_.reset();
306 ++position_;
307
308 ocean_assert(position_ != 0);
309
310 while (position_ < size_ && !isTransitionToForeground_(pixelData_ + position_, minimumGradient_, transitionHistory_))
311 {
312 ++position_;
313 }
314
315 if (position_ < size_)
316 {
317 segmentPosition_ = position_;
318
319 return true;
320 }
321
322 return false;
323}
324
325template <typename TPixel>
326bool RowSegmenter<TPixel>::prepareSegments(const size_t numberSegments)
327{
328 if (!isValid())
329 {
330 return false;
331 }
332
333 if (numberSegments <= segmentData_.size())
334 {
335 // There are sufficient segments already, no need to find additional ones
336 return true;
337 }
338
339#if 1
340 // Use a gray threshold to determine the next segments.
341
342 // Use the midpoint between the previous (background) and the current (foreground) pixel as gray threshold.
343 ocean_assert(position_ > 0u);
344
345 if (position_ == 0u)
346 {
347 return false;
348 }
349
350 const TPixel grayThreshold_ = (pixelData_[position_ - 1] + pixelData_[position_]) / 2u;
351
352 while (segmentPosition_ < size_ && numberSegments > segmentData_.size())
353 {
354 const bool atForeground = segmentData_.size() % 2 == 0;
355
356 size_t nextSegmentPosition = segmentPosition_ + 1;
357
358 // a foreground pixel is darker than the threshold for normal reflectance, and brighter for inverted reflectance
359 const bool scanForDarkPixels = atForeground == isNormalReflectance_;
360
361 if (scanForDarkPixels)
362 {
363 while (nextSegmentPosition < size_ && pixelData_[nextSegmentPosition] < grayThreshold_)
364 {
365 nextSegmentPosition++;
366 }
367 }
368 else
369 {
370 while (nextSegmentPosition < size_ && pixelData_[nextSegmentPosition] >= grayThreshold_)
371 {
372 nextSegmentPosition++;
373 }
374 }
375
376 ocean_assert(nextSegmentPosition >= segmentPosition_);
377 const uint32_t segmentSize = uint32_t(nextSegmentPosition - segmentPosition_); // nextSegmentPosition is the first element of the next segment, so no +1 necessary
378
379 if (segmentSize == 0)
380 {
381 return false;
382 }
383
384 segmentData_.emplace_back(segmentSize);
385 segmentPosition_ = nextSegmentPosition;
386 }
387#else
388 // Determine the next segments by searching for intensity transitions, i.e. locations where the gradient exceeds a certain threshold.
389
390 // 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.
391
392 while (segmentPosition_ < size_ && numberSegments > segmentData_.size())
393 {
394 // Segment data alternates between foreground and background data. The first element is a foreground segment.
395 const bool atForeground = segmentData_.size() % 2 == 0;
396
397 IsTransitionFunc isNextTransition = nullptr;
398
399 if (atForeground)
400 {
401 isNextTransition = isTransitionToBackground_;
402 }
403 else
404 {
405 isNextTransition = isTransitionToForeground_;
406 }
407
408 size_t nextSegmentPosition = segmentPosition_ + 1u;
409
410 while (nextSegmentPosition < size_ && !isNextTransition(pixelData_ + nextSegmentPosition, minimumGradient_, transitionHistory_))
411 {
412 ++nextSegmentPosition;
413 }
414
415 ocean_assert(nextSegmentPosition >= segmentPosition_);
416 const uint32_t segmentSize = uint32_t(nextSegmentPosition - segmentPosition_); // nextSegmentPosition is the first element of the next segment, so no +1 necessary
417
418 if (segmentSize == 0)
419 {
420 return false;
421 }
422
423 segmentData_.emplace_back(segmentSize);
424 segmentPosition_ = nextSegmentPosition;
425 }
426#endif
427
428 if (numberSegments <= segmentData_.size())
429 {
430 return true;
431 }
432
433 return false;
434}
435
436/**
437 * This class implements a detector for barcodes.
438 * @ingroup cvdetectorbarcodes
439 */
440class OCEAN_CV_DETECTOR_BARCODES_EXPORT BarcodeDetector2D
441{
442 public:
443
444 /**
445 * Definition of optional detection features.
446 * @note Enabling additional features will reduce the runtime performance of the detector.
447 */
448 enum DetectionFeatures : uint32_t
449 {
450 /// Standard features that should be sufficient for most cases (excluding all the cases below).
451 DF_STANDARD = 0u,
452 /// 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.
453 DF_ENABLE_MULTIPLE_SCANLINE_DIRECTIONS = 1u << 0u,
454 /// Enables the search for barcodes that use inverted reflectance.
455 DF_ENABLE_INVERTED_REFLECTANCE = 1u << 1u,
456 /// Enables the detection of barcodes which are mirrored (e.g. when held up-side-down).
457 DF_ENABLE_SCANLINE_MIRRORING = 1u << 2u,
458 /// Enable the detection of multiple codes, otherwise the detection will stop after the first detected barcode.
459 DF_ENABLE_MULTI_CODE_DETECTION = 1u << 3u,
460 /// Enable the detection of duplicate codes; this will also enable the detection of multiple codes.
461 DF_ENABLE_MULTI_CODE_DETECTION_WITH_DUPLICATES = 1u << 4u | DF_ENABLE_MULTI_CODE_DETECTION,
462 /// Enable all of the available extra features.
463 DF_ENABLE_EVERYTHING = 0xFFFFFFFFu
464 };
465
466 /**
467 * Definition of an observation of a barcode in 2D.
468 */
469 class OCEAN_CV_DETECTOR_BARCODES_EXPORT Observation
470 {
471 public:
472
473 /**
474 * Creates an invalid observation.
475 */
476 Observation() = default;
477
478 /**
479 * Create an observation from points.
480 */
481 Observation(const Vector2& startPoint, const Vector2& endPoint);
482
483 /**
484 * Returns the location of the observation.
485 * @return The location of the observation.
486 */
487 const FiniteLine2& location() const;
488
489 protected:
490
491 /// The location of the observation.
493 };
494
495 /// Definition of a vector of observations.
496 using Observations = std::vector<Observation>;
497
498 /// Definition of a function pointer for parser functions which detect the actual barcodes.
499 using ParserFunction = bool (*)(const uint32_t* segmentData, const size_t size, Barcode& barcode, IndexPair32& xCoordinates);
500
501 /// Definition of a set of parser functions.
502 using ParserFunctionSet = std::unordered_set<ParserFunction>;
503
504 public:
505
506 /**
507 * Detects barcodes in an 8-bit grayscale image.
508 * @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.
509 * @param detectionFeatures Optional flag to enable certain additional detection features.
510 * @param enabledBarcodeTypes A set of barcode types that will be detected; if empty, every supported barcode will be detected.
511 * @param scanlineSpacing The spacing between parallel scan lines in pixels, range: [1, infinity).
512 * @param observations Optional observations of the detected barcodes that will be returned, will be ignored if `nullptr`.
513 * @param scanlines Optionally resulting scan lines that were used during the detection, will be ignored if `nullptr`.
514 * @return The list of detected barcodes.
515 */
516 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);
517
518 protected:
519
520 /**
521 * Computes a vector pointing at a specific angle on a unit circle.
522 * @param angle The angle on the unit circle for which a corresponding vector is computed, range: [0, 2*PI].
523 * @param length The length that the resulting vector will have, range: (0, infinity).
524 * @return The vector
525 */
526 static Vector2 computeDirectionVector(const Scalar angle, const Scalar length = Scalar(1));
527
528 /**
529 * Computes the intersection points of a frame and an intersecting infinite line.
530 * @param frameWidth The width of the frame that is intersected by the infinite line, range: [1, infinity).
531 * @param frameHeight The height of the frame that is intersected by the infinite line, range: [1, infinity).
532 * @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).
533 * @param line The infinite line to intersect with the frame, must be valid.
534 * @param point0 The resulting first intersection point.
535 * @param point1 The resulting second intersection point.
536 * @return True if an intersection has been found, otherwise false.
537 */
538 static bool computeFrameIntersection(const unsigned int frameWidth, const unsigned frameHeight, const unsigned int frameBorder, const Line2& line, CV::PixelPositionI& point0, CV::PixelPositionI& point1);
539
540 /**
541 * Computes the locations of the scan lines for a given direction.
542 * 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.
543 * @param frameWidth The width of the frame that is intersected by the infinite line, range: [1, infinity).
544 * @param frameHeight The height of the frame that is intersected by the infinite line, range: [1, infinity).
545 * @param scanlineDirection The direction for which scan lines should be extracted, must be valid.
546 * @param scanlineSpacing The spacing between parallel scan lines in pixels, range: [1, infinity).
547 * @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).
548 * @param minimumScanlineLength The minimum length of scan lines that will be accepted, range: [1, infinity).
549 * @return The locations of the scan lines in the image, each defined by its end points in pixel coordinates.
550 */
551 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);
552
553 /**
554 * Extracts the data of scan line specified by two points.
555 * Uses the Bresenham algorithm to extract the data between two points (scan line).
556 * @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.
557 * @param scanline The scan line for which image data will be extracted, must be inside the image boundary.
558 * @param scanlineData The resulting scan line data; it is suggested to reserve its memory before calling this function.
559 * @param scanlinePositions The resulting pixel positions of the elements of the scan line, will have the same size as `scanline`.
560 * @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.
561 * @return True if a scan line has been successfully extracted and it has at least the minimum number of elements, otherwise false.
562 */
563 static bool extractScanlineData(const Frame& yFrame, const FiniteLine2& scanline, ScanlineData& scanlineData, CV::PixelPositionsI& scanlinePositions, const unsigned int minimumScanlineLength = 0u);
564
565 /**
566 * Checks if a given pixel is a foreground pixel.
567 * @param pixelValue The pixel value that will be checked.
568 * @param grayThreshold The value of the gray threshold that is used to determine if the pixel is a foreground pixel.
569 * @return True if the pixel a is a foreground pixel, otherwise false.
570 * @tparam tIsNormalReflectance Indicates whether to consider foreground for normal or inverted reflectance.
571 */
572 template <bool tIsNormalReflectance>
573 static bool isForegroundPixel(const uint8_t pixelValue, const uint8_t grayThreshold);
574
575 /**
576 * Returns the set of all available parser function pointers.
577 * @return The set of all available parser function pointers.
578 */
580};
581
582template <typename TPixel>
584{
585 return segmentData_;
586}
587
588template <typename TPixel>
590{
591 return size_;
592}
593
594template <typename TPixel>
596{
597 return position_;
598}
599
600template <typename TPixel>
601bool RowSegmenter<TPixel>::setPosition(const size_t position)
602{
603 if (position >= size_)
604 {
605 ocean_assert(false && "Invalid position value");
606 return false;
607 }
608
609 position_ = position;
610 segmentPosition_ = position_;
611 transitionHistory_.reset();
612
613 return true;
614}
615
616template <typename TPixel>
617bool RowSegmenter<TPixel>::isTransitionLightToDark(const TPixel* pixel, const TGradient gradientThreshold, TransitionHistory& history)
618{
619 ocean_assert(pixel != nullptr);
620 ocean_assert(gradientThreshold > TGradient(0));
621
622 const TGradient gradient = TGradient(*pixel) - TGradient(*(pixel - 1));
623
624 bool isTransition = false;
625
626 if (gradient < -gradientThreshold)
627 {
628 isTransition = true;
629 }
630 else
631 {
632 if (gradient + history.history1() < -gradientThreshold ||
633 gradient + history.history2() < -(gradientThreshold * 5 / 4)||
634 gradient + history.history3() < -(gradientThreshold * 6 / 4))
635 {
636 isTransition = true;
637 }
638 }
639
640 history.push(gradient);
641
642 return isTransition;
643}
644
645template <typename TPixel>
646bool RowSegmenter<TPixel>::isTransitionDarkToLight(const TPixel* pixel, const TGradient gradientThreshold, TransitionHistory& history)
647{
648 ocean_assert(pixel != nullptr);
649 ocean_assert(gradientThreshold > TGradient(0));
650
651 const TGradient gradient = TGradient(*pixel) - TGradient(*(pixel - 1));
652
653 bool isTransition = false;
654
655 if (gradient > gradientThreshold)
656 {
657 isTransition = true;
658 }
659 else
660 {
661 if (gradient + history.history1() > gradientThreshold ||
662 gradient + history.history2() > (gradientThreshold * 5 / 4)||
663 gradient + history.history3() > (gradientThreshold * 6 / 4))
664 {
665 isTransition = true;
666 }
667 }
668
669 history.push(gradient);
670
671 return isTransition;
672}
673
674} // namespace Barcodes
675
676} // namespace Detector
677
678} // namespace CV
679
680} // namespace Ocean
Definition of an observation of a barcode in 2D.
Definition BarcodeDetector2D.h:470
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:492
Observation(const Vector2 &startPoint, const Vector2 &endPoint)
Create an observation from points.
This class implements a detector for barcodes.
Definition BarcodeDetector2D.h:441
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.
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:502
std::vector< Observation > Observations
Definition of a vector of observations.
Definition BarcodeDetector2D.h:496
bool(*)(const uint32_t *segmentData, const size_t size, Barcode &barcode, IndexPair32 &xCoordinates) ParserFunction
Definition of a function pointer for parser functions which detect the actual barcodes.
Definition BarcodeDetector2D.h:499
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:449
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:240
TGradient history3()
Returns the history with window size N.
Definition BarcodeDetector2D.h:246
TGradient history1()
Returns the history with window size N.
Definition BarcodeDetector2D.h:234
void reset()
Resets the history object.
Definition BarcodeDetector2D.h:260
TransitionHistory()=default
Creates a new history object.
void push(const TGradient newDelta)
Adds a new delta object as most recent history.
Definition BarcodeDetector2D.h:252
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:268
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:617
bool prepareSegments(const size_t numberSegments)
Prepares a batch of segments.
Definition BarcodeDetector2D.h:326
bool isValid() const
Returns if this segmenter is valid.
Definition BarcodeDetector2D.h:289
TransitionHistory transitionHistory_
The object that holds the recent pixel history.
Definition BarcodeDetector2D.h:230
size_t size() const
Returns the size of the raw pixel data that is handled by this object.
Definition BarcodeDetector2D.h:589
bool(*)(const TPixel *, const TGradient, TransitionHistory &) IsTransitionFunc
Definition of a function pointer for function that determine intensity transitions between back- and ...
Definition BarcodeDetector2D.h:125
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:227
typename DifferenceValueTyper< TPixel >::Type TGradient
Definition BarcodeDetector2D.h:72
bool findNextTransitionToForeground()
Finds the next transition from background to foreground in the raw pixel data.
Definition BarcodeDetector2D.h:295
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:221
bool setPosition(const size_t position)
Sets the position of the segmenter in the raw pixel data.
Definition BarcodeDetector2D.h:601
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:646
size_t position() const
Returns the current position of the segmenter in the raw pixel data.
Definition BarcodeDetector2D.h:595
size_t segmentPosition_
The position of the segmenter in the raw pixel data when creating new segments (thresholding),...
Definition BarcodeDetector2D.h:224
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:583
TGradient minimumGradient_
The minimum value of the pixel gradient that must be exceed for it count as a intensity transition.
Definition BarcodeDetector2D.h:215
bool isNormalReflectance_
True, if the foreground is darker than the background; false, if the reflectance is inverted.
Definition BarcodeDetector2D.h:218
This class implements a 2D pixel position with pixel precision.
Definition PixelPosition.h:63
T Type
Definition of the data type for the signed difference value.
Definition DataType.h:176
This class implements Ocean's image class.
Definition Frame.h:1969
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:53
std::vector< uint8_t > ScanlineData
Definition of scan line data, i.e., a sequence of raw pixel data.
Definition Barcodes.h:59
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
float Scalar
Definition of a scalar type.
Definition Math.h:129
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:28
The namespace covering the entire Ocean framework.
Definition Accessor.h:15