487 :
public Serializable
488 ,
public std::enable_shared_from_this<Iris>
492 const std::shared_ptr<Image>
image;
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)
514 auto* ps =
static_cast<std::vector<Point>*
>(container);
515 ps->emplace_back(x, y);
517 exec->CalculateEyelid(irisHandler.get(),
image->Width(), addPoint, &points, ThrowOnError{});
519 return Polygon{ std::move(points) };
540 IsoMask(Circle c, Polygon p)
542 , eyelid(std::move(p))
546 virtual ~IsoMask() =
default;
547 IsoMask(
const IsoMask&) =
delete;
548 IsoMask(IsoMask&&) =
delete;
549 IsoMask& operator=(
const IsoMask&) =
delete;
550 IsoMask& operator=(IsoMask&&) =
delete;
583 auto maskedImage =
image->MaskImageBy(mask);
586 constexpr float IrisMarginFactorW = 0.6F;
587 constexpr float IrisMarginFactorH = 0.2F;
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);
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 },
601 auto croppedMaskedImage = maskedImage->CropRectangle(croppedRect);
602 return croppedMaskedImage;
618 auto isoEncoder = IsoImageEncoder(*
this, encoder);
619 return isoEncoder.Encode();
629 IsoImage isoImage(*
this);
630 auto rawImage =
image->AsRawGrayscale();
631 isoImage.SetImageFormat(IsoImage::ImageFormatMonoRaw);
632 return isoImage.FillIsoImage(rawImage.Data());
641 std::shared_ptr<ExtractedIris>
Extract()
656 log.LogInfo(
"Iris extraction for %v with cfg %v ...",
image, cfg);
658 std::vector<uint8_t> templData;
662 +[](
void* container,
size_t size) -> uint8_t*
664 auto* data = static_cast<std::vector<uint8_t>*>(container);
672 auto iris = shared_from_this();
673 auto extractedIris = ExtractedIris::Create(iris,
position, std::move(templData), exec);
675 log.LogInfo(
"Iris extraction result %v", extractedIris);
677 return extractedIris;
686 writer.Write(
"i",
image);
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()));
696 Iris& operator=(
const Iris&) =
delete;
698 virtual ~Iris() =
default;
702 std::shared_ptr<void> irisHandler;
706 std::shared_ptr<IrisExecutor> exec;
720 static std::shared_ptr<Iris> Create(std::shared_ptr<Image> img,
723 std::shared_ptr<void> ih,
726 std::shared_ptr<Logger> logger,
727 std::shared_ptr<IrisExecutor> exec,
730 return std::shared_ptr<Iris>(
new Iris(std::move(img),
741 Iris(std::shared_ptr<Image> img,
744 std::shared_ptr<void> ih,
747 std::shared_ptr<Logger> l,
748 std::shared_ptr<IrisExecutor> e,
750 : image(std::move(img))
753 , irisAttributes(std::move(ia))
754 , irisHandler(std::move(ih))
755 , irisBox(std::move(ic))
756 , pupilBox(std::move(pc))
762 throw NullArgumentException(
"Could not create Iris due to executor can not be null");
765 if (image ==
nullptr)
767 throw NullArgumentException(
"Could not create Iris due to image can not be null");
774 size_t writeIndex = 0U;
777 explicit IsoImage(
const Iris& i)
782 ~IsoImage() =
default;
783 IsoImage(
const IsoImage&) =
delete;
784 IsoImage(IsoImage&&) =
delete;
785 IsoImage& operator=(
const IsoImage&) =
delete;
786 IsoImage& operator=(IsoImage&&) =
delete;
788 void SetImageFormat(uint8_t ct)
793 std::vector<uint8_t> FillIsoImage(
const std::vector<uint8_t>& encodedImage)
796 static constexpr size_t GeneralHeaderLength = 16;
799 static constexpr size_t RepresentationHeaderLength = 52;
802 auto imageLength = encodedImage.size();
805 auto representationLength = RepresentationHeaderLength + imageLength;
808 auto recordLength = GeneralHeaderLength + representationLength;
810 std::vector<uint8_t> isoImage;
811 isoImage.resize(recordLength);
813 FillGeneralHeader(isoImage, recordLength);
814 FillRepresentationHeader(isoImage, representationLength, imageLength);
815 FillRepresentationBody(isoImage, encodedImage);
821 static void ThrowWhenValueCannotFitInto4Bytes(
size_t recordLength)
823 if (recordLength >
static_cast<size_t>(std::numeric_limits<uint32_t>::max()))
825 throw EnrollmentRuntimeException(
"Invalid conversion size");
837 void FillGeneralHeader(std::vector<uint8_t>& isoImage,
const size_t recordLength)
839 FillFormatIdentifier(isoImage);
840 FillVersionNumber(isoImage);
841 FillLengthOfRecord(isoImage, recordLength);
842 FillNumberOfRepresentations(isoImage);
843 FillCertificationFlag(isoImage);
844 FillNumberOfEyesRepresented(isoImage);
854 void FillFormatIdentifier(std::vector<uint8_t>& isoImage)
857 isoImage[writeIndex++] =
'I';
858 isoImage[writeIndex++] =
'I';
859 isoImage[writeIndex++] =
'R';
860 isoImage[writeIndex++] =
'\0';
870 void FillVersionNumber(std::vector<uint8_t>& isoImage)
873 isoImage[writeIndex++] =
'0';
874 isoImage[writeIndex++] =
'2';
875 isoImage[writeIndex++] =
'0';
876 isoImage[writeIndex++] =
'\0';
888 void FillLengthOfRecord(std::vector<uint8_t>& isoImage,
const size_t recordLength)
890 ThrowWhenValueCannotFitInto4Bytes(recordLength);
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);
905 void FillNumberOfRepresentations(std::vector<uint8_t>& isoImage)
908 isoImage[writeIndex++] = 0x00;
909 isoImage[writeIndex++] = 0x01;
918 void FillCertificationFlag(std::vector<uint8_t>& isoImage)
920 isoImage[writeIndex++] = 0x00;
930 void FillNumberOfEyesRepresented(std::vector<uint8_t>& isoImage)
933 isoImage[writeIndex] = 0x0;
936 isoImage[writeIndex] = 0x01;
947 void FillRepresentationHeader(std::vector<uint8_t>& isoImage,
948 size_t representationLength,
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);
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);
985 void FillRepresentationLength(std::vector<uint8_t>& isoImage,
size_t representationLength)
987 ThrowWhenValueCannotFitInto4Bytes(representationLength);
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);
1003 void FillCaptureDateTime(std::vector<uint8_t>& isoImage)
1006 static constexpr uint8_t DummyValue = 0xff;
1007 isoImage[writeIndex++] = DummyValue;
1008 isoImage[writeIndex++] = DummyValue;
1009 isoImage[writeIndex++] = DummyValue;
1010 isoImage[writeIndex++] = DummyValue;
1011 isoImage[writeIndex++] = DummyValue;
1012 isoImage[writeIndex++] = DummyValue;
1013 isoImage[writeIndex++] = DummyValue;
1014 isoImage[writeIndex++] = DummyValue;
1015 isoImage[writeIndex++] = DummyValue;
1025 void FillCaptureDeviceTechnologyIdentifier(std::vector<uint8_t>& isoImage)
1028 isoImage[writeIndex++] =
1040 void FillCaptureDeviceVendorIdentifier(std::vector<uint8_t>& isoImage)
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);
1055 void FillCaptureDeviceTypeIdentifier(std::vector<uint8_t>& isoImage)
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);
1069 void FillQualitySection(std::vector<uint8_t>& isoImage)
1072 isoImage[writeIndex++] = 0x00;
1082 void FillQualityBlockData(std::vector<uint8_t>& isoImage)
1085 FillQualityScore(isoImage);
1086 FillQualityAlgorithmVendorId(isoImage);
1087 FillQualityAlgorithmId(isoImage);
1099 void FillQualityScore(std::vector<uint8_t>& isoImage)
1101 isoImage[writeIndex++] = 0x00;
1111 void FillQualityAlgorithmVendorId(std::vector<uint8_t>& isoImage)
1114 isoImage[writeIndex++] = 0x00;
1115 isoImage[writeIndex++] = 0x00;
1125 void FillQualityAlgorithmId(std::vector<uint8_t>& isoImage)
1128 isoImage[writeIndex++] = 0x00;
1129 isoImage[writeIndex++] = 0x00;
1137 void FillRepresentationSequenceNumber(std::vector<uint8_t>& isoImage)
1140 isoImage[writeIndex++] = 0x00;
1141 isoImage[writeIndex++] = 0x01;
1149 void FillEyeLabel(std::vector<uint8_t>& isoImage)
1151 isoImage[writeIndex++] =
1160 void FillImageType(std::vector<uint8_t>& isoImage)
1162 isoImage[writeIndex++] =
static_cast<uint8_t
>(
IrisImageTypeToIso(iris.irisAttributes.GetImageType()));
1170 void FillImageFormat(std::vector<uint8_t>& isoImage)
1172 isoImage[writeIndex++] = imageFormat;
1179 void FillIrisImagePropertiesBitField(std::vector<uint8_t>& isoImage)
1181 isoImage[writeIndex++] = 0x00;
1189 void FillImageWidth(std::vector<uint8_t>& isoImage)
1192 isoImage[writeIndex++] =
static_cast<uint8_t
>(iris.image->Width() >> OneByteBitsCount);
1193 isoImage[writeIndex++] =
static_cast<uint8_t
>(iris.image->Width() & ByteMask);
1201 void FillImageHeight(std::vector<uint8_t>& isoImage)
1204 isoImage[writeIndex++] =
static_cast<uint8_t
>(iris.image->Height() >> OneByteBitsCount);
1205 isoImage[writeIndex++] =
static_cast<uint8_t
>(iris.image->Height() & ByteMask);
1214 void FillBitDepth(std::vector<uint8_t>& isoImage)
1217 static constexpr uint8_t UsedBitDepth = 8;
1218 isoImage[writeIndex++] = UsedBitDepth;
1227 void FillRange(std::vector<uint8_t>& isoImage)
1230 isoImage[writeIndex++] = 0x00;
1231 isoImage[writeIndex++] = 0x00;
1240 void FillRollAngleOfEye(std::vector<uint8_t>& isoImage)
1243 isoImage[writeIndex++] = 0x00;
1244 isoImage[writeIndex++] = 0x00;
1254 void FillRollAngleUncertainty(std::vector<uint8_t>& isoImage)
1257 isoImage[writeIndex++] = 0x00;
1258 isoImage[writeIndex++] = 0x00;
1267 void FillIrisCentreSmallestX(std::vector<uint8_t>& isoImage)
1270 isoImage[writeIndex++] = 0x00;
1271 isoImage[writeIndex++] = 0x00;
1280 void FillIrisCentreLargestX(std::vector<uint8_t>& isoImage)
1283 isoImage[writeIndex++] = 0x00;
1284 isoImage[writeIndex++] = 0x00;
1293 void FillIrisCentreSmallestY(std::vector<uint8_t>& isoImage)
1296 isoImage[writeIndex++] = 0x00;
1297 isoImage[writeIndex++] = 0x00;
1306 void FillIrisCentreLargestY(std::vector<uint8_t>& isoImage)
1309 isoImage[writeIndex++] = 0x00;
1310 isoImage[writeIndex++] = 0x00;
1318 void FillIrisDiameterSmallest(std::vector<uint8_t>& isoImage)
1321 isoImage[writeIndex++] = 0x00;
1322 isoImage[writeIndex++] = 0x00;
1330 void FillIrisDiameterLargest(std::vector<uint8_t>& isoImage)
1333 isoImage[writeIndex++] = 0x00;
1334 isoImage[writeIndex++] = 0x00;
1342 void FillImageLength(std::vector<uint8_t>& isoImage,
size_t imageLength)
1344 ThrowWhenValueCannotFitInto4Bytes(imageLength);
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);
1360 void FillRepresentationBody(std::vector<uint8_t>& isoImage,
const std::vector<uint8_t>& encodedImage)
1362 FillImageData(isoImage, encodedImage);
1371 void FillImageData(std::vector<uint8_t>& isoImage,
const std::vector<uint8_t>& encodedImage)
1374 encodedImage.begin(), encodedImage.end(), isoImage.begin() +
static_cast<ptrdiff_t
>(writeIndex));
1375 writeIndex += encodedImage.size();
1379 static constexpr uint8_t ImageFormatUnknown = 255;
1380 uint8_t imageFormat = ImageFormatUnknown;
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;
1392 class IsoImageEncoder :
public ImageEncoderVisitor
1402 std::vector<uint8_t> Encode()
1405 encoder.Accept(*
this);
1408 auto encodedImage = iris.image->EncodeIn(encoder);
1410 return isoImage.FillIsoImage(encodedImage);
1413 void Visit(
const WsqImageEncoder& )
final
1415 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for WSQ image format");
1418 void Visit(
const JpgImageEncoder& )
final
1420 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for JPG image format");
1423 void Visit(
const Jp2ImageEncoder& )
final
1425 isoImage.SetImageFormat(IsoImage::ImageFormatMonoJPG2000);
1428 void Visit(
const PngImageEncoder& )
final
1430 isoImage.SetImageFormat(IsoImage::ImageFormatMonoPNG);
1433 void Visit(
const IRawImageEncoder& )
final
1435 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for IRAW image format");
1438 void Visit(
const BmpImageEncoder& )
final
1440 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for BMP image format");
1443 void Visit(
const TiffImageEncoder& )
final
1445 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for TIFF image format");
1448 void Visit(
const WebpImageEncoder& )
final
1450 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for WEBP image format");
1455 IsoImageEncoder(
const Iris& i, ImageEncoder& e)
1458 , isoImage(IsoImage(i))
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;
1470 ImageEncoder& encoder;
1474 friend class IrisDetector;