Source code for lunavl.sdk.estimator_collections
"""Module contains face estimator collections.
"""
from enum import Enum
from typing import List, Optional
from lunavl.sdk.estimators.face_estimators.ags import AGSEstimator
from lunavl.sdk.estimators.face_estimators.basic_attributes import BasicAttributesEstimator
from lunavl.sdk.estimators.face_estimators.emotions import EmotionsEstimator
from lunavl.sdk.estimators.face_estimators.eyes import EyeEstimator, GazeEstimator
from lunavl.sdk.estimators.face_estimators.face_descriptor import FaceDescriptorEstimator
from lunavl.sdk.estimators.face_estimators.head_pose import HeadPoseEstimator
from lunavl.sdk.estimators.face_estimators.mouth_state import MouthStateEstimator
from lunavl.sdk.estimators.face_estimators.warp_quality import WarpQualityEstimator
from lunavl.sdk.faceengine.engine import VLFaceEngine
[docs]class FaceEstimator(Enum):
"""
Enum for face estimators.
"""
#: head pose estimator
HeadPose = 1
#: eye estimation (eyelid, iris landmarks and state)
Eye = 2
#: emotion estimator
Emotions = 3
#: basic attributes estimator
BasicAttributes = 4
#: gaze direction estimator
GazeDirection = 5
#: mouth state estimator
MouthState = 6
#: warp quality estimator
WarpQuality = 7
#: ags estimator
AGS = 8
#: face descriptor estimator
Descriptor = 9
[docs]class FaceEstimatorsCollection:
"""
Collection of lazy load face estimators.
Attributes:
_headPoseEstimator (Optional[HeadPoseEstimator]): lazy load head pose estimator
_eyeEstimator (Optional[EyeEstimator]): lazy load eye estimator
_gazeDirectionEstimator (Optional[GazeEstimator]): lazy load gaze direction estimator
_mouthStateEstimator (Optional[MouthStateEstimator]): lazy load mouth state estimator
_warpQualityEstimator (Optional[WarpQualityEstimator]): lazy load warp quality estimator
_basicAttributesEstimator (Optional[BasicAttributesEstimator]): lazy load basic attributes estimator
_emotionsEstimator (Optional[EmotionsEstimator]): lazy load emotions estimator
_AGSEstimator (Optional[AGSEstimator]): lazy load ags estimator
_descriptorEstimator (Optional[FaceDescriptorEstimator]): lazy load face descriptor estimator
warper (Optional[Warper]): warper
"""
__slots__ = ("_headPoseEstimator", "_eyeEstimator", "_gazeDirectionEstimator", "_mouthStateEstimator",
"_warpQualityEstimator", "_basicAttributesEstimator", "_emotionsEstimator", "_faceEngine",
"_AGSEstimator", "warper", "_descriptorEstimator")
def __init__(self, startEstimators: Optional[List[FaceEstimator]] = None,
faceEngine: Optional[VLFaceEngine] = None):
"""
Init.
Args:
startEstimators: list of estimators which will be initiate now
faceEngine: faceengine, factory for estimators
"""
if faceEngine is None:
self._faceEngine = VLFaceEngine()
else:
self._faceEngine = faceEngine
self._basicAttributesEstimator = None
self._eyeEstimator = None
self._emotionsEstimator = None
self._gazeDirectionEstimator = None
self._mouthStateEstimator = None
self._warpQualityEstimator = None
self._headPoseEstimator = None
self._AGSEstimator = None
self._descriptorEstimator = None
self.warper = self._faceEngine.createWarper()
if startEstimators:
for estimator in set(startEstimators):
self.initEstimator(estimator)
@staticmethod
def _getEstimatorByAttributeName(estimatorAttributeName: str) -> FaceEstimator:
"""
Get face estimator by attribute name which corresponding to estimator
Args:
estimatorAttributeName: name
Returns:
corresponding face estimator
Raises:
ValueError("Bad attribute name"): if face estimator not found
"""
for estimator in FaceEstimator:
if estimator.name.lower() == estimatorAttributeName[1: -len("Estimator")]:
return estimator
raise ValueError("Bad attribute name")
def _getAttributeNameByEstimator(self, estimator: FaceEstimator) -> str:
"""
Get an estimator attribute name bya face estimator
Args:
estimator: face estimator
Returns:
corresponding attribute name
Raises:
ValueError("Bad estimator"): if attribute name not found
"""
for estimatorName in self.__slots__:
if estimatorName == "_faceEngine":
continue
if estimator.name.lower() == estimatorName[1: -len("Estimator")]:
return estimatorName
raise ValueError("Bad estimator")
[docs] def initEstimator(self, estimator: FaceEstimator) -> None:
"""
Create an estimator. Create new estimator with help self._faceengine
Args:
estimator: estimator for creating
Raises:
ValueError("Bad estimator type"): if estimator not found
"""
if estimator == FaceEstimator.BasicAttributes:
self._basicAttributesEstimator = self._faceEngine.createBasicAttributesEstimator()
elif estimator == FaceEstimator.Eye:
self._eyeEstimator = self._faceEngine.createEyeEstimator()
elif estimator == FaceEstimator.Emotions:
self._emotionsEstimator = self._faceEngine.createEmotionEstimator()
elif estimator == FaceEstimator.GazeDirection:
self._gazeDirectionEstimator = self._faceEngine.createGazeEstimator()
elif estimator == FaceEstimator.MouthState:
self._mouthStateEstimator = self._faceEngine.createMouthEstimator()
elif estimator == FaceEstimator.WarpQuality:
self._warpQualityEstimator = self._faceEngine.createWarpQualityEstimator()
elif estimator == FaceEstimator.HeadPose:
self._headPoseEstimator = self._faceEngine.createHeadPoseEstimator()
elif estimator == FaceEstimator.AGS:
self._AGSEstimator = self._faceEngine.createAGSEstimator()
elif estimator == FaceEstimator.Descriptor:
self._descriptorEstimator = self._faceEngine.createFaceDescriptorEstimator()
else:
raise ValueError("Bad estimator type")
@property
def descriptorEstimator(self) -> FaceDescriptorEstimator:
"""
Get head pose estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._descriptorEstimator is None:
self._descriptorEstimator = self._faceEngine.createFaceDescriptorEstimator()
return self._descriptorEstimator
@property
def headPoseEstimator(self) -> HeadPoseEstimator:
"""
Get head pose estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._headPoseEstimator is None:
self._headPoseEstimator = self._faceEngine.createHeadPoseEstimator()
return self._headPoseEstimator
@headPoseEstimator.setter
def headPoseEstimator(self, newEstimator: HeadPoseEstimator) -> None:
"""
Set head pose estimator.
Args:
newEstimator: new estimator
"""
self._headPoseEstimator = newEstimator
# pylint: disable=C0103
@property
def AGSEstimator(self) -> AGSEstimator:
"""
Get ags estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._AGSEstimator is None:
self._AGSEstimator = self._faceEngine.createAGSEstimator()
return self._AGSEstimator
# pylint: disable=C0103
@AGSEstimator.setter
def AGSEstimator(self, newEstimator: AGSEstimator) -> None:
"""
Set ags estimator.
Args:
newEstimator: new estimator
"""
self._AGSEstimator = newEstimator
@property
def basicAttributesEstimator(self) -> BasicAttributesEstimator:
"""
Get basic attributes estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._basicAttributesEstimator is None:
self._basicAttributesEstimator = self._faceEngine.createBasicAttributesEstimator()
return self._basicAttributesEstimator
@basicAttributesEstimator.setter
def basicAttributesEstimator(self, newEstimator: BasicAttributesEstimator) -> None:
"""
Set basic attributes estimator.
Args:
newEstimator: new estimator
"""
self._basicAttributesEstimator = newEstimator
@property
def eyeEstimator(self) -> EyeEstimator:
"""
Get eye estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._eyeEstimator is None:
self._eyeEstimator = self._faceEngine.createEyeEstimator()
return self._eyeEstimator
@eyeEstimator.setter
def eyeEstimator(self, newEstimator: EyeEstimator) -> None:
"""
Set eye estimator.
Args:
newEstimator: new estimator
"""
self._eyeEstimator = newEstimator
@property
def emotionsEstimator(self) -> EmotionsEstimator:
"""
Get emotions estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._emotionsEstimator is None:
self._emotionsEstimator = self._faceEngine.createEmotionEstimator()
return self._emotionsEstimator
@emotionsEstimator.setter
def emotionsEstimator(self, newEstimator: EmotionsEstimator) -> None:
"""
Set emotions estimator.
Args:
newEstimator: new estimator
"""
self._emotionsEstimator = newEstimator
@property
def gazeDirectionEstimator(self) -> GazeEstimator:
"""
Get gaze direction estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._gazeDirectionEstimator is None:
self._gazeDirectionEstimator = self._faceEngine.createGazeEstimator()
return self._gazeDirectionEstimator
@gazeDirectionEstimator.setter
def gazeDirectionEstimator(self, newEstimator: GazeEstimator) -> None:
"""
Set gaze direction estimator.
Args:
newEstimator: new estimator
"""
self._gazeDirectionEstimator = newEstimator
@property
def mouthStateEstimator(self) -> MouthStateEstimator:
"""
Get mouth state estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._mouthStateEstimator is None:
self._mouthStateEstimator = self._faceEngine.createMouthEstimator()
return self._mouthStateEstimator
@mouthStateEstimator.setter
def mouthStateEstimator(self, newEstimator: MouthStateEstimator) -> None:
"""
Set mouth state estimator.
Args:
newEstimator: new estimator
"""
self._mouthStateEstimator = newEstimator
@property
def warpQualityEstimator(self) -> WarpQualityEstimator:
"""
Get warp quality estimator.
If estimator is initialized it will be returned otherwise it will be initialized and returned
Returns:
estimator
"""
if self._warpQualityEstimator is None:
self._warpQualityEstimator = self._faceEngine.createWarpQualityEstimator()
return self._warpQualityEstimator
@warpQualityEstimator.setter
def warpQualityEstimator(self, newEstimator: WarpQualityEstimator) -> None:
"""
Set warp quality estimator.
Args:
newEstimator: new estimator
"""
self._warpQualityEstimator = newEstimator
@property
def faceEngine(self) -> VLFaceEngine:
"""
Get current faceengine.
Returns:
self._faceEngine
"""
return self._faceEngine
@faceEngine.setter
def faceEngine(self, newFaceEngine: VLFaceEngine) -> None:
"""
Set new faceengine. All initialize estimators will be re-initialized.
Args:
newFaceEngine: new faceengine
"""
self._faceEngine = newFaceEngine
for estimatorName in self.__slots__:
if estimatorName == "_faceEngine":
continue
if getattr(self, estimatorName) is not None:
self.initEstimator(FaceEstimatorsCollection._getEstimatorByAttributeName(estimatorName))
self.warper = self._faceEngine.createWarper()
[docs] def removeEstimator(self, estimator: FaceEstimator) -> None:
"""
Remove estimators.
Args:
estimator: estimator for removing
"""
estimatorName = self._getAttributeNameByEstimator(estimator)
setattr(self, estimatorName, None)