def match( self, reference: FaceDescriptor, candidates: Union[FaceDescriptor, List[FaceDescriptor], FaceDescriptorBatch] ) -> Union[MatchingResult, List[MatchingResult]]: """ Match face descriptor vs face descriptors. Returns: List of matching results if match by several descriptors otherwise one MatchingResult. """ if isinstance(candidates, FaceDescriptor): error = self._coreMatcher.match(reference.coreEstimation, candidates.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return error.value elif isinstance(candidates, FaceDescriptorBatch): error, matchResults = self._coreMatcher.match( reference.coreEstimation, candidates.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return matchResults else: batch = self.descriptorFactory.generateDescriptorsBatch( len(candidates)) for candidate in candidates: batch.append(candidate) error, matchResults = self._coreMatcher.match( reference.coreEstimation, batch.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return matchResults
def estimateBasicAttributesBatch( self, warps: List[Union[FaceWarp, FaceWarpedImage]], estimateAge: bool, estimateGender: bool, estimateEthnicity: bool, aggregate: bool = False, ) -> Tuple[List[BasicAttributes], Union[None, BasicAttributes]]: """ Batch basic attributes estimation on warped images. Args: warps: warped images estimateAge: estimate age or not estimateGender: estimate gender or not estimateEthnicity: estimate ethnicity or not aggregate: aggregate attributes to one or not Returns: tuple, first element - list estimated attributes in corresponding order, second - optional aggregated attributes. Raises: LunaSDKException: if estimation failed """ dtAttributes = 0 if estimateAge: dtAttributes |= AttributeRequest.estimateAge if estimateGender: dtAttributes |= AttributeRequest.estimateGender if estimateEthnicity: dtAttributes |= AttributeRequest.estimateEthnicity images = [warp.warpedImage.coreImage for warp in warps] error, baseAttributes, aggregateAttribute = self._coreEstimator.estimate(images, AttributeRequest(dtAttributes)) if error.isError: errors = [] for image in images: errorOne, baseAttributesOne = self._coreEstimator.estimate(image, AttributeRequest(dtAttributes)) if errorOne.isOk: errors.append(LunaVLError.Ok.format(LunaVLError.Ok.description)) else: errors.append(LunaVLError.fromSDKError(errorOne)) raise LunaSDKException( LunaVLError.BatchedInternalError.format(LunaVLError.fromSDKError(error).detail), errors ) attributes = [BasicAttributes(baseAttribute) for baseAttribute in baseAttributes] if aggregate: return attributes, BasicAttributes(aggregateAttribute) else: return attributes, None
def estimate( warp: Union[HumanWarp, HumanWarpedImage, FaceWarp, FaceWarpedImage], descriptorFactory: BaseDescriptorFactory, coreEstimator: IDescriptorExtractorPtr, descriptor: Optional[BaseDescriptor] = None, ) -> BaseDescriptor: """ Estimate a face descriptor or a human descriptor from the warped image. Args: warp: warped image descriptor: descriptor for saving extract result descriptorFactory: descriptor factory coreEstimator: descriptor extractor Returns: estimated descriptor Raises: LunaSDKException: if estimation failed """ if descriptor is None: descriptor = descriptorFactory.generateDescriptor() coreDescriptor = descriptor.coreEstimation else: coreDescriptor = descriptor.coreEstimation error, optionalGS = coreEstimator.extractFromWarpedImage( warp.warpedImage.coreImage, coreDescriptor) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) descriptor.garbageScore = optionalGS return descriptor
def estimate( # type: ignore self, warp: Union[Warp, WarpedImage], descriptor: Optional[FaceDescriptor] = None) -> FaceDescriptor: """ Estimate face descriptor from a warp image. Args: warp: warped image descriptor: descriptor for saving extract result Returns: estimated descriptor Raises: LunaSDKException: if estimation failed """ if descriptor is None: descriptor = self.descriptorFactory.generateDescriptor() coreDescriptor = descriptor.coreEstimation else: coreDescriptor = descriptor.coreEstimation error, optionalGS = self._coreEstimator.extractFromWarpedImage( warp.warpedImage.coreImage, coreDescriptor) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) descriptor.garbageScore = optionalGS return descriptor
def makeWarpTransformationWithLandmarks( self, faceDetection: FaceDetection, typeLandmarks: str ) -> Union[Landmarks68, Landmarks5]: """ Make warp transformation with landmarks Args: faceDetection: face detection with landmarks5 typeLandmarks: landmarks for warping ("L68" or "L5") Returns: warping landmarks Raises: ValueError: if landmarks5 is not estimated LunaSDKException: if transform failed """ transformation = self._createWarpTransformation(faceDetection) if typeLandmarks == "L68": if faceDetection.landmarks68 is None: raise ValueError("landmarks68 does not estimated") error, warp = self._coreWarper.warp(faceDetection.landmarks68.coreEstimation, transformation) elif typeLandmarks == "L5": if faceDetection.landmarks5 is None: raise ValueError("landmarks5 does not estimated") error, warp = self._coreWarper.warp(faceDetection.landmarks5.coreEstimation, transformation) else: raise ValueError("Invalid value of typeLandmarks, must be 'L68' or 'L5'") if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) if typeLandmarks == "L68": return Landmarks68(warp) return Landmarks5(warp)
def estimate( self, warp: Union[FaceWarp, FaceWarpedImage], estimateAge: bool, estimateGender: bool, estimateEthnicity: bool ) -> BasicAttributes: """ Estimate a basic attributes (age, gender, ethnicity) from warped images. Args: warp: warped image estimateAge: estimate age or not estimateGender: estimate gender or not estimateEthnicity: estimate ethnicity or not Returns: estimated age, gender, ethnicity Raises: LunaSDKException: if estimation failed """ dtAttributes = 0 if estimateAge: dtAttributes |= AttributeRequest.estimateAge if estimateGender: dtAttributes |= AttributeRequest.estimateGender if estimateEthnicity: dtAttributes |= AttributeRequest.estimateEthnicity error, baseAttributes = self._coreEstimator.estimate(warp.warpedImage.coreImage, AttributeRequest(dtAttributes)) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return BasicAttributes(baseAttributes)
def estimate( self, detection: Optional[FaceDetection] = None, image: Optional[VLImage] = None, boundingBox: Optional[BoundingBox] = None, ) -> float: """ Estimate emotion on warp. Args: image: image in R8G8B8 format boundingBox: face bounding box of corresponding the image detection: face detection Returns: estimated ags, float in range[0,1] Raises: LunaSDKException: if estimation failed ValueError: if image and detection is Noee """ if detection is None: if image is None or boundingBox is None: raise ValueError( "image and boundingBox or detection bust be not None") error, ags = self._coreEstimator.estimate( image.coreImage, boundingBox.coreEstimation) else: error, ags = self._coreEstimator.estimate( detection.image.coreImage, detection.boundingBox.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return ags
def estimate(self, transformedLandmarks: Union[Landmarks5, Landmarks68], warp: Union[Warp, WarpedImage]) -> EyesEstimation: """ Estimate mouth state on warp. Args: warp: warped image transformedLandmarks: transformed landmarks Returns: estimated states Raises: LunaSDKException: if estimation failed """ cropper = EyeCropper() if isinstance(transformedLandmarks, Landmarks5): eyeRects = cropper.cropByLandmarks5( warp.warpedImage.coreImage, transformedLandmarks.coreEstimation) else: eyeRects = cropper.cropByLandmarks68( warp.warpedImage.coreImage, transformedLandmarks.coreEstimation) error, eyesEstimation = self._coreEstimator.estimate( warp.warpedImage.coreImage, eyeRects) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return EyesEstimation(eyesEstimation)
def estimateDescriptorsBatch( warps: Union[List[Union[HumanWarp, HumanWarpedImage]], List[Union[FaceWarp, FaceWarpedImage]]], descriptorFactory: Type[BaseDescriptorFactory], coreEstimator: IDescriptorExtractorPtr, aggregate: bool = False, descriptorBatch: Optional[BaseDescriptorBatch] = None, ) -> Tuple[BaseDescriptorBatch, Union[BaseDescriptor, None]]: """ Estimate a batch of descriptors from warped images. Args: warps: warped images aggregate: whether to estimate aggregate descriptor or not descriptorBatch: optional batch for saving descriptors descriptorFactory: descriptor factory coreEstimator: descriptor extractor Returns: tuple of batch and the aggregate descriptors (or None) Raises: LunaSDKException: if estimation failed """ if descriptorBatch is None: descriptorBatch = descriptorFactory.generateDescriptorsBatch( len(warps)) if aggregate: aggregatedDescriptor = descriptorFactory.generateDescriptor() error, optionalGSAggregateDescriptor, scores = coreEstimator.extractFromWarpedImageBatch( [warp.warpedImage.coreImage for warp in warps], descriptorBatch.coreEstimation, aggregatedDescriptor.coreEstimation, len(warps), ) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) aggregatedDescriptor.garbageScore = optionalGSAggregateDescriptor else: aggregatedDescriptor = None error, scores = coreEstimator.extractFromWarpedImageBatch( [warp.warpedImage.coreImage for warp in warps], descriptorBatch.coreEstimation, len(warps)) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) descriptorBatch.scores = scores return descriptorBatch, aggregatedDescriptor
def rawDescriptor(self) -> bytes: """ Get raw descriptors Returns: bytes with metadata """ error, descBytes = self.coreEstimation.save() if error.isError(): raise LunaSDKException(LunaVLError.fromSDKError(error)) return descBytes
def __init__( self, body: Union[bytes, bytearray, ndarray, CoreImage], imgFormat: Optional[ColorFormat] = None, filename: str = "", ): """ Init. Args: body: body of image - bytes numpy array or core image imgFormat: img format filename: user mark a source of image Raises: TypeError: if body has incorrect type LunaSDKException: if failed to load image to sdk Image """ if imgFormat is None: imgFormat = ColorFormat.R8G8B8 self.coreImage = CoreImage() if isinstance(body, CoreImage): self.coreImage = body elif isinstance(body, bytes): error = self.coreImage.loadFromMemory(body, len(body), imgFormat.coreFormat) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) elif isinstance(body, bytearray): error = self.coreImage.loadFromMemory(bytes(body), len(body), imgFormat.coreFormat) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) elif isinstance(body, ndarray): #: todo, format ????? self.coreImage.setData(body, imgFormat.coreFormat) else: raise TypeError("Bad image type") self.source = body self.filename = filename
def assertError(error: FSDKErrorResult) -> None: """ Assert core optional. Args: error: optional Raises: LunaSDKException: if optional contains error """ if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error))
def match( self, reference: Union[FaceDescriptor, bytes], candidates: Union[FaceDescriptor, bytes, List[Union[FaceDescriptor, bytes]], FaceDescriptorBatch], ) -> Union[MatchingResult, List[MatchingResult]]: """ Match face descriptor vs face descriptors. Returns: List of matching results if match by several descriptors otherwise one MatchingResult. """ if isinstance(reference, bytes): referenceForMatcher = self.descriptorFactory.generateDescriptor( reference) else: referenceForMatcher = reference if isinstance(candidates, bytes): candidatesForMatcher = self.descriptorFactory.generateDescriptor( candidates) elif isinstance(candidates, list): candidatesForMatcher = [] for idx in range(len(candidates)): if isinstance(candidates[idx], bytes): candidatesForMatcher.append( self.descriptorFactory.generateDescriptor( candidates[idx])) else: candidatesForMatcher.append(candidates[idx]) else: candidatesForMatcher = candidates if isinstance(candidatesForMatcher, FaceDescriptor): error, matchResults = self._coreMatcher.match( referenceForMatcher.coreEstimation, candidatesForMatcher.coreEstimation) elif isinstance(candidatesForMatcher, FaceDescriptorBatch): error, matchResults = self._coreMatcher.match( referenceForMatcher.coreEstimation, candidatesForMatcher.coreEstimation) else: batch = self.descriptorFactory.generateDescriptorsBatch( len(candidatesForMatcher)) for candidate in candidatesForMatcher: batch.append(candidate) error, matchResults = self._coreMatcher.match( referenceForMatcher.coreEstimation, batch.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return matchResults
def assertError(error: FSDKErrorResult, context: Optional[List[Any]] = None) -> None: """ Assert core optional. Args: error: optional context: list with errors Raises: LunaSDKException: if optional contains error """ if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error), context)
def validateInputByBatchEstimator(estimator, *args): """ Validate input data using batch estimator Args: estimator: estimator args: args to validate by estimator Raises: LunaSDKException(LunaVLError.BatchedInternalError): if data is not valid LunaSDKException: if validation is failed """ validationError, sdkErrors = estimator.validate(*args) if validationError.isOk: return errors = [LunaVLError.fromSDKError(error) for error in sdkErrors] if validationError.error != FSDKError.ValidationFailed: raise LunaSDKException(LunaVLError.fromSDKError(validationError), errors) raise LunaSDKException( LunaVLError.BatchedInternalError.format( LunaVLError.fromSDKError(validationError).detail), errors)
def estimate(self, warp: Union[Warp, WarpedImage]) -> Quality: """ Estimate quality from a warp. Args: warp: raw warped image or warp Returns: estimated quality Raises: LunaSDKException: if estimation failed """ error, coreQuality = self._coreEstimator.estimate(warp.warpedImage.coreImage) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return Quality(coreQuality)
def estimate(self, warp: Union[FaceWarp, FaceWarpedImage]) -> Mask: """ Estimate mask from a warp. Args: warp: raw warped image or warp Returns: estimated mask Raises: LunaSDKException: if estimation failed """ error, mask = self._coreEstimator.estimate(warp.warpedImage.coreImage) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return Mask(mask)
def estimate(self, warp: Union[FaceWarp, FaceWarpedImage]) -> MouthStates: """ Estimate mouth state on warp. Args: warp: warped image Returns: estimated states Raises: LunaSDKException: if estimation failed """ error, mouthState = self._coreEstimator.estimate( warp.warpedImage.coreImage) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return MouthStates(mouthState)
def estimate(self, warp: Union[FaceWarp, FaceWarpedImage]) -> Emotions: """ Estimate emotion on warp. Args: warp: warped image Returns: estimated emotions Raises: LunaSDKException: if estimation failed """ error, emotions = self._coreEstimator.estimate( warp.warpedImage.coreImage) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return Emotions(emotions)
def estimate(self, transformedLandmarks: Union[Landmarks5, Landmarks68], warp: Union[Warp, WarpedImage]) -> GazeDirection: """ Estimate a gaze direction Args: warp: warped image transformedLandmarks: transformed landmarks Returns: estimated states Raises: LunaSDKException: if estimation failed """ error, gaze = self._coreEstimator.estimate( warp.warpedImage.coreImage, transformedLandmarks.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return GazeDirection(gaze)
def estimateByBoundingBox(self, detection: BoundingBox, imageWithDetection: VLImage) -> HeadPose: """ Estimate head pose by detection. Args: detection: detection bounding box imageWithDetection: image with the detection. Returns: estimate head pose Raises: LunaSDKException: if estimation is failed """ error, headPoseEstimation = self._coreEstimator.estimate( imageWithDetection.coreImage, detection.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return HeadPose(headPoseEstimation)
def estimateBy68Landmarks(self, landmarks68: Landmarks68) -> HeadPose: """ Estimate head pose by 68 landmarks. Args: landmarks68: landmarks68 Returns: estimate head pose Raises: LunaSDKException: if estimation is failed """ error, headPoseEstimation = self._coreEstimator.estimate( landmarks68.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) return HeadPose(headPoseEstimation)
def warp(self, humanDetection: HumanDetection) -> HumanWarp: """ Create warp from detection. Args: humanDetection: human body detection with landmarks17 Returns: Warp Raises: LunaSDKException: if creation failed """ error, warp = self._coreWarper.warp(humanDetection.coreEstimation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) warpedImage = HumanWarpedImage(body=warp, filename=humanDetection.image.filename) return HumanWarp(warpedImage, humanDetection)
def warp(self, faceDetection: FaceDetection) -> FaceWarp: """ Create warp from detection. Args: faceDetection: face detection with landmarks5 Returns: Warp Raises: LunaSDKException: if creation failed """ transformation = self._createWarpTransformation(faceDetection) error, warp = self._coreWarper.warp(faceDetection.image.coreImage, transformation) if error.isError: raise LunaSDKException(LunaVLError.fromSDKError(error)) warpedImage = FaceWarpedImage(body=warp, filename=faceDetection.image.filename) return FaceWarp(warpedImage, faceDetection)
def getErrorsExtractingOneByOne() -> List[LunaVLError]: """ Extract descriptor without batching and collect errors Returns: list with errors """ errors = [] for idx, warp in enumerate(warps): if len(descriptorBatch): coreDescriptor = descriptorBatch[idx].coreEstimation else: descriptor = descriptorFactory.generateDescriptor() coreDescriptor = descriptor.coreEstimation errorOne, _ = coreEstimator.extractFromWarpedImage( warp.warpedImage.coreImage, coreDescriptor) if errorOne.isError: errors.append(LunaVLError.fromSDKError(errorOne)) else: errors.append(LunaVLError.Ok.format( LunaVLError.Ok.description)) return errors
def estimateDescriptorsBatch( warps: Union[List[Union[HumanWarp, HumanWarpedImage]], List[Union[FaceWarp, FaceWarpedImage]]], descriptorFactory: Type[BaseDescriptorFactory], coreEstimator: IDescriptorExtractorPtr, aggregate: bool = False, descriptorBatch: Optional[BaseDescriptorBatch] = None, ) -> Tuple[BaseDescriptorBatch, Union[BaseDescriptor, None]]: """ Estimate a batch of descriptors from warped images. Args: warps: warped images aggregate: whether to estimate aggregate descriptor or not descriptorBatch: optional batch for saving descriptors descriptorFactory: descriptor factory coreEstimator: descriptor extractor Returns: tuple of batch and the aggregate descriptors (or None) Raises: LunaSDKException: if estimation failed """ def getErrorsExtractingOneByOne() -> List[LunaVLError]: """ Extract descriptor without batching and collect errors Returns: list with errors """ errors = [] for idx, warp in enumerate(warps): if len(descriptorBatch): coreDescriptor = descriptorBatch[idx].coreEstimation else: descriptor = descriptorFactory.generateDescriptor() coreDescriptor = descriptor.coreEstimation errorOne, _ = coreEstimator.extractFromWarpedImage( warp.warpedImage.coreImage, coreDescriptor) if errorOne.isError: errors.append(LunaVLError.fromSDKError(errorOne)) else: errors.append(LunaVLError.Ok.format( LunaVLError.Ok.description)) return errors if descriptorBatch is None: descriptorBatch = descriptorFactory.generateDescriptorsBatch( len(warps)) if aggregate: aggregatedDescriptor = descriptorFactory.generateDescriptor() error, optionalGSAggregateDescriptor, scores = coreEstimator.extractFromWarpedImageBatch( [warp.warpedImage.coreImage for warp in warps], descriptorBatch.coreEstimation, aggregatedDescriptor.coreEstimation, len(warps), ) if error.isError: errors = getErrorsExtractingOneByOne() raise LunaSDKException( LunaVLError.BatchedInternalError.format( LunaVLError.fromSDKError(error).detail), errors) aggregatedDescriptor.garbageScore = optionalGSAggregateDescriptor else: aggregatedDescriptor = None error, scores = coreEstimator.extractFromWarpedImageBatch( [warp.warpedImage.coreImage for warp in warps], descriptorBatch.coreEstimation, len(warps)) if error.isError: errors = getErrorsExtractingOneByOne() raise LunaSDKException( LunaVLError.BatchedInternalError.format( LunaVLError.fromSDKError(error).detail), errors) descriptorBatch.scores = scores return descriptorBatch, aggregatedDescriptor