Enrollment 28.2.0
Loading...
Searching...
No Matches
PrintCapture.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include "enrollment/Export.h"
21
24#include <cmath>
25#include <memory>
26#include <mutex>
27#include <vector>
28// cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes: This is
29// not a problem because we are using them only as read only. cppcoreguidelines-avoid-const-or-ref-data-members: We
30// design te API with const member variables instead of implementing getter methods. This is nicely transformed in
31// C# to properties. Usually our objects are immutable by intention to have no problem in multithreaded
32// applications.
33// NOLINTBEGIN(cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members)
34namespace inno
35{
36 class Logger;
37 class PrintCapture;
38
39 // Internal interface to overcome cyclic includes between this header and PrintDetector.
40 // It is introduced to be possible to add convenient function PrintCapture::SegmentWith.
41 class PrintCaptureSegmentation
42 {
43 public:
49 virtual std::vector<std::shared_ptr<PrintSegment>> Segment(const std::shared_ptr<PrintCapture>& capture) = 0;
50
51 PrintCaptureSegmentation() = default;
52 virtual ~PrintCaptureSegmentation() = default;
53 PrintCaptureSegmentation(const PrintCaptureSegmentation&) = delete;
54 PrintCaptureSegmentation(PrintCaptureSegmentation&&) = delete;
55 PrintCaptureSegmentation& operator=(const PrintCaptureSegmentation&) = delete;
56 PrintCaptureSegmentation& operator=(PrintCaptureSegmentation&&) = delete;
57 };
58
63 */
64 class PrintCapture
65 : public CropablePrint
66 , public std::enable_shared_from_this<PrintCapture>
67 {
68 public:
70 const std::shared_ptr<Image> image;
73
81 */
82 static std::shared_ptr<PrintCapture> Create(
83 std::shared_ptr<Image> img,
84 const PrintAttributes& pa = PrintAttributes(),
85 std::shared_ptr<PrintExecutor> executor = GlobalPrintExecutor::Get())
86 {
87 return std::shared_ptr<PrintCapture>(new PrintCapture(std::move(img), pa, std::move(executor)));
88 }
89
98 */
99 [[nodiscard]] std::shared_ptr<PrintCapture> ChangeDpiTo(ImageDpi targetDpi) const
100 {
101 const Image::BicubicImageResampler resampler{ targetDpi };
102 return ChangeDpiTo(resampler);
103 }
104
114 */
115 [[nodiscard]] std::shared_ptr<PrintCapture> ChangeDpiTo(const Image::ImageResampler& resampler) const
116 {
117 return Create(image->ChangeDpiTo(resampler), printAttributes, exec);
118 }
119
128 */
129 virtual std::vector<std::shared_ptr<PrintSegment>> SegmentWith(PrintCaptureSegmentation& detector)
130 {
131 auto capture = shared_from_this();
132 auto segments = detector.Segment(capture);
133 DoModifySegments(segments);
134 return segments;
135 }
136
143 */
144 [[nodiscard]] std::shared_ptr<Image> CropPrint(const Rectangle& rectangle,
145 const PrintCropConfiguration& cfg) const final
146 {
147 if (cfg.IsAlignedCroppingEnabled())
148 {
149 return image->CropAlignedRectangle(rectangle, cfg.GetBackgroundColor(), cfg.GetImageDimensions());
150 }
151
152 return image->CropRectangle(rectangle, cfg.GetBackgroundColor(), cfg.GetImageDimensions());
153 }
154
160 */
161 [[nodiscard]] std::shared_ptr<Image> CropPrint(const Rectangle& rectangle) const
162 {
163 static const PrintCropConfiguration DefaultCropCfg;
164 return CropPrint(rectangle, DefaultCropCfg);
165 }
166
172 */
173 std::shared_ptr<Image> Draw(const std::vector<std::shared_ptr<PrintSegment>>& segments,
174 const ImageShapeAttributes& attr) const
175 {
176 const RoundingBoxesShape rbs(segments, attr);
177 return image->DrawShape(rbs);
178 }
179
183 */
184 void WriteTo(Writer& writer) const final
185 {
186 writer.Write("i", image);
187 writer.Write("a", printAttributes);
188 const std::scoped_lock lock(intensityMux);
189 if (intensity.has_value())
190 {
191 writer.Write("in", intensity.value());
192 }
193 DoWriteTo(writer);
194 }
195
198 */
199 uint8_t CalculateIntensity()
200 {
201 const std::scoped_lock lock(intensityMux);
202 if (!intensity.has_value())
203 {
204 intensity = Print::CalculateIntensity(image, exec);
205 }
206 return intensity.value();
207 }
208
209 PrintCapture(const PrintCapture&) = delete;
210 PrintCapture(PrintCapture&&) = delete;
211 PrintCapture& operator=(const PrintCapture&) = delete;
212 PrintCapture& operator=(PrintCapture&&) = delete;
213 virtual ~PrintCapture() = default;
214 PrintCapture() = delete;
215
216 protected:
217 explicit PrintCapture(std::shared_ptr<Image> i,
219 std::shared_ptr<PrintExecutor> executor = GlobalPrintExecutor::Get())
220 : image(std::move(i))
221 , printAttributes(std::move(pa))
222 , exec(std::move(executor))
223 {
224 if (image == nullptr)
225 {
226 throw NullArgumentException("Image cannot be null when creating PrintCapture");
227 }
228 }
229 virtual void DoWriteTo(Writer& /* writer */) const
230 {
231 }
232
233 virtual void DoModifySegments(std::vector<std::shared_ptr<PrintSegment>>& segments)
234 {
235 ClearPositionInSegments(segments);
236 }
237
238 void ClearPositionInSegments(std::vector<std::shared_ptr<PrintSegment>>& segments)
239 {
240 for (auto& s : segments)
241 {
242 if (s->HasPosition())
243 {
244 s = std::make_shared<PrintSegment>(
245 shared_from_this(), printAttributes, s->roundingBox, s->angle, 0, exec);
246 }
247 }
248 }
249
250 private:
251 class RoundingBoxesShape final : public ImageShape
252 {
253 public:
254 void DrawIn(ImageShapeDrawer& drawer) const final
255 {
256 for (const auto& s : segments)
257 {
258 auto rs = RectangleShape(s->roundingBox, attr);
259 rs.DrawIn(drawer);
260 }
261 }
262
263 RoundingBoxesShape(const std::vector<std::shared_ptr<PrintSegment>>& s, ImageShapeAttributes a)
264 : segments(s)
265 , attr(std::move(a))
266 {
267 }
268 RoundingBoxesShape() = delete;
269 virtual ~RoundingBoxesShape() = default;
270 RoundingBoxesShape(const RoundingBoxesShape&) = delete;
271 RoundingBoxesShape(RoundingBoxesShape&&) = delete;
272 RoundingBoxesShape& operator=(const RoundingBoxesShape&) = delete;
273 RoundingBoxesShape& operator=(RoundingBoxesShape&&) = delete;
274
275 private:
276 const std::vector<std::shared_ptr<PrintSegment>>& segments;
277 ImageShapeAttributes attr;
278 };
279
280 std::shared_ptr<PrintExecutor> exec;
281 mutable std::mutex printMutex;
282 mutable std::mutex intensityMux;
283 std::vector<std::shared_ptr<Print>> prints;
284 std::optional<uint8_t> intensity;
285 };
286
291 */
292 class GuessedHandPosition
293 {
294 public:
298 */
299 [[nodiscard]] bool IsGuessSuccessful() const
300 {
301 return hand.has_value();
302 }
307 */
308 [[nodiscard]] HandPosition GetHandPosition() const
309 {
310
311 if (!hand.has_value())
312 {
313 throw EnrollmentRuntimeException("Not possible to guess hand position");
314 }
315
316 return hand.value();
317 }
318
319 GuessedHandPosition() = default;
320 explicit GuessedHandPosition(HandPosition handPosition)
321 : hand(handPosition)
322 {
323 }
324 virtual ~GuessedHandPosition() = default;
325 GuessedHandPosition(const GuessedHandPosition&) = default;
326 GuessedHandPosition(GuessedHandPosition&&) = default;
327 GuessedHandPosition& operator=(const GuessedHandPosition&) = default;
328 GuessedHandPosition& operator=(GuessedHandPosition&&) = default;
329
330 private:
331 std::optional<HandPosition> hand;
332 };
333
338 */
339 class SlapCapture final : public PrintCapture
340 {
341 public:
343 const HandPosition hand;
344
352 */
353 std::vector<std::shared_ptr<PrintSegment>> SegmentWith(PrintCaptureSegmentation& detector) final
354 {
355 return PrintCapture::SegmentWith(detector);
356 }
357
366 */
367 static std::shared_ptr<SlapCapture> Create(std::shared_ptr<Image> img,
368 const HandPosition& hand,
369 const PrintAttributes& pa = PrintAttributes(),
370 std::shared_ptr<PrintExecutor> executor = GlobalPrintExecutor::Get())
371 {
372 return std::shared_ptr<SlapCapture>(new SlapCapture(std::move(img), hand, pa, std::move(executor)));
373 }
374
375 static GuessedHandPosition GuessHandPosition(const std::vector<std::shared_ptr<PrintSegment>>& segments)
376 {
377 int rightHand = 0;
378 int leftHand = 0;
379
380 for (const auto& i : segments)
381 {
382 if (i->HasPosition())
383 {
384 auto position = i->GetPosition();
385
386 if (position >= PrintPosition::RIGHT_THUMB && position <= PrintPosition::RIGHT_LITTLE)
387 {
388 rightHand++;
389 }
390
391 else if (position >= PrintPosition::LEFT_THUMB && position <= PrintPosition::LEFT_LITTLE)
392 {
393 leftHand++;
394 }
395 }
396 }
397
398 if (rightHand == 0 && leftHand > 0)
399 {
400 return GuessedHandPosition{ HandPosition::LEFT };
401 }
402 if (rightHand > 0 && leftHand == 0)
403 {
404 return GuessedHandPosition{ HandPosition::RIGHT };
405 }
406 return GuessedHandPosition{};
407 }
408
414 */
415 static int CalculateGlobalAngle(const std::vector<std::shared_ptr<inno::PrintSegment>>& segments)
416 {
417 if (segments.empty())
418 {
420 "Not possible to calculate global angle, no segments are given");
421 }
422
423 double sumSines = 0.0;
424 double sumCosines = 0.0;
425 constexpr int StraightAngle = 180;
426 constexpr int CompleteAngle = 360;
427 // The clang-tidy suggest to use 'std::numbers::pi'. Due to compilation issues with our dependency
428 // Boost 1.73 in Android NDK r26d (first version that contains 'number' header), we're unable to utilize the
429 // suggested change. NOLINTNEXTLINE(modernize-use-std-numbers)
430 constexpr double MathPI = 3.14159265358979323846;
431
432 for (const auto& segment : segments)
433 {
434 // Convert angle in degrees to radians.
435 const double radians = segment->angle * MathPI / StraightAngle;
436
437 // Add the sine and cosine components.
438 sumSines += sin(radians);
439 sumCosines += cos(radians);
440 }
441
442 // Calculate the average angle in radians
443 const double averageRadians = atan2(sumSines, sumCosines);
444
445 // Convert the average back to degrees
446 double averageDegrees = averageRadians * StraightAngle / MathPI;
447
448 if (averageDegrees < 0)
449 {
450 averageDegrees = CompleteAngle + averageDegrees;
451 }
452
453 return static_cast<int>(averageDegrees);
454 }
455
456 SlapCapture(const SlapCapture&) = delete;
457 SlapCapture(SlapCapture&&) = delete;
458 SlapCapture& operator=(const SlapCapture&) = delete;
459 SlapCapture& operator=(SlapCapture&&) = delete;
460 virtual ~SlapCapture() = default;
461 SlapCapture() = delete;
462
463 private:
464 SlapCapture(std::shared_ptr<Image> img,
465 HandPosition h,
466 const PrintAttributes& pa = PrintAttributes(),
467 std::shared_ptr<PrintExecutor> executor = GlobalPrintExecutor::Get())
468 : PrintCapture(std::move(img), pa, std::move(executor))
469 , hand(h)
470 {
471 }
472
473 void DoWriteTo(Writer& writer) const final
474 {
475 writer.Write("h", static_cast<unsigned int>(hand));
476 }
477
478 void DoModifySegments(std::vector<std::shared_ptr<PrintSegment>>& /*segments*/) final
479 {
480 // nothing to modify
481 }
482 };
483
488 */
489 class ThumbsCapture final : public PrintCapture
490 {
491 public:
499 */
500 std::vector<std::shared_ptr<PrintSegment>> SegmentWith(PrintCaptureSegmentation& detector) final
501 {
502 return PrintCapture::SegmentWith(detector);
503 }
504
512 */
513 static std::shared_ptr<ThumbsCapture> Create(
514 std::shared_ptr<Image> img,
515 const PrintAttributes& pa = PrintAttributes(),
516 std::shared_ptr<PrintExecutor> executor = GlobalPrintExecutor::Get())
517 {
518 return std::shared_ptr<ThumbsCapture>(new ThumbsCapture(std::move(img), pa, std::move(executor)));
519 }
520
521 ThumbsCapture(const ThumbsCapture&) = delete;
522 ThumbsCapture(ThumbsCapture&&) = delete;
523 ThumbsCapture& operator=(const ThumbsCapture&) = delete;
524 ThumbsCapture& operator=(ThumbsCapture&&) = delete;
525 virtual ~ThumbsCapture() = default;
526 ThumbsCapture() = delete;
527
528 private:
529 ThumbsCapture(std::shared_ptr<Image> img,
530 const PrintAttributes& pa,
531 std::shared_ptr<PrintExecutor> executor = GlobalPrintExecutor::Get())
532 : PrintCapture(std::move(img), pa, std::move(executor))
533 {
534 }
535
536 void DoWriteTo(Writer& /*writer*/) const final
537 {
538 // nothing more to serialize
539 }
540
541 void DoModifySegments(std::vector<std::shared_ptr<PrintSegment>>& segments) final
542 {
543 if (segments.size() == 2)
544 {
545 segments[0]->SetPosition(PrintPosition::LEFT_THUMB);
546 segments[1]->SetPosition(PrintPosition::RIGHT_THUMB);
547 }
548 else
549 {
550 ClearPositionInSegments(segments);
551 }
552 }
553 };
554} // namespace inno
555// NOLINTEND(cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members)
HandPosition
Hand to which slap belongs.
Definition HandPosition.h:17
@ RIGHT
Right hand position.
Definition HandPosition.h:21
@ LEFT
Left hand position.
Definition HandPosition.h:19
Base exception for all enrollment-sdk invalid argument exceptions.
Definition EnrollmentException.h:96
Base exception for all enrollment-sdk runtime exceptions.
Definition EnrollmentException.h:84
static std::shared_ptr< PrintExecutor > Get()
Provides current executor.
Definition PrintExecutor.h:1306
It represents guessed hand position of Slap.
Definition PrintCapture.h:292
bool IsGuessSuccessful() const
Definition PrintCapture.h:298
HandPosition GetHandPosition() const
Definition PrintCapture.h:307
Image DPI.
Definition ImageAttribute.h:47
It holds shape attributes such as color and line width.
Definition ImageShape.h:22
Image resampler for DPI-change operations, including upsampling and downsampling using bicubic interp...
Definition Image.h:584
Image resampler for DPI-change operations, including upsampling and downsampling.
Definition Image.h:530
Interface for library logging.
Definition Logger.h:45
Null argument is not allowed.
Definition EnrollmentException.h:156
Print attributes Holds the print attributes.
Definition PrintAttributes.h:34
It holds all functions and data related to print manipulation.
Definition PrintCapture.h:66
std::shared_ptr< PrintCapture > ChangeDpiTo(ImageDpi targetDpi) const
Create new PrintCapture with given DPI.
Definition PrintCapture.h:98
std::shared_ptr< Image > CropPrint(const Rectangle &rectangle, const PrintCropConfiguration &cfg) const final
It crops image with given rectangle and background color.
Definition PrintCapture.h:143
void WriteTo(Writer &writer) const final
Function serializes print via provided Writer.
Definition PrintCapture.h:183
virtual std::vector< std::shared_ptr< PrintSegment > > SegmentWith(PrintCaptureSegmentation &detector)
It segments print capture.
Definition PrintCapture.h:128
std::shared_ptr< Image > CropPrint(const Rectangle &rectangle) const
It crops image with given rectangle by default PrintCropConfiguration.
Definition PrintCapture.h:160
static std::shared_ptr< PrintCapture > Create(std::shared_ptr< Image > img, const PrintAttributes &pa=PrintAttributes(), std::shared_ptr< PrintExecutor > executor=GlobalPrintExecutor::Get())
Constructor of PrintCapture.
Definition PrintCapture.h:81
std::shared_ptr< Image > Draw(const std::vector< std::shared_ptr< PrintSegment > > &segments, const ImageShapeAttributes &attr) const
It draws rounding boxes into PrintCapture.
Definition PrintCapture.h:172
uint8_t CalculateIntensity()
Function calculates the image intensity.
Definition PrintCapture.h:198
const std::shared_ptr< Image > image
Provides PrintCapture Image.
Definition PrintCapture.h:69
const PrintAttributes printAttributes
Provides PrintCapture Image.
Definition PrintCapture.h:71
std::shared_ptr< PrintCapture > ChangeDpiTo(const Image::ImageResampler &resampler) const
Create new PrintCapture using provided DPI-change configuration.
Definition PrintCapture.h:114
Holds print cropping configuration.
Definition PrintSegment.h:35
uint8_t CalculateIntensity()
Function calculates the image intensity.
Definition Print.h:494
It holds rectangle vertexes, width, height.
Definition ImageAttribute.h:357
It represents PrintCapture with Slap.
Definition PrintCapture.h:339
static std::shared_ptr< SlapCapture > Create(std::shared_ptr< Image > img, const HandPosition &hand, const PrintAttributes &pa=PrintAttributes(), std::shared_ptr< PrintExecutor > executor=GlobalPrintExecutor::Get())
Constructor of SlapCapture.
Definition PrintCapture.h:366
const HandPosition hand
Provides given hand position.
Definition PrintCapture.h:342
static int CalculateGlobalAngle(const std::vector< std::shared_ptr< inno::PrintSegment > > &segments)
Calculates the global angle of segmented prints.
Definition PrintCapture.h:414
std::vector< std::shared_ptr< PrintSegment > > SegmentWith(PrintCaptureSegmentation &detector) final
It segments slap capture.
Definition PrintCapture.h:352
It represents PrintCapture with ThumbsCapture.
Definition PrintCapture.h:489
std::vector< std::shared_ptr< PrintSegment > > SegmentWith(PrintCaptureSegmentation &detector) final
It segments thumbs capture.
Definition PrintCapture.h:499
static std::shared_ptr< ThumbsCapture > Create(std::shared_ptr< Image > img, const PrintAttributes &pa=PrintAttributes(), std::shared_ptr< PrintExecutor > executor=GlobalPrintExecutor::Get())
Constructor sets image and attributes of ThumbsCapture.
Definition PrintCapture.h:512
Provides interface for serialization of all classes.
Definition Writer.h:164
@ LEFT_LITTLE
Little finger on left hand.
Definition PrintPosition.h:69
@ LEFT_THUMB
Thumb on left hand.
Definition PrintPosition.h:53
@ RIGHT_LITTLE
Little on right hand.
Definition PrintPosition.h:49
@ RIGHT_THUMB
Thumb on right hand.
Definition PrintPosition.h:33