From 500adc3ab027240d8310bbed033fa272e731653e Mon Sep 17 00:00:00 2001 From: Melad Raouf Date: Tue, 21 Apr 2026 22:55:49 +0100 Subject: [PATCH 1/2] [MS-1412] Fix area calculation in RectF to handle negative values --- .../main/java/com/simprints/core/tools/extentions/RectF.ext.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/infra/core/src/main/java/com/simprints/core/tools/extentions/RectF.ext.kt b/infra/core/src/main/java/com/simprints/core/tools/extentions/RectF.ext.kt index c84205d7ee..aa3b89e503 100644 --- a/infra/core/src/main/java/com/simprints/core/tools/extentions/RectF.ext.kt +++ b/infra/core/src/main/java/com/simprints/core/tools/extentions/RectF.ext.kt @@ -1,5 +1,6 @@ package com.simprints.core.tools.extentions import android.graphics.RectF +import kotlin.math.abs -fun RectF.area() = height() * width() +fun RectF.area() = abs(height() * width()) From 8dddc5c4ca0c9bbf9c8f796cc02dcc1b86cf4c9a Mon Sep 17 00:00:00 2001 From: Melad Raouf Date: Tue, 21 Apr 2026 23:28:58 +0100 Subject: [PATCH 2/2] [MS-1413] Enhance face area detection logic to adapt based on image size --- .../simprints/face/capture/models/FaceTarget.kt | 3 ++- .../LiveFeedbackFragmentViewModel.kt | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/face/capture/src/main/java/com/simprints/face/capture/models/FaceTarget.kt b/face/capture/src/main/java/com/simprints/face/capture/models/FaceTarget.kt index 3549a78f59..316870679c 100644 --- a/face/capture/src/main/java/com/simprints/face/capture/models/FaceTarget.kt +++ b/face/capture/src/main/java/com/simprints/face/capture/models/FaceTarget.kt @@ -6,7 +6,8 @@ import kotlin.math.abs internal data class FaceTarget( val yawTarget: Target, val rollTarget: Target, - val areaRange: ClosedRange, + val minFacePixelArea: Float, + val maxRelativeArea: Float, ) { operator fun contains(face: Face): Boolean = face.roll in rollTarget && face.yaw in yawTarget } diff --git a/face/capture/src/main/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackFragmentViewModel.kt b/face/capture/src/main/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackFragmentViewModel.kt index 1c3bf071b0..b062a4afd1 100644 --- a/face/capture/src/main/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackFragmentViewModel.kt +++ b/face/capture/src/main/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackFragmentViewModel.kt @@ -46,7 +46,8 @@ internal class LiveFeedbackFragmentViewModel @Inject constructor( private val faceTarget = FaceTarget( SymmetricTarget(VALID_YAW_DELTA), SymmetricTarget(VALID_ROLL_DELTA), - 0.20f..0.5f, + minFacePixelArea = 10000f, // Todo to be visited latter + maxRelativeArea = 0.5f, ) private val fallbackCaptureEventStartTime = timeHelper.now() private var shouldSendFallbackCaptureEvent: AtomicBoolean = AtomicBoolean(true) @@ -229,9 +230,18 @@ internal class LiveFeedbackFragmentViewModel @Inject constructor( potentialFace: Face, ): FaceDetection { val areaOccupied = potentialFace.relativeBoundingBox.area() + + // 2. Calculate the absolute pixel area the face occupies in the current bitmap + val totalImageArea = bitmap.width * bitmap.height + val absoluteFaceArea = areaOccupied * totalImageArea + val status = when { - areaOccupied < faceTarget.areaRange.start -> FaceDetection.Status.TOOFAR - areaOccupied > faceTarget.areaRange.endInclusive -> FaceDetection.Status.TOOCLOSE + // Check if the face lacks enough pixel density (TOOFAR) + absoluteFaceArea < faceTarget.minFacePixelArea -> FaceDetection.Status.TOOFAR + + // Check if the face is overflowing the camera frame (TOOCLOSE) + areaOccupied > faceTarget.maxRelativeArea -> FaceDetection.Status.TOOCLOSE + potentialFace.yaw !in faceTarget.yawTarget -> FaceDetection.Status.OFFYAW potentialFace.roll !in faceTarget.rollTarget -> FaceDetection.Status.OFFROLL shouldCheckQuality() && potentialFace.quality < qualityThreshold -> FaceDetection.Status.BAD_QUALITY