593 :
public Serializable
594 ,
public std::enable_shared_from_this<Face>
602 class Keypoint :
public Serializable
622 [[nodiscard]]
float GetScore()
const
644 : pos(std::move(position))
645 , score(reliabilityScore)
649 friend class Keypoints;
658 class Keypoints :
public Serializable
671 return CalculateKeypoint(exec->GetRightEyeOuterCornerId(),
"reoc");
684 return CalculateKeypoint(exec->GetRightEyeCentreId(),
"rec");
697 return CalculateKeypoint(exec->GetRightEyeInnerCornerId(),
"reic");
710 return CalculateKeypoint(exec->GetLeftEyeInnerCornerId(),
"leic");
723 return CalculateKeypoint(exec->GetLeftEyeCentreId(),
"lec");
736 return CalculateKeypoint(exec->GetLeftEyeOuterCornerId(),
"leoc");
747 return CalculateKeypoint(exec->GetNoseRootId(),
"nr");
760 return CalculateKeypoint(exec->GetNoseRightBottomId(),
"nrb");
771 return CalculateKeypoint(exec->GetNoseTipId(),
"nt");
784 return CalculateKeypoint(exec->GetNoseLeftBottomId(),
"nlb");
795 return CalculateKeypoint(exec->GetNoseBottomId(),
"nb");
808 return CalculateKeypoint(exec->GetMouthRightCornerId(),
"mrc");
819 return CalculateKeypoint(exec->GetMouthCenterId(),
"mc");
832 return CalculateKeypoint(exec->GetMouthLeftCornerId(),
"mlc");
843 return CalculateKeypoint(exec->GetMouthUpperEdgeId(),
"mue");
854 return CalculateKeypoint(exec->GetMouthLowerEdgeId(),
"mle");
867 return CalculateKeypoint(exec->GetRightEyebrowOuterEndId(),
"reoe");
880 return CalculateKeypoint(exec->GetRightEyebrowInnerEndId(),
"reie");
893 return CalculateKeypoint(exec->GetLeftEyebrowInnerEndId(),
"leie");
906 return CalculateKeypoint(exec->GetLeftEyebrowOuterEndId(),
"leoe");
919 return CalculateKeypoint(exec->GetRightEdgeId(),
"re");
930 return CalculateKeypoint(exec->GetChinTipId(),
"cht");
943 return CalculateKeypoint(exec->GetLeftEdgeId(),
"le");
950 [[nodiscard]] std::shared_ptr<Image>
GetImage()
const
952 return capture->image;
961 const std::scoped_lock lock(keyPointsMux);
962 for (
const auto& [
id, serializableKeypoint] : keypoints)
964 writer.Write(serializableKeypoint.serializationKey, serializableKeypoint.keypoint);
979 Keypoints(std::shared_ptr<FaceCapture> faceCapture,
980 std::shared_ptr<void> face,
981 std::shared_ptr<FaceExecutor> executor)
982 :
capture(std::move(faceCapture))
983 , faceItem(std::move(face))
984 , exec(std::move(executor))
990 if (faceItem ==
nullptr)
996 throw NullArgumentException(
"executor can not be null");
1000 Keypoint CalculateKeypoint(
unsigned int id,
const char* serializationKey)
1002 const std::scoped_lock keyPointsLock(keyPointsMux);
1004 const bool alreadyCalculated = keypoints.contains(
id);
1005 if (!alreadyCalculated)
1010 exec->GetKeypoint(
GlobalLogger::Get(), faceItem.get(),
id, &score, &x, &y, ThrowOnError{});
1014 SerializableKeypoint{ serializationKey,
1015 Keypoint(Point{
static_cast<X>(x),
static_cast<Y>(y) }, score) });
1017 return keypoints[id].keypoint;
1020 std::shared_ptr<FaceCapture> capture;
1021 std::shared_ptr<void> faceItem;
1022 std::shared_ptr<FaceExecutor> exec;
1023 struct SerializableKeypoint
1025 const char* serializationKey =
nullptr;
1029 std::unordered_map<unsigned int, SerializableKeypoint> keypoints;
1030 mutable std::mutex keyPointsMux;
1040 [[nodiscard]] std::shared_ptr<Keypoints>
GetKeypoints()
const
1047 const std::shared_ptr<FaceCapture>
capture;
1066 return std::shared_ptr<CroppedFace>(
new CroppedFace(faceItem,
capture, std::move(cfg), exec));
1092 auto isoEncoder = IsoImageEncoder(*
this, encoder);
1093 return isoEncoder.Encode();
1105 log.LogInfo(
"Face extraction for %v with cfg %v ...",
capture, cfg);
1107 std::vector<uint8_t> templData;
1111 +[](
void* container,
size_t size) -> uint8_t*
1113 auto* data = static_cast<std::vector<uint8_t>*>(container);
1115 return data->data();
1121 auto face = shared_from_this();
1122 auto extractedFace = ExtractedFace::Create(face, std::move(templData), exec);
1124 log.LogInfo(
"Face extraction result %v", extractedFace);
1126 return extractedFace;
1134 std::shared_ptr<ExtractedFace>
Extract()
1147 writer.Write(
"k", keypoints);
1149 for (
auto const& attribute : attributes)
1151 const std::scoped_lock lock(attribute.mux);
1152 if (attribute.value.has_value())
1154 writer.Write(attribute.serializationKey, attribute.value.value());
1158 const std::scoped_lock lock(fastPassiveLivenessMux);
1159 if (fastPassiveLiveness.has_value())
1161 writer.Write(
"ulf", fastPassiveLiveness.value());
1165 const std::scoped_lock lock(accuratePassiveLivenessMux);
1166 if (accuratePassiveLiveness.has_value())
1168 writer.Write(
"ula", accuratePassiveLiveness.value());
1180 bool IsSameAs(
const Face& face)
const
1182 return this == &face;
1211 return !(*
this == f);
1230 return CalculateAttribute(exec->GetSharpnessId(),
"sr");
1250 return CalculateAttribute(exec->GetBrightnessId(),
"br");
1270 return CalculateAttribute(exec->GetContrastId(),
"ct");
1290 return CalculateAttribute(exec->GetUniqueIntensityLevelsId(),
"uil");
1310 return CalculateAttribute(exec->GetShadowId(),
"sh");
1328 return CalculateAttribute(exec->GetNoseShadowId(),
"ns");
1348 return CalculateAttribute(exec->GetSpecularityId(),
"sp");
1367 return CalculateAttribute(exec->GetEyeGazeId(),
"eg");
1384 return CalculateAttribute(exec->GetEyeStatusRId(),
"esr");
1401 return CalculateAttribute(exec->GetEyeStatusLId(),
"esl");
1416 return CalculateAttribute(exec->GetGlassStatusId(),
"gs");
1434 return CalculateAttribute(exec->GetHeavyFrameId(),
"hf");
1452 return CalculateAttribute(exec->GetMouthStatusId(),
"ms");
1475 static constexpr uint8_t MaxBackgroundRatio = 100;
1476 if (minimalBackgroundRatio > MaxBackgroundRatio)
1479 "The minimal background ratio for face background uniformity MUST be in range <0,100>");
1481 AttributeConfiguration config;
1482 config.emplace_back(inno_FaceParams::BackgroundUniformityMinRatioName,
1483 std::to_string(minimalBackgroundRatio));
1484 return CalculateAttribute(exec->GetBackgroundUniformityId(),
"bu", std::move(config));
1506 static constexpr uint8_t DefaultMinimalBackgroundRatio = 5;
1557 AttributeConfiguration config;
1558 config.emplace_back(inno_FaceParams::AgeGenderMode, ToString(mode));
1559 return CalculateAttribute(exec->GetAgeId(),
"age", std::move(config));
1576 return CalculateAttribute(exec->GetRedEyeRId(),
"rer");
1593 return CalculateAttribute(exec->GetRedEyeLId(),
"rel");
1649 AttributeConfiguration config;
1650 config.emplace_back(inno_FaceParams::AgeGenderMode, ToString(mode));
1651 return CalculateAttribute(exec->GetGenderId(),
"gen", std::move(config));
1667 return CalculateAttribute(exec->GetEyeDistanceId(),
"ed");
1683 return CalculateAttribute(exec->GetRollAngleId(),
"ra");
1696 return CalculateAttribute(exec->GetPitchAngleId(),
"pa");
1709 return CalculateAttribute(exec->GetYawAngleId(),
"ya");
1720 return CalculateAttribute(exec->GetFaceSizeId(),
"fs");
1734 return CalculateAttribute(exec->GetFaceRelativeAreaId(),
"fra");
1748 return CalculateAttribute(exec->GetFaceRelativeAreaInImageId(),
"fri");
1763 return CalculateAttribute(exec->GetTintedGlassesId(),
"tg");
1777 return CalculateWidthHeightRatio();
1845 return CalculateFastPassiveLiveness();
1848 return CalculateAccuratePassiveLiveness();
1868 UNIQUE_INTENSITY_LEVELS,
1898 BACKGROUND_UNIFORMITY,
1931 FACE_RELATIVE_AREA_IN_IMAGE,
1942 Face& operator=(
const Face&) =
delete;
1944 virtual ~Face() =
default;
1948 using AttributeConfiguration = std::vector<std::tuple<const char*, std::string>>;
1952 const char* serializationKey =
nullptr;
1953 std::optional<float> value;
1954 AttributeConfiguration config;
1955 mutable std::mutex mux;
1957 Attribute() =
default;
1958 ~Attribute() =
default;
1959 Attribute(
const Attribute&) =
delete;
1960 Attribute(Attribute&&) =
delete;
1961 Attribute& operator=(
const Attribute&) =
delete;
1962 Attribute& operator=(Attribute&&) =
delete;
1965 std::vector<Attribute> attributes;
1966 std::optional<float> fastPassiveLiveness;
1967 mutable std::mutex fastPassiveLivenessMux;
1968 std::optional<float> accuratePassiveLiveness;
1969 mutable std::mutex accuratePassiveLivenessMux;
1970 FormattingLogger log;
1981 static std::shared_ptr<Face> Create(std::shared_ptr<FaceCapture> capture,
1982 std::shared_ptr<void> faceItem,
1984 unsigned int confidence,
1987 return std::shared_ptr<Face>(
1988 new Face(std::move(capture), std::move(bb), confidence, std::move(faceItem), std::move(exec)));
1991 Face(std::shared_ptr<FaceCapture> capt,
1994 std::shared_ptr<void> fi,
1995 std::shared_ptr<FaceExecutor> e)
1996 : capture(std::move(capt))
1998 , attributes(e->GetMaxId())
1999 , log(GlobalLogger::Get())
2000 , faceItem(std::move(fi))
2001 , boundingBox(std::move(bb))
2002 , exec(std::move(e))
2003 , keypoints(new Keypoints(capture, faceItem, exec))
2005 if (exec ==
nullptr)
2007 throw NullArgumentException(
"Could not create Face due to executor can not be null");
2010 if (capture ==
nullptr)
2012 throw NullArgumentException(
"Could not create Face due to the face original capture can not be null");
2016 float CalculateAttribute(
unsigned int id,
const char* serializationKey)
2018 AttributeConfiguration config;
2019 return CalculateAttribute(
id, serializationKey, std::move(config));
2021 float CalculateAttribute(
unsigned int id,
const char* serializationKey, AttributeConfiguration&& config)
2023 const std::scoped_lock attributesLock(attributes[
id].mux);
2024 auto& attribute = attributes[id];
2026 if (attribute.value.has_value() && config == attribute.config)
2028 return attribute.value.value();
2031 std::vector<inno_FaceParams> params(config.size());
2032 std::transform(config.begin(),
2035 [](
const auto& c) { return inno_FaceParams{ std::get<0>(c), std::get<1>(c).c_str() }; });
2038 exec->GetAttribute(
GlobalLogger::Get(), faceItem.get(),
id, params.data(), params.size(), ThrowOnError{});
2040 attribute.value = value;
2041 attribute.serializationKey = serializationKey;
2042 attribute.config = std::move(config);
2047 float CalculateAccuratePassiveLiveness()
2049 const std::scoped_lock attributesLock(accuratePassiveLivenessMux);
2051 if (accuratePassiveLiveness.has_value())
2053 return accuratePassiveLiveness.value();
2056 float value = exec->GetPassiveLivenessAccurate(
GlobalLogger::Get(), faceItem.get(), ThrowOnError{});
2058 accuratePassiveLiveness = value;
2063 float CalculateFastPassiveLiveness()
2065 const std::scoped_lock attributesLock(fastPassiveLivenessMux);
2067 if (fastPassiveLiveness.has_value())
2069 return fastPassiveLiveness.value();
2072 float value = exec->GetPassiveLivenessFast(
GlobalLogger::Get(), faceItem.get(), ThrowOnError{});
2074 fastPassiveLiveness = value;
2079 float CalculateWidthHeightRatio()
const
2081 auto width = capture->image->Width();
2082 auto height = capture->image->Height();
2083 if (width == 0 || height == 0)
2087 const float ratio =
static_cast<float>(width) /
static_cast<float>(height);
2091 static std::string ToString(AgeEstimationMode mode)
2095 case AgeEstimationMode::BALANCED:
2097 case AgeEstimationMode::ACCURATE:
2101 throw EnrollmentInvalidArgumentException(
"Incorrect AgeEstimationMode '" +
2102 std::to_string(
static_cast<uint8_t
>(mode)) +
"'");
2105 static std::string ToString(GenderEstimationMode mode)
2109 case GenderEstimationMode::BALANCED:
2111 case GenderEstimationMode::ACCURATE:
2115 throw EnrollmentInvalidArgumentException(
"Incorrect GenderEstimationMode '" +
2116 std::to_string(
static_cast<uint8_t
>(mode)) +
"'");
2122 explicit IsoImage(
const Face& f)
2126 IsoImage() =
delete;
2127 ~IsoImage() =
default;
2128 IsoImage(
const IsoImage&) =
delete;
2129 IsoImage(IsoImage&&) =
delete;
2130 IsoImage& operator=(
const IsoImage&) =
delete;
2131 IsoImage& operator=(IsoImage&&) =
delete;
2133 void SetCompressionType(uint8_t ct)
2135 compressionType = ct;
2138 std::vector<uint8_t> FillIsoImage(
const std::vector<uint8_t>& encodedImage)
2141 static constexpr size_t GeneralHeaderLength = 17;
2144 static constexpr size_t NumberOfQualityBlocks = 0;
2147 static constexpr size_t SizeOfQualityBlock = 5;
2150 static constexpr size_t NumberOfLandmarkPoints = 0;
2153 static constexpr size_t SizeOfLandmarkPoints = 8;
2156 static constexpr size_t RepresentationHeaderLength =
2157 47 + NumberOfQualityBlocks * SizeOfQualityBlock + NumberOfLandmarkPoints * SizeOfLandmarkPoints;
2160 static constexpr size_t ImageDataBlockLength = 4;
2163 auto imageLength = encodedImage.size();
2166 auto representationLength = RepresentationHeaderLength + imageLength + ImageDataBlockLength;
2169 auto recordLength = GeneralHeaderLength + representationLength;
2171 std::vector<uint8_t> isoImage;
2172 isoImage.resize(recordLength);
2174 FillGeneralHeader(isoImage, recordLength);
2175 FillRepresentationHeader(isoImage, representationLength);
2176 FillRepresentationBody(isoImage, encodedImage, imageLength);
2182 static void ThrowWhenValueCannotFitInto4Bytes(
size_t recordLength)
2184 if (recordLength >
static_cast<size_t>(std::numeric_limits<uint32_t>::max()))
2186 throw EnrollmentRuntimeException(
"Invalid conversion size");
2198 void FillGeneralHeader(std::vector<uint8_t>& isoImage,
const size_t recordLength)
2200 FillFormatIdentifier(isoImage);
2201 FillVersionNumber(isoImage);
2202 FillLengthOfRecord(isoImage, recordLength);
2203 FillNumberOfRepresentations(isoImage);
2204 FillCertificationFlag(isoImage);
2205 FilTemporalSemantics(isoImage);
2214 void FillFormatIdentifier(std::vector<uint8_t>& isoImage)
2217 isoImage[writeIndex++] =
'F';
2218 isoImage[writeIndex++] =
'A';
2219 isoImage[writeIndex++] =
'C';
2220 isoImage[writeIndex++] =
'\0';
2232 void FillVersionNumber(std::vector<uint8_t>& isoImage)
2235 isoImage[writeIndex++] =
'0';
2236 isoImage[writeIndex++] =
'3';
2237 isoImage[writeIndex++] =
'0';
2238 isoImage[writeIndex++] =
'\0';
2250 void FillLengthOfRecord(std::vector<uint8_t>& isoImage,
const size_t recordLength)
2252 ThrowWhenValueCannotFitInto4Bytes(recordLength);
2255 isoImage[writeIndex++] =
static_cast<uint8_t
>(recordLength >> ThreeBytesBitsCount);
2256 isoImage[writeIndex++] =
static_cast<uint8_t
>((recordLength >> TwoBytesBitsCount) & ByteMask);
2257 isoImage[writeIndex++] =
static_cast<uint8_t
>((recordLength >> OneByteBitsCount) & ByteMask);
2258 isoImage[writeIndex++] =
static_cast<uint8_t
>(recordLength & ByteMask);
2267 void FillNumberOfRepresentations(std::vector<uint8_t>& isoImage)
2270 isoImage[writeIndex++] = 0x00;
2271 isoImage[writeIndex++] = 0x01;
2279 void FillCertificationFlag(std::vector<uint8_t>& isoImage)
2281 isoImage[writeIndex++] = 0x00;
2291 void FilTemporalSemantics(std::vector<uint8_t>& isoImage)
2294 isoImage[writeIndex++] = 0x00;
2295 isoImage[writeIndex++] = 0x00;
2311 void FillRepresentationHeader(std::vector<uint8_t>& isoImage,
size_t representationLength)
2313 FillRepresentationLength(isoImage, representationLength);
2314 FillCaptureDateTime(isoImage);
2315 FillCaptureDeviceTechnologyIdentifier(isoImage);
2316 FillCaptureDeviceVendorIdentifier(isoImage);
2317 FillCaptureDeviceTypeIdentifier(isoImage);
2318 FillNumberOfQualityBlocks(isoImage);
2319 FillFacialInformation(isoImage);
2320 FillImageInformation(isoImage);
2334 void FillRepresentationLength(std::vector<uint8_t>& isoImage,
size_t representationLength)
2336 ThrowWhenValueCannotFitInto4Bytes(representationLength);
2339 isoImage[writeIndex++] =
static_cast<uint8_t
>(representationLength >> ThreeBytesBitsCount);
2340 isoImage[writeIndex++] =
static_cast<uint8_t
>((representationLength >> TwoBytesBitsCount) & ByteMask);
2341 isoImage[writeIndex++] =
static_cast<uint8_t
>((representationLength >> OneByteBitsCount) & ByteMask);
2342 isoImage[writeIndex++] =
static_cast<uint8_t
>(representationLength & ByteMask);
2352 void FillCaptureDateTime(std::vector<uint8_t>& isoImage)
2355 static constexpr uint8_t DummyValue = 0xff;
2356 isoImage[writeIndex++] = DummyValue;
2357 isoImage[writeIndex++] = DummyValue;
2358 isoImage[writeIndex++] = DummyValue;
2359 isoImage[writeIndex++] = DummyValue;
2360 isoImage[writeIndex++] = DummyValue;
2361 isoImage[writeIndex++] = DummyValue;
2362 isoImage[writeIndex++] = DummyValue;
2363 isoImage[writeIndex++] = DummyValue;
2364 isoImage[writeIndex++] = DummyValue;
2375 void FillCaptureDeviceTechnologyIdentifier(std::vector<uint8_t>& isoImage)
2378 face.capture->faceAttributes.GetCaptureDeviceTechnology();
2379 isoImage[writeIndex++] =
2392 void FillCaptureDeviceVendorIdentifier(std::vector<uint8_t>& isoImage)
2395 const FaceCaptureDeviceVendorID& vendor = face.capture->faceAttributes.GetCaptureDeviceVendorID();
2396 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(vendor) >> OneByteBitsCount);
2397 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(vendor) & ByteMask);
2409 void FillCaptureDeviceTypeIdentifier(std::vector<uint8_t>& isoImage)
2412 const FaceCaptureDeviceTypeID type = face.capture->faceAttributes.GetCaptureDeviceTypeID();
2413 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(type) >> OneByteBitsCount);
2414 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(type) & ByteMask);
2423 void FillNumberOfQualityBlocks(std::vector<uint8_t>& isoImage)
2425 isoImage[writeIndex++] = 0x00;
2432 void FillQualityBlockData(std::vector<uint8_t>& isoImage)
2435 FillQualityScore(isoImage);
2436 FillQualityAlgorithmVendorId(isoImage);
2437 FillQualityAlgorithmId(isoImage);
2449 void FillQualityScore(std::vector<uint8_t>& isoImage)
2451 isoImage[writeIndex++] = 0x00;
2461 void FillQualityAlgorithmVendorId(std::vector<uint8_t>& isoImage)
2464 isoImage[writeIndex++] = 0x00;
2465 isoImage[writeIndex++] = 0x00;
2475 void FillQualityAlgorithmId(std::vector<uint8_t>& isoImage)
2478 isoImage[writeIndex++] = 0x00;
2479 isoImage[writeIndex++] = 0x00;
2489 void FillFacialInformation(std::vector<uint8_t>& isoImage)
2491 FillNumberOfLandmarkPoints(isoImage);
2492 FillGender(isoImage);
2493 FillEyeColour(isoImage);
2494 FillHairColour(isoImage);
2495 FillSubjectHeight(isoImage);
2496 FillPropertyMask(isoImage);
2497 FillExpressionMask(isoImage);
2498 FillPoseAngle(isoImage);
2499 FillPoseAngleUncertainty(isoImage);
2508 void FillNumberOfLandmarkPoints(std::vector<uint8_t>& isoImage)
2511 isoImage[writeIndex++] = 0x00;
2512 isoImage[writeIndex++] = 0x00;
2520 void FillGender(std::vector<uint8_t>& isoImage)
2522 isoImage[writeIndex++] = 0x00;
2531 void FillEyeColour(std::vector<uint8_t>& isoImage)
2533 isoImage[writeIndex++] = 0x00;
2541 void FillHairColour(std::vector<uint8_t>& isoImage)
2543 isoImage[writeIndex++] = 0x00;
2551 void FillSubjectHeight(std::vector<uint8_t>& isoImage)
2553 isoImage[writeIndex++] = 0x00;
2562 void FillPropertyMask(std::vector<uint8_t>& isoImage)
2565 isoImage[writeIndex++] = 0x00;
2566 isoImage[writeIndex++] = 0x00;
2567 isoImage[writeIndex++] = 0x00;
2576 void FillExpressionMask(std::vector<uint8_t>& isoImage)
2579 isoImage[writeIndex++] = 0x00;
2580 isoImage[writeIndex++] = 0x00;
2592 void FillPoseAngle(std::vector<uint8_t>& isoImage)
2595 isoImage[writeIndex++] = 0x00;
2596 isoImage[writeIndex++] = 0x00;
2597 isoImage[writeIndex++] = 0x00;
2608 void FillPoseAngleUncertainty(std::vector<uint8_t>& isoImage)
2611 isoImage[writeIndex++] = 0x00;
2612 isoImage[writeIndex++] = 0x00;
2613 isoImage[writeIndex++] = 0x00;
2623 void Fill2D3DLandmarkPoints(std::vector<uint8_t>& isoImage)
2625 FillLandmarkPointType(isoImage);
2626 FillLandmarkPointCode(isoImage);
2627 FillLandmarkXCoordinate(isoImage);
2628 FillLandmarkYCoordinate(isoImage);
2629 FillLandmarkZCoordinate(isoImage);
2638 void FillLandmarkPointType(std::vector<uint8_t>& isoImage)
2640 isoImage[writeIndex++] = 0x00;
2649 void FillLandmarkPointCode(std::vector<uint8_t>& isoImage)
2651 isoImage[writeIndex++] = 0x00;
2658 void FillLandmarkXCoordinate(std::vector<uint8_t>& isoImage)
2660 isoImage[writeIndex++] = 0x00;
2661 isoImage[writeIndex++] = 0x00;
2668 void FillLandmarkYCoordinate(std::vector<uint8_t>& isoImage)
2670 isoImage[writeIndex++] = 0x00;
2671 isoImage[writeIndex++] = 0x00;
2678 void FillLandmarkZCoordinate(std::vector<uint8_t>& isoImage)
2680 isoImage[writeIndex++] = 0x00;
2681 isoImage[writeIndex++] = 0x00;
2691 void FillImageInformation(std::vector<uint8_t>& isoImage)
2694 ImageDataType(isoImage);
2697 SpatialSamplingRateLevel(isoImage);
2698 PostAcquisitionProcessing(isoImage);
2699 CrossReference(isoImage);
2700 ImageColourSpace(isoImage);
2711 isoImage[writeIndex++] =
static_cast<uint8_t
>(
2722 void ImageDataType(std::vector<uint8_t>& isoImage)
2724 isoImage[writeIndex++] = compressionType;
2733 void ImageWidth(std::vector<uint8_t>& isoImage)
2736 isoImage[writeIndex++] =
static_cast<uint8_t
>(face.capture->image->Width() >> OneByteBitsCount);
2737 isoImage[writeIndex++] =
static_cast<uint8_t
>(face.capture->image->Width() & ByteMask);
2749 isoImage[writeIndex++] =
static_cast<uint8_t
>(face.capture->image->Height() >> OneByteBitsCount);
2750 isoImage[writeIndex++] =
static_cast<uint8_t
>(face.capture->image->Height() & ByteMask);
2762 void SpatialSamplingRateLevel(std::vector<uint8_t>& isoImage)
2764 isoImage[writeIndex++] = 0x00;
2776 void PostAcquisitionProcessing(std::vector<uint8_t>& isoImage)
2779 isoImage[writeIndex++] = 0x00;
2780 isoImage[writeIndex++] = 0x00;
2792 void CrossReference(std::vector<uint8_t>& isoImage)
2794 isoImage[writeIndex++] = 0x00;
2804 void ImageColourSpace(std::vector<uint8_t>& isoImage)
2806 isoImage[writeIndex++] = 0x00;
2816 void FillRepresentationBody(std::vector<uint8_t>& isoImage,
2817 const std::vector<uint8_t>& encodedImage,
2820 FillImageDataLength(isoImage, imageLength);
2821 FillImageData(isoImage, encodedImage);
2830 void FillImageDataLength(std::vector<uint8_t>& isoImage,
size_t imageLength)
2832 ThrowWhenValueCannotFitInto4Bytes(imageLength);
2834 isoImage[writeIndex++] =
static_cast<uint8_t
>(imageLength >> ThreeBytesBitsCount);
2835 isoImage[writeIndex++] =
static_cast<uint8_t
>((imageLength >> TwoBytesBitsCount) & ByteMask);
2836 isoImage[writeIndex++] =
static_cast<uint8_t
>((imageLength >> OneByteBitsCount) & ByteMask);
2837 isoImage[writeIndex++] =
static_cast<uint8_t
>(imageLength & ByteMask);
2847 void FillImageData(std::vector<uint8_t>& isoImage,
const std::vector<uint8_t>& encodedImage)
2849 std::copy(encodedImage.begin(),
2851 std::next(isoImage.begin(),
static_cast<ptrdiff_t
>(writeIndex)));
2852 writeIndex += encodedImage.size();
2855 size_t writeIndex = 0U;
2857 static constexpr uint8_t NoCompressionType = 255;
2858 uint8_t compressionType = NoCompressionType;
2859 static constexpr unsigned int OneByteBitsCount = 8U;
2860 static constexpr unsigned int TwoBytesBitsCount = 16U;
2861 static constexpr unsigned int ThreeBytesBitsCount = 24U;
2862 static constexpr unsigned int ByteMask = 0xffU;
2865 class IsoImageEncoder :
public ImageEncoderVisitor
2875 std::vector<uint8_t> Encode()
2878 encoder.Accept(*
this);
2881 auto encodedImage = face.capture->image->EncodeIn(encoder);
2883 return isoImage.FillIsoImage(encodedImage);
2886 void Visit(
const WsqImageEncoder& )
final
2888 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for WSQ image format");
2891 void Visit(
const JpgImageEncoder& )
final
2893 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for JPG image format");
2896 void Visit(
const Jp2ImageEncoder& jp2Encoder)
final
2898 if (jp2Encoder.IsLossy())
2901 isoImage.SetCompressionType(1);
2906 isoImage.SetCompressionType(2);
2910 void Visit(
const PngImageEncoder& )
final
2913 isoImage.SetCompressionType(3);
2916 void Visit(
const IRawImageEncoder& )
final
2918 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for IRAW image format");
2921 void Visit(
const BmpImageEncoder& )
final
2923 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for BMP image format");
2926 void Visit(
const TiffImageEncoder& )
final
2928 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for TIFF image format");
2931 void Visit(
const WebpImageEncoder& )
final
2933 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for WEBP image format");
2938 IsoImageEncoder(
const Face& f, ImageEncoder& e)
2941 , isoImage(IsoImage(f))
2944 IsoImageEncoder() =
delete;
2945 virtual ~IsoImageEncoder() =
default;
2946 IsoImageEncoder(
const IsoImageEncoder&) =
delete;
2947 IsoImageEncoder(IsoImageEncoder&&) =
delete;
2948 IsoImageEncoder& operator=(
const IsoImageEncoder&) =
delete;
2949 IsoImageEncoder& operator=(IsoImageEncoder&&) =
delete;
2953 ImageEncoder& encoder;
2957 std::shared_ptr<void> faceItem;
2958 Rectangle boundingBox;
2959 std::shared_ptr<FaceExecutor> exec;
2960 std::shared_ptr<Keypoints> keypoints;
2962 friend class FaceDetector;