Enrollment 28.2.0
Loading...
Searching...
No Matches
Iris.h
Go to the documentation of this file.
1
9
10#pragma once
11
13#include "enrollment/Export.h"
23#include <algorithm>
24#include <array>
25#include <memory>
26#include <mutex>
27#include <optional>
28#include <vector>
29
30// cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes: This is not a
31// problem because we are using them only as read only.
32// cppcoreguidelines-avoid-const-or-ref-data-members: We design te API with const member variables instead of
33// implementing getter methods. This is nicely transformed in C# to properties. Usually our objects are immutable by
34// intention to have no problem in multithreaded applications.
35// NOLINTBEGIN(cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members)
36namespace inno
37{
41 */
42 class IrisExtractorConfig : public Serializable
43 {
44 public:
47 */
48 enum class Type : uint8_t
49 {
56 ACCURATE,
62 FAST,
63 };
67 */
68 void SetExtractor(Type value)
69 {
70 type = value;
71 }
75 */
76 [[nodiscard]] Type GetExtractor() const
77 {
78 return type;
79 }
80
84 */
85 void WriteTo(Writer& writer) const final
86 {
87 writer.Write("t", static_cast<unsigned int>(type));
88 }
89
94 */
96 {
97 static const IrisExtractorConfig Cfg;
98 return Cfg;
99 }
104 IrisExtractorConfig() = default;
105 virtual ~IrisExtractorConfig() = default;
108 IrisExtractorConfig& operator=(const IrisExtractorConfig&) = default;
109 IrisExtractorConfig& operator=(IrisExtractorConfig&&) = default;
110
111 private:
112 Type type = Type::ACCURATE;
113 };
114
115 class Iris;
116
121 */
122 class IrisTemplate : public Serializable
123 {
124 public:
126 const std::vector<uint8_t> data;
127
132 */
134 {
135 return pos.has_value();
136 }
137
142 */
144 {
145 if (!pos.has_value())
146 {
147 throw EnrollmentRuntimeException("IrisTemplate has unknown biometric position");
148 }
149
150 return pos.value();
151 }
152
158 */
159 IrisSimilarityScore SimilarWith(const IrisTemplate& gallery) const
160 {
161 log.LogInfo("Matching irises %v - %v", *this, gallery);
162 float score = 0.0F;
163
164 exec->Match(data.data(), data.size(), gallery.data.data(), gallery.data.size(), &score, ThrowOnError{});
165 auto irisScore = static_cast<IrisSimilarityScore>(score);
166 log.LogInfo("Matching irises %v - %v with score %u from %f", *this, gallery, irisScore, score);
167 return irisScore;
168 }
169
175 */
176 unsigned int CalculateQuality()
177 {
178 const std::scoped_lock lock(qualityMux);
179
180 if (!quality.has_value())
181 {
182 int32_t q = 0;
183
184 exec->IrisQuality(data.data(), data.size(), &q, ThrowOnError{});
185
186 quality = q;
187 }
188
189 return static_cast<unsigned int>(quality.value());
190 }
191
195 */
196 [[nodiscard]] std::string GetVersion() const
197 {
198
199 uint32_t modelVersion = 0;
200 uint32_t enrollmentVersion = 0;
201 exec->GetTemplateVersion(data.data(), data.size(), &modelVersion, &enrollmentVersion, ThrowOnError{});
202
203 return std::to_string(modelVersion) + "." + std::to_string(enrollmentVersion);
204 }
205
209 */
210 void WriteTo(Writer& writer) const override
211 {
212 writer.WriteArray("t", data);
213
214 const std::scoped_lock lock(qualityMux);
215 if (quality.has_value())
216 {
217 writer.Write("q", quality.value());
218 }
219 }
220
228 */
229 IrisTemplate(std::vector<uint8_t>&& templ, std::shared_ptr<IrisExecutor> executor)
230 : data(std::move(templ))
231 , exec(std::move(executor))
232 , log(GlobalLogger::Get())
233 {
234 if (exec == nullptr)
235 {
236 throw NullArgumentException("executor can not be null");
237 }
238 if (data.empty())
239 {
240 throw InvalidTemplateException("Iris template MUST have data");
241 }
242 }
243
250 */
251 explicit IrisTemplate(std::vector<uint8_t>&& templ)
252 : data(std::move(templ))
253 , exec(GlobalIrisExecutor::Get())
254 , log(GlobalLogger::Get())
255 {
256 if (data.empty())
257 {
258 throw InvalidTemplateException("Iris template MUST have data");
259 }
260 }
261
269 */
270 IrisTemplate(const std::vector<uint8_t>& templ, std::shared_ptr<IrisExecutor> executor)
271 : data(templ)
272 , exec(std::move(executor))
273 , log(GlobalLogger::Get())
274 {
275 if (exec == nullptr)
276 {
277 throw NullArgumentException("executor can not be null");
278 }
279 if (data.empty())
280 {
281 throw InvalidTemplateException("Iris template MUST have data");
282 }
283 }
284
291 */
292 explicit IrisTemplate(const std::vector<uint8_t>& templ)
293 : data(templ)
294 , exec(GlobalIrisExecutor::Get())
295 , log(GlobalLogger::Get())
296 {
297 if (data.empty())
298 {
299 throw InvalidTemplateException("Iris template MUST have data");
300 }
301 }
302
310 */
311 IrisTemplate(std::vector<uint8_t>&& templ, IrisPosition position, std::shared_ptr<IrisExecutor> executor)
312 : data(std::move(templ))
313 , exec(std::move(executor))
314 , log(GlobalLogger::Get())
315 , pos(position)
316 {
317 if (exec == nullptr)
318 {
319 throw NullArgumentException("executor can not be null");
320 }
321 if (data.empty())
322 {
323 throw InvalidTemplateException("Iris template MUST have data");
324 }
325 }
326
333 */
334 explicit IrisTemplate(std::vector<uint8_t>&& templ, IrisPosition position)
335 : data(std::move(templ))
336 , exec(GlobalIrisExecutor::Get())
337 , log(GlobalLogger::Get())
338 , pos(position)
339 {
340 if (data.empty())
341 {
342 throw InvalidTemplateException("Iris template MUST have data");
343 }
344 }
345
353 */
354 IrisTemplate(const std::vector<uint8_t>& templ, IrisPosition position, std::shared_ptr<IrisExecutor> executor)
355 : data(templ)
356 , exec(std::move(executor))
357 , log(GlobalLogger::Get())
358 , pos(position)
359 {
360 if (exec == nullptr)
361 {
362 throw NullArgumentException("executor can not be null");
363 }
364 if (data.empty())
365 {
366 throw InvalidTemplateException("Iris template MUST have data");
367 }
368 }
369
376 */
377 explicit IrisTemplate(const std::vector<uint8_t>& templ, IrisPosition position)
378 : data(templ)
379 , exec(GlobalIrisExecutor::Get())
380 , log(GlobalLogger::Get())
381 , pos(position)
382 {
383 if (data.empty())
384 {
385 throw InvalidTemplateException("Iris template MUST have data");
386 }
387 }
388
389 [[nodiscard]] bool operator==(const IrisTemplate& other) const noexcept
390 {
391 return data == other.data && pos == other.pos;
392 }
393
394 [[nodiscard]] std::size_t Hash() const noexcept
395 {
396 std::size_t h = detail::HashBytes(data);
397 h = detail::HashCombine(h, static_cast<std::size_t>(pos.has_value()));
398 if (pos.has_value())
399 {
400 h = detail::HashCombine(h, static_cast<std::size_t>(pos.value()));
401 }
402 return h;
403 }
404
405 IrisTemplate(const IrisTemplate&) = delete;
406 IrisTemplate(IrisTemplate&&) = delete;
407 IrisTemplate& operator=(const IrisTemplate&) = delete;
408 IrisTemplate& operator=(IrisTemplate&&) = delete;
409 IrisTemplate() = delete;
410 virtual ~IrisTemplate() = default;
411
412 private:
413 mutable std::mutex qualityMux;
414 std::optional<uint32_t> quality;
415 std::shared_ptr<IrisExecutor> exec;
416 FormattingLogger log;
417 std::optional<IrisPosition> pos;
418 };
419
424 */
425 class ExtractedIris : public IrisTemplate
426 {
427 public:
429 const std::shared_ptr<Iris> iris;
430
439 */
440 static std::vector<std::shared_ptr<IrisTemplate>> ToTemplates(
441 const std::vector<std::shared_ptr<ExtractedIris>>& irises)
442 {
443 std::vector<std::shared_ptr<IrisTemplate>> templates(irises.size());
444 std::transform(irises.begin(), irises.end(), templates.begin(), [](const auto& t) { return t; });
445 return templates;
446 }
451 void WriteTo(Writer& writer) const final;
452
453 ExtractedIris(const ExtractedIris&) = delete;
454 ExtractedIris(ExtractedIris&&) = delete;
455 ExtractedIris& operator=(const ExtractedIris&) = delete;
456 ExtractedIris& operator=(ExtractedIris&&) = delete;
457 ExtractedIris() = delete;
458 virtual ~ExtractedIris() = default;
459
460 private:
461 static std::shared_ptr<ExtractedIris> Create(std::shared_ptr<Iris> iris,
462 IrisPosition position,
463 std::vector<uint8_t>&& templ,
464 std::shared_ptr<IrisExecutor> exec)
465 {
466 return std::shared_ptr<ExtractedIris>(
467 new ExtractedIris(std::move(iris), position, std::move(templ), std::move(exec)));
468 }
469
470 ExtractedIris(std::shared_ptr<Iris> i,
471 IrisPosition position,
472 std::vector<uint8_t>&& t,
473 std::shared_ptr<IrisExecutor> e)
474 : IrisTemplate(std::move(t), position, std::move(e))
475 , iris(std::move(i))
476 {
477 }
478
479 friend class Iris;
480 };
481
485 */
486 class Iris final
487 : public Serializable
488 , public std::enable_shared_from_this<Iris>
489 {
490 public:
492 const std::shared_ptr<Image> image;
496 const float confidence;
501
505 */
507 {
508
509 std::vector<Point> points;
510 constexpr size_t PolygonLinesCount = 2;
511 points.reserve(image->Width() * PolygonLinesCount);
512 auto addPoint = +[](void* container, int x, int y)
513 {
514 auto* ps = static_cast<std::vector<Point>*>(container);
515 ps->emplace_back(x, y);
516 };
517 exec->CalculateEyelid(irisHandler.get(), image->Width(), addPoint, &points, ThrowOnError{});
518
519 return Polygon{ std::move(points) };
520 }
521
522 private:
523 class IsoMask : public ImageMask
524 {
525 public:
526 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
527 inline static const RGBA Iso19794Sclera = RGBA(200, 200, 200, RGBA::FULLY_OPAQUE);
528 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
529 inline static const RGBA Iso19794Eyelid = RGBA(128, 128, 128, RGBA::FULLY_OPAQUE);
530
531 void MaskWith(ImageMasker& masker) const final
532 {
533 masker.MaskCircle(iris, ImageMaskConfiguration{ ImageMaskType::OUTSIDE, Iso19794Sclera });
534 masker.MaskPolygon(eyelid, ImageMaskConfiguration{ ImageMaskType::OUTSIDE, Iso19794Eyelid });
535 masker.AddToBlur(iris, ImageMaskType::OUTSIDE);
536 masker.AddToBlur(eyelid, ImageMaskType::OUTSIDE);
538 }
539
540 IsoMask(Circle c, Polygon p)
541 : iris(std::move(c))
542 , eyelid(std::move(p))
543 {
544 }
545 IsoMask() = delete;
546 virtual ~IsoMask() = default;
547 IsoMask(const IsoMask&) = delete;
548 IsoMask(IsoMask&&) = delete;
549 IsoMask& operator=(const IsoMask&) = delete;
550 IsoMask& operator=(IsoMask&&) = delete;
551
552 private:
553 Circle iris;
554 Polygon eyelid;
555 };
556
557 public:
573 */
574 std::shared_ptr<Image> GetISO19794IrisImage() const
575 {
576 if (image->RectangleIntersection(irisBox) != Image::Intersection::INSIDE)
577 {
578 throw EnrollmentInvalidArgumentException("Iris is not fully contained within the image");
579 }
580
581 auto mask = IsoMask{ Circle::CreateInscribedCircle(irisBox), CalculateEyelid() };
582
583 auto maskedImage = image->MaskImageBy(mask);
584
585 // Defined in 6.4 Cropped Iris Image of 19794-6:2011
586 constexpr float IrisMarginFactorW = 0.6F;
587 constexpr float IrisMarginFactorH = 0.2F;
588
589 const auto irisWidth = static_cast<float>(irisBox.GetWidth());
590 const auto irisHeight = static_cast<float>(irisBox.GetHeight());
591 const auto marginX = static_cast<X>((irisWidth / 2) * IrisMarginFactorW);
592 const auto marginY = static_cast<Y>((irisHeight / 2) * IrisMarginFactorH);
593
594 const Rectangle croppedRect{
595 { irisBox.GetTopLeft().x - marginX, irisBox.GetTopLeft().y - marginY },
596 { irisBox.GetTopRight().x + marginX, irisBox.GetTopRight().y - marginY },
597 { irisBox.GetBottomRight().x + marginX, irisBox.GetBottomRight().y + marginY },
598 { irisBox.GetBottomLeft().x - marginX, irisBox.GetBottomLeft().y + marginY },
599 };
600
601 auto croppedMaskedImage = maskedImage->CropRectangle(croppedRect);
602 return croppedMaskedImage;
603 }
604
615 */
616 std::vector<uint8_t> ToIsoImage(ImageEncoder& encoder) const
617 {
618 auto isoEncoder = IsoImageEncoder(*this, encoder);
619 return isoEncoder.Encode();
620 }
621
626 */
627 [[nodiscard]] std::vector<uint8_t> ToIsoRawImage() const
628 {
629 IsoImage isoImage(*this);
630 auto rawImage = image->AsRawGrayscale();
631 isoImage.SetImageFormat(IsoImage::ImageFormatMonoRaw);
632 return isoImage.FillIsoImage(rawImage.Data());
633 }
634
640 */
641 std::shared_ptr<ExtractedIris> Extract()
642 {
643 auto cfg = IrisExtractorConfig::Default();
644 return Extract(cfg);
645 }
646
653 */
654 std::shared_ptr<ExtractedIris> Extract(const IrisExtractorConfig& cfg)
655 {
656 log.LogInfo("Iris extraction for %v with cfg %v ...", image, cfg);
657
658 std::vector<uint8_t> templData;
659
660 exec->Extract(
661 irisHandler.get(),
662 +[](void* container, size_t size) -> uint8_t*
663 {
664 auto* data = static_cast<std::vector<uint8_t>*>(container);
665 data->resize(size);
666 return data->data();
667 },
668 &templData,
669 static_cast<unsigned int>(cfg.GetExtractor()),
670 ThrowOnError{});
671
672 auto iris = shared_from_this();
673 auto extractedIris = ExtractedIris::Create(iris, position, std::move(templData), exec);
674
675 log.LogInfo("Iris extraction result %v", extractedIris);
676
677 return extractedIris;
678 }
679
683 */
684 void WriteTo(Writer& writer) const final
685 {
686 writer.Write("i", image);
687 writer.Write("c", confidence);
688 writer.Write("p", static_cast<int>(position));
689 writer.Write("c", static_cast<unsigned int>(irisAttributes.GetCaptureDeviceTechnology()));
690 writer.Write("ei", static_cast<unsigned int>(irisAttributes.GetCaptureDeviceVendorID()));
691 writer.Write("dt", static_cast<unsigned int>(irisAttributes.GetCaptureDeviceTypeID()));
692 }
693
694 Iris(const Iris&) = delete;
695 Iris(Iris&&) = delete;
696 Iris& operator=(const Iris&) = delete;
697 Iris& operator=(Iris&&) = delete;
698 virtual ~Iris() = default;
699 Iris() = delete;
700
701 private:
702 std::shared_ptr<void> irisHandler;
703 Rectangle irisBox;
704 Rectangle pupilBox;
706 std::shared_ptr<IrisExecutor> exec;
707
708 /*
709 * Constructor sets image for extraction and Logger to log.
710 * @param img Iris image
711 * @param confidence is detection confidence
712 * @param position is iris position defined in IrisPosition enum
713 * @param ih detection handler
714 * @param irisBox is rounding box of iris
715 * @param pupilBox is rounding box of pupil
716 * @param log Logger
717 * @param exec iris functionality executor
718 * @param ia IrisAttributes
719 */
720 static std::shared_ptr<Iris> Create(std::shared_ptr<Image> img,
721 float confidence,
722 const IrisPosition& position,
723 std::shared_ptr<void> ih,
724 Rectangle irisBox,
725 Rectangle pupilBox,
726 std::shared_ptr<Logger> logger,
727 std::shared_ptr<IrisExecutor> exec,
728 const IrisAttributes& ia = IrisAttributes())
729 {
730 return std::shared_ptr<Iris>(new Iris(std::move(img),
731 confidence,
732 position,
733 std::move(ih),
734 std::move(irisBox),
735 std::move(pupilBox),
736 std::move(logger),
737 std::move(exec),
738 ia));
739 }
740
741 Iris(std::shared_ptr<Image> img,
742 float conf,
743 const IrisPosition& pos,
744 std::shared_ptr<void> ih,
745 Rectangle ic,
746 Rectangle pc,
747 std::shared_ptr<Logger> l,
748 std::shared_ptr<IrisExecutor> e,
749 IrisAttributes ia)
750 : image(std::move(img))
751 , confidence(conf)
752 , position(pos)
753 , irisAttributes(std::move(ia))
754 , irisHandler(std::move(ih))
755 , irisBox(std::move(ic))
756 , pupilBox(std::move(pc))
757 , log(std::move(l))
758 , exec(std::move(e))
759 {
760 if (exec == nullptr)
761 {
762 throw NullArgumentException("Could not create Iris due to executor can not be null");
763 }
764
765 if (image == nullptr)
766 {
767 throw NullArgumentException("Could not create Iris due to image can not be null");
768 }
769 }
770
771 class IsoImage
772 {
773 private:
774 size_t writeIndex = 0U;
775
776 public:
777 explicit IsoImage(const Iris& i)
778 : iris(i)
779 {
780 }
781 IsoImage() = delete;
782 ~IsoImage() = default;
783 IsoImage(const IsoImage&) = delete;
784 IsoImage(IsoImage&&) = delete;
785 IsoImage& operator=(const IsoImage&) = delete;
786 IsoImage& operator=(IsoImage&&) = delete;
787
788 void SetImageFormat(uint8_t ct)
789 {
790 imageFormat = ct;
791 }
792
793 std::vector<uint8_t> FillIsoImage(const std::vector<uint8_t>& encodedImage)
794 {
795 // General header contains 16 bytes.
796 static constexpr size_t GeneralHeaderLength = 16;
797
798 // Representation header contains 52 bytes.
799 static constexpr size_t RepresentationHeaderLength = 52;
800
801 // Length of encoded image.
802 auto imageLength = encodedImage.size();
803
804 // Representation length including the representation header length.
805 auto representationLength = RepresentationHeaderLength + imageLength;
806
807 // Record length with image data.
808 auto recordLength = GeneralHeaderLength + representationLength;
809
810 std::vector<uint8_t> isoImage;
811 isoImage.resize(recordLength);
812
813 FillGeneralHeader(isoImage, recordLength);
814 FillRepresentationHeader(isoImage, representationLength, imageLength);
815 FillRepresentationBody(isoImage, encodedImage);
816
817 return isoImage;
818 }
819
820 private:
821 static void ThrowWhenValueCannotFitInto4Bytes(size_t recordLength)
822 {
823 if (recordLength > static_cast<size_t>(std::numeric_limits<uint32_t>::max()))
824 {
825 throw EnrollmentRuntimeException("Invalid conversion size");
826 }
827 }
828
837 void FillGeneralHeader(std::vector<uint8_t>& isoImage, const size_t recordLength)
838 {
839 FillFormatIdentifier(isoImage);
840 FillVersionNumber(isoImage);
841 FillLengthOfRecord(isoImage, recordLength);
842 FillNumberOfRepresentations(isoImage);
843 FillCertificationFlag(isoImage);
844 FillNumberOfEyesRepresented(isoImage);
845 }
846
854 void FillFormatIdentifier(std::vector<uint8_t>& isoImage)
855 {
856 // Mandatory fields.
857 isoImage[writeIndex++] = 'I';
858 isoImage[writeIndex++] = 'I';
859 isoImage[writeIndex++] = 'R';
860 isoImage[writeIndex++] = '\0';
861 }
862
870 void FillVersionNumber(std::vector<uint8_t>& isoImage)
871 {
872 // Mandatory fields.
873 isoImage[writeIndex++] = '0';
874 isoImage[writeIndex++] = '2';
875 isoImage[writeIndex++] = '0';
876 isoImage[writeIndex++] = '\0';
877 }
878
888 void FillLengthOfRecord(std::vector<uint8_t>& isoImage, const size_t recordLength)
889 {
890 ThrowWhenValueCannotFitInto4Bytes(recordLength);
891
892 // Mandatory fields.
893 isoImage[writeIndex++] = static_cast<uint8_t>(recordLength >> ThreeBytesBitsCount);
894 isoImage[writeIndex++] = static_cast<uint8_t>((recordLength >> TwoBytesBitsCount) & ByteMask);
895 isoImage[writeIndex++] = static_cast<uint8_t>((recordLength >> OneByteBitsCount) & ByteMask);
896 isoImage[writeIndex++] = static_cast<uint8_t>(recordLength & ByteMask);
897 }
898
905 void FillNumberOfRepresentations(std::vector<uint8_t>& isoImage)
906 {
907 // Mandatory fields.
908 isoImage[writeIndex++] = 0x00;
909 isoImage[writeIndex++] = 0x01;
910 }
911
918 void FillCertificationFlag(std::vector<uint8_t>& isoImage)
919 {
920 isoImage[writeIndex++] = 0x00; // Mandatory field.
921 }
922
930 void FillNumberOfEyesRepresented(std::vector<uint8_t>& isoImage)
931 {
932 // Mandatory field.
933 isoImage[writeIndex] = 0x0;
934 if (iris.position == IrisPosition::LEFT_EYE || iris.position == IrisPosition::RIGHT_EYE)
935 {
936 isoImage[writeIndex] = 0x01;
937 }
938 writeIndex++;
939 }
940
947 void FillRepresentationHeader(std::vector<uint8_t>& isoImage,
948 size_t representationLength,
949 size_t imageLength)
950 {
951 FillRepresentationLength(isoImage, representationLength);
952 FillCaptureDateTime(isoImage);
953 FillCaptureDeviceTechnologyIdentifier(isoImage);
954 FillCaptureDeviceVendorIdentifier(isoImage);
955 FillCaptureDeviceTypeIdentifier(isoImage);
956 FillQualitySection(isoImage);
957 FillRepresentationSequenceNumber(isoImage);
958 FillEyeLabel(isoImage);
959 FillImageType(isoImage);
960 FillImageFormat(isoImage);
961 FillIrisImagePropertiesBitField(isoImage);
962 FillImageWidth(isoImage);
963 FillImageHeight(isoImage);
964 FillBitDepth(isoImage);
965 FillRange(isoImage);
966 FillRollAngleOfEye(isoImage);
967 FillRollAngleUncertainty(isoImage);
968 FillIrisCentreSmallestX(isoImage);
969 FillIrisCentreLargestX(isoImage);
970 FillIrisCentreSmallestY(isoImage);
971 FillIrisCentreLargestY(isoImage);
972 FillIrisDiameterSmallest(isoImage);
973 FillIrisDiameterLargest(isoImage);
974 FillImageLength(isoImage, imageLength);
975 }
976
985 void FillRepresentationLength(std::vector<uint8_t>& isoImage, size_t representationLength)
986 {
987 ThrowWhenValueCannotFitInto4Bytes(representationLength);
988
989 // Mandatory fields.
990 isoImage[writeIndex++] = static_cast<uint8_t>(representationLength >> ThreeBytesBitsCount);
991 isoImage[writeIndex++] = static_cast<uint8_t>((representationLength >> TwoBytesBitsCount) & ByteMask);
992 isoImage[writeIndex++] = static_cast<uint8_t>((representationLength >> OneByteBitsCount) & ByteMask);
993 isoImage[writeIndex++] = static_cast<uint8_t>(representationLength & ByteMask);
994 }
995
1003 void FillCaptureDateTime(std::vector<uint8_t>& isoImage)
1004 {
1005 // Mandatory fields.
1006 static constexpr uint8_t DummyValue = 0xff;
1007 isoImage[writeIndex++] = DummyValue; // year
1008 isoImage[writeIndex++] = DummyValue; // year
1009 isoImage[writeIndex++] = DummyValue; // month
1010 isoImage[writeIndex++] = DummyValue; // day
1011 isoImage[writeIndex++] = DummyValue; // hour
1012 isoImage[writeIndex++] = DummyValue; // minute
1013 isoImage[writeIndex++] = DummyValue; // second
1014 isoImage[writeIndex++] = DummyValue; // millisecond
1015 isoImage[writeIndex++] = DummyValue; // millisecond
1016 }
1017
1025 void FillCaptureDeviceTechnologyIdentifier(std::vector<uint8_t>& isoImage)
1026 {
1027 const IrisCaptureDeviceTechnology technology = iris.irisAttributes.GetCaptureDeviceTechnology();
1028 isoImage[writeIndex++] =
1029 static_cast<uint8_t>(IrisToIsoCaptureDeviceTechnology(technology)); // Mandatory field.
1030 }
1031
1040 void FillCaptureDeviceVendorIdentifier(std::vector<uint8_t>& isoImage)
1041 {
1042 // Mandatory fields.
1043 const IrisCaptureDeviceVendorID vendor = iris.irisAttributes.GetCaptureDeviceVendorID();
1044 isoImage[writeIndex++] = static_cast<uint8_t>(static_cast<unsigned int>(vendor) >> OneByteBitsCount);
1045 isoImage[writeIndex++] = static_cast<uint8_t>(static_cast<unsigned int>(vendor) & ByteMask);
1046 }
1047
1055 void FillCaptureDeviceTypeIdentifier(std::vector<uint8_t>& isoImage)
1056 {
1057 // Mandatory fields.
1058 const IrisCaptureDeviceTypeID type = iris.irisAttributes.GetCaptureDeviceTypeID();
1059 isoImage[writeIndex++] = static_cast<uint8_t>(static_cast<unsigned int>(type) >> OneByteBitsCount);
1060 isoImage[writeIndex++] = static_cast<uint8_t>(static_cast<unsigned int>(type) & ByteMask);
1061 }
1062
1069 void FillQualitySection(std::vector<uint8_t>& isoImage)
1070 {
1071 // Number of quality blocks
1072 isoImage[writeIndex++] = 0x00;
1073 }
1074
1082 void FillQualityBlockData(std::vector<uint8_t>& isoImage)
1083 {
1084 // Optional fields.
1085 FillQualityScore(isoImage);
1086 FillQualityAlgorithmVendorId(isoImage);
1087 FillQualityAlgorithmId(isoImage);
1088 }
1089
1099 void FillQualityScore(std::vector<uint8_t>& isoImage)
1100 {
1101 isoImage[writeIndex++] = 0x00; // Optional field.
1102 }
1103
1111 void FillQualityAlgorithmVendorId(std::vector<uint8_t>& isoImage)
1112 {
1113 // Optional fields.
1114 isoImage[writeIndex++] = 0x00;
1115 isoImage[writeIndex++] = 0x00;
1116 }
1117
1125 void FillQualityAlgorithmId(std::vector<uint8_t>& isoImage)
1126 {
1127 // Optional fields.
1128 isoImage[writeIndex++] = 0x00;
1129 isoImage[writeIndex++] = 0x00;
1130 }
1131
1137 void FillRepresentationSequenceNumber(std::vector<uint8_t>& isoImage)
1138 {
1139 // Mandatory fields.
1140 isoImage[writeIndex++] = 0x00;
1141 isoImage[writeIndex++] = 0x01;
1142 }
1143
1149 void FillEyeLabel(std::vector<uint8_t>& isoImage)
1150 {
1151 isoImage[writeIndex++] =
1152 static_cast<uint8_t>(IrisPositionToIsoPosition(iris.position)); // Mandatory field.
1153 }
1154
1160 void FillImageType(std::vector<uint8_t>& isoImage)
1161 {
1162 isoImage[writeIndex++] = static_cast<uint8_t>(IrisImageTypeToIso(iris.irisAttributes.GetImageType()));
1163 }
1164
1170 void FillImageFormat(std::vector<uint8_t>& isoImage)
1171 {
1172 isoImage[writeIndex++] = imageFormat;
1173 }
1174
1179 void FillIrisImagePropertiesBitField(std::vector<uint8_t>& isoImage)
1180 {
1181 isoImage[writeIndex++] = 0x00; // Mandatory field.
1182 }
1183
1189 void FillImageWidth(std::vector<uint8_t>& isoImage)
1190 {
1191 // Mandatory fields.
1192 isoImage[writeIndex++] = static_cast<uint8_t>(iris.image->Width() >> OneByteBitsCount);
1193 isoImage[writeIndex++] = static_cast<uint8_t>(iris.image->Width() & ByteMask);
1194 }
1195
1201 void FillImageHeight(std::vector<uint8_t>& isoImage)
1202 {
1203 // Mandatory fields.
1204 isoImage[writeIndex++] = static_cast<uint8_t>(iris.image->Height() >> OneByteBitsCount);
1205 isoImage[writeIndex++] = static_cast<uint8_t>(iris.image->Height() & ByteMask);
1206 }
1207
1214 void FillBitDepth(std::vector<uint8_t>& isoImage)
1215 {
1216 // The enrollment sdk image has always bit depth 8
1217 static constexpr uint8_t UsedBitDepth = 8;
1218 isoImage[writeIndex++] = UsedBitDepth;
1219 }
1220
1227 void FillRange(std::vector<uint8_t>& isoImage)
1228 {
1229 // Mandatory fields.
1230 isoImage[writeIndex++] = 0x00;
1231 isoImage[writeIndex++] = 0x00;
1232 }
1233
1240 void FillRollAngleOfEye(std::vector<uint8_t>& isoImage)
1241 {
1242 // Mandatory fields.
1243 isoImage[writeIndex++] = 0x00;
1244 isoImage[writeIndex++] = 0x00;
1245 }
1246
1254 void FillRollAngleUncertainty(std::vector<uint8_t>& isoImage)
1255 {
1256 // Mandatory fields.
1257 isoImage[writeIndex++] = 0x00;
1258 isoImage[writeIndex++] = 0x00;
1259 }
1260
1267 void FillIrisCentreSmallestX(std::vector<uint8_t>& isoImage)
1268 {
1269 // Mandatory fields.
1270 isoImage[writeIndex++] = 0x00;
1271 isoImage[writeIndex++] = 0x00;
1272 }
1273
1280 void FillIrisCentreLargestX(std::vector<uint8_t>& isoImage)
1281 {
1282 // Mandatory fields.
1283 isoImage[writeIndex++] = 0x00;
1284 isoImage[writeIndex++] = 0x00;
1285 }
1286
1293 void FillIrisCentreSmallestY(std::vector<uint8_t>& isoImage)
1294 {
1295 // Mandatory fields.
1296 isoImage[writeIndex++] = 0x00;
1297 isoImage[writeIndex++] = 0x00;
1298 }
1299
1306 void FillIrisCentreLargestY(std::vector<uint8_t>& isoImage)
1307 {
1308 // Mandatory fields.
1309 isoImage[writeIndex++] = 0x00;
1310 isoImage[writeIndex++] = 0x00;
1311 }
1312
1318 void FillIrisDiameterSmallest(std::vector<uint8_t>& isoImage)
1319 {
1320 // Mandatory fields.
1321 isoImage[writeIndex++] = 0x00;
1322 isoImage[writeIndex++] = 0x00;
1323 }
1324
1330 void FillIrisDiameterLargest(std::vector<uint8_t>& isoImage)
1331 {
1332 // Mandatory fields.
1333 isoImage[writeIndex++] = 0x00;
1334 isoImage[writeIndex++] = 0x00;
1335 }
1336
1342 void FillImageLength(std::vector<uint8_t>& isoImage, size_t imageLength)
1343 {
1344 ThrowWhenValueCannotFitInto4Bytes(imageLength);
1345
1346 // Mandatory fields.
1347 isoImage[writeIndex++] = static_cast<uint8_t>(imageLength >> ThreeBytesBitsCount);
1348 isoImage[writeIndex++] = static_cast<uint8_t>((imageLength >> TwoBytesBitsCount) & ByteMask);
1349 isoImage[writeIndex++] = static_cast<uint8_t>((imageLength >> OneByteBitsCount) & ByteMask);
1350 isoImage[writeIndex++] = static_cast<uint8_t>(imageLength & ByteMask);
1351 }
1352
1360 void FillRepresentationBody(std::vector<uint8_t>& isoImage, const std::vector<uint8_t>& encodedImage)
1361 {
1362 FillImageData(isoImage, encodedImage);
1363 }
1364
1371 void FillImageData(std::vector<uint8_t>& isoImage, const std::vector<uint8_t>& encodedImage)
1372 {
1373 std::copy(
1374 encodedImage.begin(), encodedImage.end(), isoImage.begin() + static_cast<ptrdiff_t>(writeIndex));
1375 writeIndex += encodedImage.size();
1376 }
1377
1378 const Iris& iris;
1379 static constexpr uint8_t ImageFormatUnknown = 255;
1380 uint8_t imageFormat = ImageFormatUnknown;
1381
1382 public:
1383 static constexpr uint8_t ImageFormatMonoRaw = 2;
1384 static constexpr uint8_t ImageFormatMonoJPG2000 = 10;
1385 static constexpr uint8_t ImageFormatMonoPNG = 14;
1386 static constexpr unsigned int OneByteBitsCount = 8U;
1387 static constexpr unsigned int TwoBytesBitsCount = 16U;
1388 static constexpr unsigned int ThreeBytesBitsCount = 24U;
1389 static constexpr unsigned int ByteMask = 0xffU;
1390 };
1391
1392 class IsoImageEncoder : public ImageEncoderVisitor
1393 {
1394 public:
1402 std::vector<uint8_t> Encode()
1403 {
1404 // Get necessary image data for creating iso image.
1405 encoder.Accept(*this);
1406
1407 // Get image data in requested format.
1408 auto encodedImage = iris.image->EncodeIn(encoder);
1409
1410 return isoImage.FillIsoImage(encodedImage);
1411 }
1412
1413 void Visit(const WsqImageEncoder& /* encoder */) final
1414 {
1415 throw EnrollmentInvalidArgumentException("Could not create ISO image for WSQ image format");
1416 }
1417
1418 void Visit(const JpgImageEncoder& /* encoder */) final
1419 {
1420 throw EnrollmentInvalidArgumentException("Could not create ISO image for JPG image format");
1421 }
1422
1423 void Visit(const Jp2ImageEncoder& /* jp2Encoder */) final
1424 {
1425 isoImage.SetImageFormat(IsoImage::ImageFormatMonoJPG2000);
1426 }
1427
1428 void Visit(const PngImageEncoder& /* encoder */) final
1429 {
1430 isoImage.SetImageFormat(IsoImage::ImageFormatMonoPNG);
1431 }
1432
1433 void Visit(const IRawImageEncoder& /* encoder */) final
1434 {
1435 throw EnrollmentInvalidArgumentException("Could not create ISO image for IRAW image format");
1436 }
1437
1438 void Visit(const BmpImageEncoder& /* encoder */) final
1439 {
1440 throw EnrollmentInvalidArgumentException("Could not create ISO image for BMP image format");
1441 }
1442
1443 void Visit(const TiffImageEncoder& /* encoder */) final
1444 {
1445 throw EnrollmentInvalidArgumentException("Could not create ISO image for TIFF image format");
1446 }
1447
1448 void Visit(const WebpImageEncoder& /* encoder */) final
1449 {
1450 throw EnrollmentInvalidArgumentException("Could not create ISO image for WEBP image format");
1451 }
1452
1453 // We can use references because this is inner class of Print and we always know the usage.
1454 // The references will be valid in whole class lifetime.
1455 IsoImageEncoder(const Iris& i, ImageEncoder& e)
1456 : iris(i)
1457 , encoder(e)
1458 , isoImage(IsoImage(i))
1459 {
1460 }
1461 IsoImageEncoder() = delete;
1462 virtual ~IsoImageEncoder() = default;
1463 IsoImageEncoder(const IsoImageEncoder&) = delete;
1464 IsoImageEncoder(IsoImageEncoder&&) = delete;
1465 IsoImageEncoder& operator=(const IsoImageEncoder&) = delete;
1466 IsoImageEncoder& operator=(IsoImageEncoder&&) = delete;
1467
1468 private:
1469 const Iris& iris;
1470 ImageEncoder& encoder;
1471 IsoImage isoImage;
1472 };
1473
1474 friend class IrisDetector;
1475 };
1477 inline void ExtractedIris::WriteTo(Writer& writer) const
1478 {
1479 writer.Write("i", iris);
1480 IrisTemplate::WriteTo(writer);
1481 }
1482} // namespace inno
1483// NOLINTEND(cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members)
static Circle CreateInscribedCircle(const Rectangle &rect)
Creates the largest circle that fits entirely within a given rectangle.
Definition ImageAttribute.h:703
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
ExtractedIris is template created by IrisExtractor with Iris that belongs to template.
Definition Iris.h:425
const std::shared_ptr< Iris > iris
Iris that is used to template extraction.
Definition Iris.h:428
void WriteTo(Writer &writer) const final
Function serializes ExtractedIris via provided Writer.
Definition Iris.h:1476
static std::vector< std::shared_ptr< IrisTemplate > > ToTemplates(const std::vector< std::shared_ptr< ExtractedIris > > &irises)
Converts a vector of ExtractedIris objects into a vector of IrisTemplate objects.
Definition Iris.h:439
It provides functions with format specifier to compose and log message via provided Logger.
Definition FormattingLogger.h:601
Holds instance of IrisExecutor.
Definition IrisExecutor.h:369
Holds instance of Logger.
Definition Logger.h:275
Interface for image formatting converting to ImageType.
Definition ImageEncoder.h:106
Configuration parameters for image masking operations, including mask type, and color.
Definition ImageMask.h:60
Defines the interface for applying mask to the image with a masker.
Definition ImageMask.h:193
Interface for image masking operations.
Definition ImageMask.h:122
@ INSIDE
Object is fully in Image.
Definition Image.h:129
Iris attributes Holds the iris attributes.
Definition IrisAttributes.h:32
It contains extraction configuration.
Definition Iris.h:42
Type GetExtractor() const
Function gets extractor type.
Definition Iris.h:75
void WriteTo(Writer &writer) const final
Function serializes configuration via provided Writer.
Definition Iris.h:84
Type
Type of neural network extractor.
Definition Iris.h:48
@ ACCURATE
Iris templates suitable for verification/identification of very high accuracy are created when accura...
Definition Iris.h:55
@ FAST
Iris templates suitable for verification of fairly good accuracy are created when fast mode is used.
Definition Iris.h:61
void SetExtractor(Type value)
Function sets type of extractor.
Definition Iris.h:67
IrisExtractorConfig()=default
default configuration.
static IrisExtractorConfig Default()
Provides default configuration.
Definition Iris.h:94
IrisTemplate is Innovatrics proprietary template created by IrisExtractor.
Definition Iris.h:122
IrisTemplate(const std::vector< uint8_t > &templ, IrisPosition position, std::shared_ptr< IrisExecutor > executor)
Construct a new IrisTemplate object, copy template data.
Definition Iris.h:353
IrisTemplate(const std::vector< uint8_t > &templ, std::shared_ptr< IrisExecutor > executor)
Construct a new IrisTemplate object, copy template data Biometric position is unknown.
Definition Iris.h:269
void WriteTo(Writer &writer) const override
Function serializes IrisTemplate via provided Writer.
Definition Iris.h:209
unsigned int CalculateQuality()
Calculates quality of IrisTemplate.
Definition Iris.h:175
std::string GetVersion() const
Provides version information of Innovatrics proprietary algorithm used to create the iris template.
Definition Iris.h:195
const std::vector< uint8_t > data
Template data.
Definition Iris.h:125
IrisTemplate(std::vector< uint8_t > &&templ)
Construct a new IrisTemplate object Biometric position is unknown.
Definition Iris.h:250
bool IsIrisTemplateBiometricPositionKnown() const
It checks if template contains known biometric position.
Definition Iris.h:132
IrisSimilarityScore SimilarWith(const IrisTemplate &gallery) const
Calculates IrisSimilarityScore for given IrisTemplate.
Definition Iris.h:158
IrisTemplate(std::vector< uint8_t > &&templ, IrisPosition position)
Construct a new IrisTemplate object GlobalIrisExecutor is used.
Definition Iris.h:333
IrisPosition GetIrisTemplateBiometricPosition() const
It returns biometric position to which template belongs.
Definition Iris.h:142
IrisTemplate(const std::vector< uint8_t > &templ)
Construct a new IrisTemplate object, copy template data Biometric position is unknown.
Definition Iris.h:291
IrisTemplate(std::vector< uint8_t > &&templ, IrisPosition position, std::shared_ptr< IrisExecutor > executor)
Construct a new IrisTemplate object.
Definition Iris.h:310
IrisTemplate(std::vector< uint8_t > &&templ, std::shared_ptr< IrisExecutor > executor)
Construct a new IrisTemplate object Biometric position is unknown.
Definition Iris.h:228
IrisTemplate(const std::vector< uint8_t > &templ, IrisPosition position)
Construct a new IrisTemplate object, copy template data GlobalIrisExecutor is used.
Definition Iris.h:376
It holds all functions and data related to iris manipulation.
Definition Iris.h:488
const float confidence
Provides confidence score of the iris related to iris detection.
Definition Iris.h:495
std::shared_ptr< ExtractedIris > Extract()
Function creates template for given image with default IrisExtractorConfig.
Definition Iris.h:640
void WriteTo(Writer &writer) const final
Function serializes Iris via provided Writer.
Definition Iris.h:683
std::vector< uint8_t > ToIsoRawImage() const
Function creates ISO image based on ISO/IEC 19794-6 (Iris image data) use RawImage.
Definition Iris.h:626
std::vector< uint8_t > ToIsoImage(ImageEncoder &encoder) const
Function creates ISO image based on ISO/IEC 19794-6 (Iris image data).
Definition Iris.h:615
Polygon CalculateEyelid() const
Provides polygon of lower and upper eyelid.
Definition Iris.h:505
const IrisAttributes irisAttributes
Provides IrisAttributes.
Definition Iris.h:499
const IrisPosition position
Provides IrisPosition.
Definition Iris.h:497
const std::shared_ptr< Image > image
Provides Iris Image.
Definition Iris.h:491
std::shared_ptr< ExtractedIris > Extract(const IrisExtractorConfig &cfg)
Function creates template for given image.
Definition Iris.h:653
std::shared_ptr< Image > GetISO19794IrisImage() const
Provides a cropped and masked iris image compliant with ISO/IEC 19794-6:2011 standards.
Definition Iris.h:573
Null argument is not allowed.
Definition EnrollmentException.h:156
It holds polygon points.
Definition ImageAttribute.h:765
It holds RGB color with transparency.
Definition ImageAttribute.h:908
@ FULLY_OPAQUE
Color is fully opaque, means it is visible.
Definition ImageAttribute.h:920
It holds rectangle vertexes, width, height.
Definition ImageAttribute.h:357
Provides interface for serialization of all classes.
Definition Writer.h:164
virtual void Write(const char *name, const Serializable &s)=0
Serialize serializable.
void WriteArray(const char *name, const std::vector< uint8_t > &value)
Serialize bytes from vector.
Definition Writer.h:233
int Y
Y coordinate.
Definition ImageAttribute.h:117
int X
X coordinate.
Definition ImageAttribute.h:112
@ ISO_19794_BORDER_BLURRING
Applies border blurring according to ISO/IEC 19794-6 standard.
Definition ImageMask.h:52
@ OUTSIDE
Mask is applied to the region outside the shape, preserving the area inside.
Definition ImageMask.h:27
IrisPosition
It is position of iris on face iso_19794-6_2011.
Definition IrisPosition.h:22
unsigned int IrisSimilarityScore
It is similarity score between iris Templates.
Definition SimilarityScore.h:40
static constexpr int IrisToIsoCaptureDeviceTechnology(IrisCaptureDeviceTechnology printCaptureDeviceTechnology)
Function converts IrisCaptureDeviceTechnology to ISO capture technology.
Definition IrisCaptureDeviceTechnology.h:39
static constexpr int IrisImageTypeToIso(IrisImageType type)
Function converts IrisImageType to ISO iris image type.
Definition IrisImageType.h:45
IrisCaptureDeviceTechnology
It shall indicate the class of capture device technology used to acquire the captured biometric sampl...
Definition IrisCaptureDeviceTechnology.h:22
static constexpr int IrisPositionToIsoPosition(IrisPosition irisPosition)
Function converts IrisPosition to ISO position.
Definition IrisPosition.h:36
@ RIGHT_EYE
Iris of right eye.
Definition IrisPosition.h:24
@ LEFT_EYE
Iris of left eye.
Definition IrisPosition.h:26