yoti-face-capture-android provides a simplified way of capturing a face. It performs face detection from the front facing camera, analyses those frames and produces an optimised cropped image of the captured face.
This library leverage Google ML Kit to perform the face detection.
- Android 21+
In your gradle.properties
add one of the following dependency
implementation 'com.yoti.mobile.android:face-capture-bundled:4.1.2'
implementation 'com.yoti.mobile.android:face-capture-unbundled:4.1.2'
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. Additionally you can 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 captured face.
If the actual face center is not near this point it will not be considered a valid face.
This parameter is a percentage value (x, y). E.g.: (0,0) - top left; (0.5, 0.5) - center of the screen; (1,1) - bottom right;
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 valid face. These set of points are nullable
If set to true, SDK will return smile score on valid face. These 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 - The Face Capture has connected to the camera and the preview is available, but no analyzing is happening
- 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 initialzing the camera.
- MissingPermissions - The Face Capture does not have sufficient permissions to caccess the camera.
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
- 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.
If you have any other questions please do not hesitate to contact [email protected] 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.