|
|
- /**
- * @file IDescriptor.h
- * @brief Descriptor extractor and matcher interfaces.
- * @copyright VisionLabs LLC
- * @date 25.06.2014
- * */
-
- #pragma once
-
- #include "IObject.h"
- #include "IDetector.h"
- #include "FSDKError.h"
- #include "Types.h"
- #include <limits>
-
- namespace fsdk {
-
- #ifndef DOXYGEN_SHOULD_SKIP_THIS
- DECLARE_SMARTPTR(IDescriptor);
- DECLARE_SMARTPTR(IDescriptorBatch);
- DECLARE_SMARTPTR(IDescriptorMatcher);
- DECLARE_SMARTPTR(IDescriptorExtractor);
- #endif
-
- /**
- * @defgroup DescriptorProcessingGroup Descriptor extractor
- * @brief Descriptor extractor public interfaces and related types and structures.
- * @{
- * */
-
- /**
- * @brief Result of descriptor matching.
- * */
- struct MatchingResult {
- float distance; //!< distance between descriptor vectors.
- float similarity; //!< similarity (normalized in [0..1] range).
-
- /**
- * @brief Initializes result to default values.
- * */
- MatchingResult(void) noexcept
- : distance(std::numeric_limits<float>::infinity())
- , similarity(0.f)
- {}
-
- /**
- * @brief Initializes result.
- * @param [in] distance distance value.
- * @param [in] similarity similarity value.
- * */
- MatchingResult(
- float distance,
- float similarity) noexcept
- : distance(distance)
- , similarity(similarity)
- {}
- };
-
- /**
- * @brief Descriptor type enum.
- * Determines which type of descriptor to use.
- * */
- enum DescriptorType {
- DT_FACE, //!< face descriptor.
- DT_HUMAN //!< human descriptor.
- };
-
- /**
- * @brief Minimum descriptor model version.
- * Determines which minimum version of descriptor to use.
- * */
- enum DescriptorVersion : uint32_t {
- DV_MIN_FACE_DESCRIPTOR_VERSION = 46, //!< face descriptor.
- DV_MIN_HUMAN_DESCRIPTOR_VERSION = 102 //!< human descriptor.
- };
-
- /**
- * @brief Human descriptor model versions.
- * Determines which version of human descriptor to use.
- * */
- enum HumanDescriptorVersion : uint32_t {
- HDV_TRACKER_HUMAN_DESCRIPTOR_VERSION = 102, //!< human descriptor for tracking of people, light and fast version.
- HDV_PRECISE_HUMAN_DESCRIPTOR_VERSION = 103, //!< precise human descriptor, heavy and slow.
- HDV_REGULAR_HUMAN_DESCRIPTOR_VERSION = 104, //!< regular human descriptor.
- };
-
- /**
- * @brief Descriptor interface.
- * @details Used for matching.
- * */
- struct IDescriptor : IDataStorageObject {
- /**
- * @brief Get algorithm model version this descriptor was created with.
- * @return Version as integral number.
- * */
- virtual uint32_t getModelVersion() const noexcept = 0;
-
- /**
- * @brief Get type of descriptor.
- * @return type as enum.
- * @see DescriptorType for details.
- * */
- virtual DescriptorType getDescriptorType() const noexcept = 0;
-
- /**
- * @brief return size of descriptor in bytes.
- * @return size of descriptor in bytes.
- * @note This method is thread safe.
- * */
- virtual uint32_t getDescriptorLength() const noexcept = 0;
-
- /**
- * @brief Copy descriptor data to user provided buffer.
- * @param [out] buffer user provided buffer.
- * @return true if OK, and false if ERROR.
- * @note This method is thread safe.
- * @note buffer must be preallocated by client code.
- * */
- virtual bool getDescriptor(uint8_t* buffer) const noexcept = 0;
-
- /**
- * @brief Copy descriptor from user providedbuffer.
- * @param [in] buffer user provided buffer.
- */
- virtual void setDescriptor(const uint8_t* buffer) noexcept = 0;
- };
-
- /**
- * @brief Descriptor batch interface.
- * @details Used for matching large continous sets of descriptors.
- *
- * A batch is created with a reserved memory for descriptors that can not be later extended. Thus descriptors can be
- * add()'ed until the memory reservation is exceeded.
- *
- * Memory reservation size can be obtained via getMaxCount() function. The batch me be reset via clear() function.
- * It does not deallocate memory reservation. Instead, it resets internal counter allowing to re-populate the batch
- * via add() again.
- * */
- struct IDescriptorBatch : IDataStorageObject {
- /**
- * @brief Descriptor batch error enumeration.
- * @details Used for descriptor batch related errors indication.
- * */
- enum class Error : uint32_t {
- Ok, //!< No error.
- InvalidInput, //!< Invalid input (Ex: null pointer while a valid object is expected).
- BatchFull, //!< Batch is full.
- Incompatible, //!< Trying to add an incompatible descriptor.
- Internal, //!< An internal processing error (Ex: memopry allocation or misalignment).
- IoError, //!< Error while trying open/read/write file.
- OutOfRange, //!< Error while accessing descriptor out of range.
- };
-
- /**
- * @brief Add a descriptor to the batch.
- * @param [in] descriptor descriptor to add. Descriptor data is copied and to internal reference is held, thus
- * it is safe to release the source descriptor object later.
- * @return Result with one of the error codes specified by DescriptorBatchError.
- * @see IDescriptor, Result and Error for details.
- * */
- virtual Result<Error> add(IDescriptor* descriptor) noexcept = 0;
-
- /**
- * @brief Add a given descriptor batch content to the current batch. Descriptors to copy
- * from the source batch are selected based on offset parameter.
- * @param [in] batch batch to take content from. All descriptors from the input batch
- * are copied to the buffer of the current batch. So it is safe
- * to release the source descriptor batch object later.
- * @param [in] offset offset of descriptors to copy.
- * @return Result with one of the error codes specified by DescriptorBatchError.
- * @see IDescriptorBatch, Result and Error for details.
- * @note Current batch should have enough free space to place all descriptors
- * from the input batch.
- * @note All selected descriptors from the source batch will be placed right after all
- * descriptors in the current batch.
- * @note All selected descriptors from the input batch are copied to the buffer
- * of the current batch. So it is safe to release the source descriptor batch object later.
- * */
- virtual Result<Error> add(IDescriptorBatch* batch, uint32_t offset = 0) noexcept = 0;
-
- /**
- * @brief Add a descriptor batch content to the batch. Descriptors to copy
- * from the source bath are selected based on count and offset parameters.
- * @param [in] batch batch to take content from.
- * @param [in] offset offset of descriptors to copy.
- * @param [in] count count of descriptors to copy.
- * @return Result with one of the error codes specified by DescriptorBatchError.
- * @see IDescriptorBatch, Result and Error for details.
- * @note Current batch should have enough free space to place all descriptors
- * from the input batch.
- * @note All selected descriptors from the source batch will be placed right after all
- * descriptors in the current batch.
- * @note All selected descriptors from the input batch are copied to the buffer
- * of the current batch. So it is safe to release the source descriptor batch object later.
- * */
- virtual Result<Error> add(IDescriptorBatch* batch, uint32_t offset, uint32_t count) noexcept = 0;
-
- /**
- * @brief Remove a descriptor from batch.
- * @details Remove descriptor by swapping it with the last descriptor in batch. This breaks descriptor order.
- * @param [in] index descriptor index.
- * @return Result with one of the error codes specified by DescriptorBatchError.
- * @see Result and Error for details.
- * */
- virtual Result<Error> removeFast(uint32_t index) noexcept = 0;
-
- /**
- * @brief Remove a descriptor from batch.
- * @details Remove descriptor by shifting all the following descriptors back. This preserves descriptor order.
- * @param [in] index descriptor index.
- * @return Result with one of the error codes specified by DescriptorBatchError.
- * @see Result and Error for details.
- * */
- virtual Result<Error> removeSlow(uint32_t index) noexcept = 0;
-
- /**
- * @brief Load a descriptor/descriptors from archive and add it to the batch.
- * @note This method supports both serialized IDescriptorBatch and IDescriptor.
- * @param [in] archive archive to read from.
- * @return MultiError result with codes specified by DescriptorBatchError and SerializationError.
- * @note This method pass exceptions from user defined IArchive, but doesnt throw its own
- * @see Result, IArchive, ISerializableObject::Error, Error and MultiError for details.
- * */
- virtual Result<MultiError<ISerializableObject::Error,Error>> loadAndAdd(IArchive* archive) = 0;
-
- /**
- * @brief Get maximum number of descriptors in this batch.
- * @return maximum number of descriptors in this batch.
- * */
- virtual uint32_t getMaxCount() const noexcept = 0;
-
- /**
- * @brief Get actual number of descriptors in this batch.
- * @return actual number of descriptors in this batch.
- * */
- virtual uint32_t getCount() const noexcept = 0;
-
- /**
- * @brief Get algorithm model version the descriptors in this batch were created with.
- * @note This function only makes sense when there is at least one descriptor in the batch. It will return 0 if
- * the batch is empty.
- * @return Version as integral number.
- * */
- virtual uint32_t getModelVersion() const noexcept = 0;
-
- /**
- * @brief Get type of descriptor.
- * @note This function only makes sense when there is at least one descriptor in the batch.
- * @return type as enum.
- * @see DescriptorType for details.
- * */
- virtual DescriptorType getDescriptorType() const noexcept = 0;
-
- /**
- * @brief Get length of one descriptor. Specified by version of descriptors in batch.
- * @return Length of one descriptor in batch.
- * */
- virtual uint32_t getDescriptorLength() const noexcept = 0;
-
- /**
- * @brief Get descriptor from batch by index with copying.
- * @param [in] index descriptor index in batch.
- * @return ResultValue with error code and IDescriptorPtr instance.
- * @see IDescriptorPtr, ResultValue and FSDKError for details.
- * */
- virtual ResultValue<FSDKError, IDescriptorPtr> getDescriptorSlow(uint32_t index) const noexcept = 0;
-
- /**
- * @brief Get descriptor from batch by index without copying.
- * @param [in] index descriptor index in batch.
- * @return ResultValue with error code and IDescriptorPtr instance.
- * @see IDescriptorPtr, ResultValue and FSDKError for details.
- * @note If you change achived descriptor - corresponded descriptor in batch will be changed.
- * */
- virtual ResultValue<FSDKError, IDescriptorPtr> getDescriptorFast(uint32_t index) noexcept = 0;
- };
-
- /**
- * @brief Specialized for DescriptorBatchError.
- * */
- template<>
- struct ErrorTraits<IDescriptorBatch::Error> {
- static bool isOk(IDescriptorBatch::Error error) noexcept {
- return error == IDescriptorBatch::Error::Ok;
- }
-
- static const char* toString (IDescriptorBatch::Error error) noexcept {
- switch(error) {
- case IDescriptorBatch::Error::Ok: return "Ok";
- case IDescriptorBatch::Error::IoError: return "Error during reading/writing";
- case IDescriptorBatch::Error::Internal: return "Internal error";
- case IDescriptorBatch::Error::BatchFull: return "Batch is full";
- case IDescriptorBatch::Error::OutOfRange: return "Descriptor out of range";
- case IDescriptorBatch::Error::Incompatible: return "Incompatible descriptor";
- case IDescriptorBatch::Error::InvalidInput: return "Invalid input";
- default: return "Unknown error";
- }
- }
- };
-
- /**
- * @brief Descriptor extractor interface.
- * @details Extracts face descriptors from images. The descriptors can be later used for face matching.
- * */
- struct IDescriptorExtractor : IRefCounted {
- /**
- * @brief Extract descriptor from a warped image.
- * @param [in] warp image with warped face or human warp.
- * @note Warp should be a valid 250x250 image in R8G8B8 format for DT_FACE descriptor type.
- * @note Warp should be a valid 128x256 image in R8G8B8 format for DT_HUMAN descriptor type.
- * @param [out] descriptor descriptor to fill with data.
- * @return ResultValue with error code and score of descriptor normalized in range [0, 1]
- * 1 - face on the input warp; 0 - garbage on the input warp.
- * @note human descriptor does not support garbage score, 1.0 will be returned.
- * @see Image, IDescriptor, ResultValue and FSDKError for details.
- * @note warp format must be R8G8B8, @see Format.
- * */
- virtual ResultValue<FSDKError, float>
- extractFromWarpedImage(
- const Image& warp,
- IDescriptor* descriptor) const noexcept = 0;
-
- /**
- * @brief Extract batch of descriptors from a batch of images and perform aggregation.
- * @param [in] warps span of images with warped faces or human warps.
- * @note Warps should be in R8G8B8 format, with size 250x250 for DT_FACE descriptor type.
- * @note Warps should be in R8G8B8 format, with size 128x256 for DT_HUMAN descriptor type.
- * @param [out] descriptorBatch descriptor batch to fill with data.
- * @note DT_HUMAN descriptor does not support garbage score.
- * @param [out] aggregation descriptor with aggregation based on descriptor batch.
- * @param [out] garbageScoreBatch span of descriptor scores normalized in range [0, 1]
- * 1 - face on the input warp; 0 - garbage on the input warp.
- * @note human descriptor does not support garbage score, 1.0 will be returned.
- * @return ResultValue with error code and aggregated garbage score.
- * @see Span, Image, IDescriptor, IDescriptorBatch, ResultValue and FSDKError for details.
- * @note warps format must be R8G8B8, @see Format.
- * @note all spans should be based on user owned continuous collections.
- * @note all spans should be equal size.
- * */
- virtual ResultValue<FSDKError, float>
- extractFromWarpedImageBatch(
- Span<const Image> warps,
- IDescriptorBatch* descriptorBatch,
- IDescriptor* aggregation,
- Span<float> garbageScoreBatch) const noexcept = 0;
-
- /**
- * @brief Extract batch of descriptors from a batch of images.
- * @param [in] warps span of images with warped faces or human warps.
- * @note Warps should be in R8G8B8 format, with size 250x250 for DT_FACE descriptor type.
- * @note Warps should be in R8G8B8 format, with size 128x256 for DT_HUMAN descriptor type.
- * @param [out] descriptorBatch descriptor batch to fill with data.
- * @param [out] garbageScoreBatch span of descriptor scores normalized in range [0, 1]
- * 1 - face on the input warp; 0 - garbage on the input warp. DT_HUMAN descriptor does not support garbage score.
- * In a case of DT_HUMAN descriptor, you'll get batch filled by 1.0.
- * @return Result with error code.
- * @see Span, Image, IDescriptorBatch, Result and FSDKError for details.
- * @note warps format must be R8G8B8, @see Format.
- * @note all spans should be based on user owned continuous collections.
- * @note all spans should be equal size.
- * */
- virtual Result<FSDKError>
- extractFromWarpedImageBatch(
- Span<const Image> warps,
- IDescriptorBatch* descriptorBatch,
- Span<float> garbageScoreBatch) const noexcept = 0;
-
- /**
- * @brief Validate input of multiple frames in a single function call.
- * @param [in] warps span of images with warped faces or human warps.
- * @param [out] errors output span of errors for each image.
- * @return Result with error code.
- * @see Span, Image, Result and FSDKError for details.
- * @note warps format must be R8G8B8, @see Format.
- * @note all spans should be based on user owned continuous collections.
- * @note all spans should be equal size.
- * */
- virtual Result<FSDKError>
- validate(
- Span<const Image> warps,
- Span<Result<FSDKError>> errors) const noexcept = 0;
-
- /**
- * @brief Get algorithm model version this extractor works with.
- * @return Version as integral number.
- * */
- virtual uint32_t getModelVersion() const noexcept = 0;
-
- /**
- * @brief Get type of descriptor this extractor works with.
- * @return type as enum @see DescriptorType.
- * */
- virtual DescriptorType getDescriptorType() const noexcept = 0;
-
- /**
- * @brief Common aliases for BestShotQuality asynchronous interface.
- * */
- using FutureResult = vlc::future<float>;
-
- /**
- * @brief Asynchronously extract batch of descriptors from a batch of images.
- * @param [in] warps span of images with warped faces or human warps.
- * @note Warps should be in R8G8B8 format, with size 250x250 for DT_FACE descriptor type.
- * @note Warps should be in R8G8B8 format, with size 128x256 for DT_HUMAN descriptor type.
- * @param [out] descriptorBatch descriptor batch to fill with data.
- * @param [out] aggregation descriptor with aggregation based on descriptor batch.
- * @param [out] garbageScoreBatch span of descriptor scores normalized in range [0, 1]
- * 1 - face on the input warp; 0 - garbage on the input warp. DT_HUMAN descriptor does not support garbage score.
- * In a case of DT_HUMAN descriptor, you'll get batch filled by 1.0.
- * @return Result with error code and aggregated garbage score.
- * @see Span, Image, IDescriptorBatch, Result and FSDKError for details.
- * @note warps format must be R8G8B8, @see Format.
- * @note all spans should be based on user owned continuous collections.
- * @note all spans should be equal size.
- * @note this method is experimental and interface may be changed in the future.
- * @note this method is not marked as noexcept and may throw an exception.
- * */
- virtual FutureResult extractFromWarpedImageBatchAsync(
- Span<const Image> warps,
- IDescriptorBatch* descriptorBatch,
- IDescriptor* aggregation,
- Span<float> garbageScoreBatch) const = 0;
- };
-
- /**
- * @brief Descriptor matcher interface.
- * @details Matches descriptors 1:1 and 1:M (@see IDescriptor and IDescriptorBatch interfaces).
- *
- * As a result of the matching process the calling site gets a MatchingResult (or several of them in case of 1:M
- * matching). The MatchingResult structure contains distance and similarity metrics.
- *
- * Distance is measured in abstract units and tends to 0 for similar descriptors and to infinity for different ones.
- * Similarity is the opposite metric and shows probability of two descriptors belonging to the same person; therfore
- * it is normalized to [0..1] range.
- *
- * @see MatchingResult for details.
- * */
- struct IDescriptorMatcher : IRefCounted {
- /**
- * @brief Match descriptors 1:1.
- * @param [in] first first descriptor.
- * @param [in] second second descriptor.
- * @return ResultValue with error code and matching result.
- * @see MatchingResult, IDescriptor, ResultValue and FSDKError for details.
- * */
- virtual ResultValue<
- FSDKError,
- MatchingResult>
- match(
- const IDescriptor* first,
- const IDescriptor* second) noexcept = 0;
-
- /**
- * @brief Match descriptors 1:M.
- * @details Matches a reference descriptor to a batch of candidate descriptors. The results are layed out in the
- * same order as the candidate descriptors in the batch.
- * @param [in] reference the reference descriptor.
- * @param [in] candidates the candidate descriptor batch to match with the reference.
- * @param [out] results span of matching results.
- * @note Length of `results` must be at least the same as the length of the candidates batch.
- * @see IDescriptorBatch::getMaxCount().
- * @return Result with error code.
- * @see Span, MatchingResult, IDescriptor, IDescriptorBatch, Result and FSDKError for details.
- * @note all spans should be based on user owned continuous collections.
- * */
- virtual Result<FSDKError>
- match(
- const IDescriptor* reference,
- const IDescriptorBatch* candidates,
- Span<MatchingResult> results) noexcept = 0;
-
- /**
- * @brief Get algorithm model version this matcher works with.
- * @return Version as integral number.
- * */
- virtual uint32_t getModelVersion() const noexcept = 0;
-
- /**
- * @brief Calculates similarity based on distance.
- * @details The method gets distance from `distances`[i].distances.
- * and assigns the result to `distances`[i].similarity.
- * @param [in] dinstances is a mutable span of matching results with calculated distances.
- * @return Result with error code.
- * @see Span, MatchingResult, Result and FSDKError for details.
- * @note all spans should be based on user owned continuous collections.
- * */
- virtual Result<FSDKError> calcSimilarity(Span<MatchingResult> distances) const noexcept = 0;
-
- /**
- * @brief Calculates distance from similarity.
- * @details The method gets similarity from `similarities`[i].similarity
- * and assigns the result to `similarities`[i].distance.
- * @param [in] similarities is a mutable span of matching results with calculated similarity.
- * @return Result with error code.
- * @see Span, MatchingResult, Result and FSDKError for details.
- * @note all spans should be based on user owned continuous collections.
- * */
- virtual Result<FSDKError> calcDistance(Span<MatchingResult> similarities) const noexcept = 0;
- };
- /** @} */
- }
|