IBestShotMobileObserver interface#
As was explained in the "BestShotMobile object" chapter all frames are handled into the BestShotMobile library with an asynchronous scheme.
To receive results of the processing use should define the callbacks by implementing the IBestShotMobileObserver interface. This interface has several virtual methods that should be overridden.
BestShot callback#
All frames from the pushFrame method are handled with the next steps:
- Face detection to find any face on the frame
- Checking quality of the frame and head pose with BestShotQualityEstimator. See "FaceEngine_Handbook" for details.
User code will receive the bestShot callback with a BestShotInfo structure for every frame with detected face. The BestShotInfo structure contains next fields:
struct BestShotInfo {
//! State of this frame
BestShotState state;
//! Source image
fsdk::Image image;
//! Detection with face
fsdk::Detection detection;
//! Face landmarks
fsdk::Landmarks5 landmarks;
//! Estimation of the head position.
//! This parameter could help to show notification to the user in case of bad angles.
fsdk::HeadPoseEstimation headPoseEstimation;
//! AGS estimation result.
//! This parameter could help to show notification to the user in case of bad quality.
float agsEstimation;
//! Index of the frame
tsdk::FrameId frameIndex;
//! Index of the track
tsdk::TrackId trackId;
};
If all checks are successfully processed and the results are good enough (head angles are less than thresholds, quality of the frame is good) the current frame is estimated as the best shot. The BestShotInfo::state field will be set to BestShotState::Ok in this case.
If some parameters of the frame are not good or some error happened during the processing the BestShotInfo::state will be set to one of the next values: BestShotState::BadQuality - in case of bad frame quality, BestShotState::BadHeadPose - in case of bad head angles, BestShotState::Error - in case of some error during processing.
It can be a good solution to show some notification to the user about BestShotState::BadQuality and BestShotState::BadHeadPose statuses of the bestshot.
If the best shot without liveness check is not required for any business logic and notification to the user is not required this user-defined callback could be just empty. In case of some additional logic (for example, some user interaction) this callback could be useful.
Liveness callback#
All the frames that were estimated as the best shot will be checked for the liveness state at the next step. The result of this check will be sent through the separated liveness callback with the BestShotInfo structure and the LivenessState enum.
The BestShotInfo structure was described in the previous section.
The LivenessState enum can contain the next states:
enum class LivenessState {
Alive, //!< Face was estimated as alive.
Fake, //!< Face was estimated as not alive.
None, //!< No liveness check at all.
NotReady, //!< Liveness check not ready for now. Need more frames to handle.
BadHeadPose, //!< Head angles bigger than thresholds.
BadQuality, //!< Image quality is less than threshold.
FaceNotFound, //!< Face was not found.
FaceTooClose, //!< Face is too close to the camera.
FaceCloseToBorder, //!< Face is too close to the frame border.
FaceTooSmall, //!< Face is too small.
TooManyFaces, //!< There is more than one face in the frame.
Timeout, //!< Liveness timeout.
CriticalError //!< Critical during liveness processing.
};
Note It can be a good solution to show some notification to the user about LivenessState::BadQuality, LivenessState::BadHeadPose, LivenessState::FaceTooClose, LivenessState::FaceTooSmall and LivenessState::TooManyFaces statuses of the liveness.
TrackEnd callback#
The BestShotMobile library has a face tracking functionality. When the current face track has ended no more best shots should be expected from it. To handle this situation user-defined trackEnd callback could be used.
If such situation should not be handled by the business logic this callback could be just empty.
Settings the callbacks#
To use all callbacks user should implement the IBestShotMobileObserver interface. Then the user should create this implementation class and pass the pointer to this class to the setBestShotMobileObserver method.