Configuring the camera#
Applies to LUNA ID for Android only.
LUNA ID for Android uses Google's CameraX library to provide flexible and reliable camera control, enabling you to customize key video capture parameters for optimal face detection and analysis.
Key camera parameters#
The following parameters are part of ShowCameraParams
and define how the camera operates during a face capture session:
@Serializable(with = CameraSelectorSerializer::class)
val cameraSelector: CameraSelector = defaultCameraSelector(),
@Serializable(with = ResolutionSelectorSerializer::class)
val previewResolutionSelector: ResolutionSelector = defaultPreviewResolutionSelector(),
@Serializable(with = ResolutionSelectorSerializer::class)
val analysisResolutionSelector: ResolutionSelector = defaultAnalysisResolutionSelector(),
@Serializable(with = QualitySelectorSerializer::class)
val videoQualitySelector: QualitySelector = defaultVideoQualitySelector(),
Parameter | Description |
---|---|
cameraSelector |
Specifies which physical camera to use: front (DEFAULT_FRONT_CAMERA ) or rear (DEFAULT_BACK_CAMERA ). |
previewResolutionSelector |
Sets the resolution of the video stream displayed on the device screen (UI preview). |
analysisResolutionSelector |
Defines the resolution of frames sent to the LUNA ID detector for facial analysis (for example, liveness, attribute estimation). |
videoQualitySelector |
Determines the quality of the recorded video output. Possible values: SD , HD , FHD , UHD . |
Default configuration#
LUNA ID applies the following defaults for camera operation:
Parameter | Default value |
---|---|
Video quality | SD (~640x480 pixels) |
Analysis resolution | 640×480 pixels |
Review resolution | 640×480 pixels |
Default camera | Front-facing |
const val DEFAULT_ANALYSIS_FRAME_WIDTH = 640
const val DEFAULT_ANALYSIS_FRAME_HEIGHT = 480
const val DEFAULT_PREVIEW_FRAME_WIDTH = 640
const val DEFAULT_PREVIEW_FRAME_HEIGHT = 480
val DEFAULT_ANALYSIS_ASPECT_RATIO_STRATEGY = AspectRatioStrategy.RATIO_16_9_FALLBACK_AUTO_STRATEGY
val DEFAULT_PREVIEW_ASPECT_RATIO_STRATEGY = AspectRatioStrategy.RATIO_16_9_FALLBACK_AUTO_STRATEGY
val DEFAULT_VIDEO_QUALITY: Quality = Quality.SD
These values are used in the corresponding functions:
private fun defaultAnalysisResolutionSelector(): ResolutionSelector =
ResolutionSelector.Builder()
.setResolutionStrategy(
ResolutionStrategy(
Size(DEFAULT_ANALYSIS_FRAME_WIDTH, DEFAULT_ANALYSIS_FRAME_HEIGHT),
ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER
)
)
.setAspectRatioStrategy(DEFAULT_ANALYSIS_ASPECT_RATIO_STRATEGY)
.build()
private fun defaultPreviewResolutionSelector(): ResolutionSelector =
ResolutionSelector.Builder()
.setResolutionStrategy(
ResolutionStrategy(
Size(DEFAULT_PREVIEW_FRAME_WIDTH, DEFAULT_PREVIEW_FRAME_HEIGHT),
ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER
)
)
.setAspectRatioStrategy(ShowCameraParams.DEFAULT_PREVIEW_ASPECT_RATIO_STRATEGY)
.build()
private fun defaultVideoQualitySelector() =
QualitySelector.from(ShowCameraParams.DEFAULT_VIDEO_QUALITY)
private fun defaultCameraSelector(): CameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
Note: The
FALLBACK_RULE_CLOSEST_HIGHER
strategy ensures that if the requested resolution is not supported by the device, the system selects the closest higher available resolution.
Pre-initializing camera availability#
On certain devices, particularly embedded systems like POS terminals, it may be necessary to pre-initialize the camera provider to ensure timely access. You can proactively load the list of available cameras, for example, within the MainActivity
scope:
CoroutineScope(Dispatchers.IO).launch {
(this@MainActivity.application as App)
.availableCameraTypes
.update { getAvailableCameraTypes(this@MainActivity) }
}
Getting available camera types#
Use this function to retrieve available camera types:
@SuppressLint("RestrictedApi1")
@ExperimentalCamera2Interop
suspend fun getAvailableCameraTypes(context: Context): List<Int> = withContext(Dispatchers.IO) {
val provider = ProcessCameraProvider.getInstance(context).get()
provider
.availableCameraInfos
.mapNotNull { info ->
val characteristics = Camera2CameraInfo.from(info).cameraCharacteristicsMap
Log.i("FacePayViewModel", "getAvailableCameraTypes: $characteristics")
val lensFacing = characteristics.values.firstOrNull()?.get(CameraCharacteristics.LENS_FACING)
when (lensFacing) {
CameraCharacteristics.LENS_FACING_BACK -> 1
CameraCharacteristics.LENS_FACING_FRONT -> 0
else -> null
}
}
.distinct()
}
This populates an observable state (availableCameraTypes
) with the supported camera directions (front or back).
Launching the camera with dynamic selection#
Once camera availability is known, you can launch LunaID.showCamera()
using the detected camera type:
val cameras = (context.applicationContext as App).availableCameraTypes
cameras.filterNotNull().first { availableCameras ->
val cameraSelector = getSelectorFor(availableCameras.first())
val showCameraParams = settings.showCameraParams.copy(
borderDistanceStrategy = BorderDistancesStrategy.WithCustomView(R.id.faceCaptureOverlay),
cameraSelector = cameraSelector,
checkSecurity = false,
)
LunaID.showCamera(
context = context,
params = showCameraParams,
interactions = Interactions.Builder().build(),
commands = Commands.Builder().build()
)
true
}
fun getSelectorFor(type: Int): CameraSelector =
CameraSelector.Builder()
.requireLensFacing(type)
.build()