yoti-face-capture-android provides a simplified way of capturing a face. It performs face detection from the front facing or back camera, analyses those frames and produces an optimised cropped image of the captured face.
This library leverages on Google ML Kit to perform face detection.
- Android 21+
In your gradle.properties
add one of the following dependency
implementation 'com.yoti.mobile.android:face-capture-bundled:4.5.0'
implementation 'com.yoti.mobile.android:face-capture-unbundled:4.5.0'
We offer two options to add this library to your app, bundled and unbundled.
The bundled version embeds a 16Mb AI model for face detection with about 23.1Mb total SDK size.
The unbundled version which has an estimated SDK size of 2.4Mb, will manage the download of the AI model via Google Play Services the first time you start using the AI model. It is recommended to add the following metadata to your manifest.xml
to get the model downloaded as soon as the app is installed.
<application ...>
...
<meta-data
android:name="com.google.firebase.ml.vision.DEPENDENCIES"
android:value="face" />
</application>
Add the FaceCapture
View to your layout
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.yoti.mobile.android.capture.face.ui.FaceCapture
android:id="@+id/faceCapture"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
...
</androidx.constraintlayout.widget.ConstraintLayout>
val faceCenter = PointF(0.5F, 0.5F)
val configuration = FaceCaptureConfiguration(
faceCenter,
ImageQuality.MEDIUM,
requireValidAngle = true,
requireEyesOpen = true,
requireBrightEnvironment = true,
requiredStableFrames = 3,
provideLandmarks = true,
provideSmileScore = true
)
The face center is a PointF
representing the expected position of the center of the user's face inside the image captured. In the samples below, it is represented by the intersection of the red and blue lines in the sample images.
If the actual face center is not near this point it will not be considered a valid face.
- In this sample we set as faceCenter a point which has to match with where the face silhouette is inside the
FaceCapture
view. This is the place where the user's face will be. In this case, the faceCenter is set toPointF(.5F, .45F)
, which means, a 50% of the horizontal axis and 45% of the vertical one.
- In this other sample, we have a face silhouette which is closer to the top of the
FaceCapture
view, so we should move the vertical axis point towards the upper part, so in this case the FaceCenter configuration is set toPointF(.5F, .35F)
:
This is the image quality of the cropped image after it has been compressed and converted to JPEG. It can be either ImageQuality.LOW
or ImageQuality.MEDIUM
or ImageQuality.HIGH
This boolean if true, will require the picture to be taken with a tilt angle no bigger than 30 degrees.
When this requirement is not met FaceNotStraight
error is returned.
This boolean if true it will require the eyes to be opened.
When this requirement is not met EyesClosed
error is returned.
If true it will require the environment luminosity to be above a pre-determined threshold.
When this requirement is not met EnvironmentTooDark
error is returned.
This integer will require "n" number of frames to be as similar as possible in terms of width/hight and x/y position.
The purpose of this is to avoid capturing blurry images.
When this requirement is not met FaceNotStable
error is returned.
If set to true, SDK will return facial landmark points for both original and cropped images on a valid face. These set of points are nullable.
If set to true, SDK will return smile score on a valid face. This score is a nullable value.
val faceCapture = findViewById<FaceCapture>(R.id.faceCapture)
There are two ways to start the camera:
faceCapture.startCamera(this, ::onCameraState)
Or you could also do:
faceCapture.cameraState.observe(this, ::onCameraState)
faceCaputure.startCamera(this)
There are a few states that can be returned to allow the integrator to know what the current state of the Face Capture is. These are:
- CameraReady - Face Capture has connected to the camera and the preview is available, but no analyzing is happening yet.
- CameraStopped - The camera has stopped and no analyzing is happening.
- Analyzing - The camera is ready and the Face Capture is analyzing frames to detect faces.
- CameraInitializationError - There was an error initializing the camera and it is not possible to swap to other facing camera.
- MissingPermissions - Face Capture does not have permissions to caccess the camera.
- CameraFacingSwapped - Configured facing camera is not available and the SDK has swappped automatically to the other facing camera (if available)
The following CameraErrors can be returned when the state is CameraInitializationError
- IllegalState
- UnableToResolveCamera
- Unknown
Start the detection and listen for incoming FaceCaptureResult
faceCapture.startAnalysing(configuration, ::onFaceCaptureResult)
This can be called straight after startCamera(), no need to wait for CameraReady
Result of the face capture containing the following:
- Original Image. This will be a 1280x720 YUV image
- State of the face capture:
- Invalid Face containing the reason it is invalid
- Valid Face containing:
- Cropped Image - Byte array representation of a compressed JPEG image based on the configured image quality
- The bounding box of the face inside the cropped image
- The bounding box of the face inside the original image
- Facial landmark points for the original image
- Facial landmark points for the cropped image
- Smile score between 0.0 (unlikely smiling) and 1.0 (more likely smiling)
If the cropping of the face did not meet the requirements then the Invalid Face will be returned. This will not contain any cropped image.
The error states and validation states are in a specific order. For example, the FaceTooSmall check will be performed before the FaceNotCentered check. As such here are the states that can be returned in order of the checks that are done:
- AnalysisError: this could happen if the device is not compatible with the SDK and the capture analysis cannot be performed. We recommend you to fallback to manual capture mode (check sample app) if this error happens, do the user can do a manual capture.
- NoFaceDetected
- MultipleFacesDetected
- FaceTooSmall
- FaceTooBig
- FaceNotCentered
- EnvironmentTooDark
Optional errors (depending on the configuration passed):
- FaceNotStraight
- EyesClosed
- FaceNotStable
faceCapture.stopAnalysing()
faceCapture.stopCamera()
This is only required if it is part of your camera flow. Not required in response of lifecycle changes.
You can find a sample App here. It is divided in three different use cases:
- Automatic capture: capture is done automatically when a valid frame is detected.
- Manual capture: capture is done by the user with a button which is visible only when a valid frame is detected.
- Debug mode: this mode could help you to define the Face Center parameter for your UI.
If you have any other questions please do not hesitate to contact us here: https://support.yoti.com Once we have answered your question we may contact you again to discuss Yoti products and services. If you'd prefer us not to do this, please let us know when you e-mail.