package com.visioncamerafacedetection import android.graphics.PointF import androidx.camera.core.ImageProxy import com.facebook.react.bridge.WritableNativeMap import com.google.android.gms.tasks.Tasks import com.google.mlkit.vision.common.InputImage import com.google.mlkit.vision.face.Face import com.google.mlkit.vision.face.FaceDetection import com.google.mlkit.vision.face.FaceDetectorOptions import com.mrousavy.camera.frameprocessor.FrameProcessorPlugin import kotlin.math.abs class FaceDetectionFrameProcessorPlugin : FrameProcessorPlugin("detectFace") { private val options = FaceDetectorOptions.Builder() .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST) .setMinFaceSize(0.25f) .build() private val detector = FaceDetection.getClient(options) override fun callback(image: ImageProxy, params: Array): Any? { val map = WritableNativeMap() val inputImage = InputImage.fromMediaImage(image.image!!, image.imageInfo.rotationDegrees) val task = detector.process(inputImage) try { val faces: List = Tasks.await(task) if (faces.size == 1) { val face = faces[0] val bounds = face.boundingBox val eulerY = face.headEulerAngleY val eulerZ = face.headEulerAngleZ val isFaceStraight = abs(eulerY) <= 10 && abs(eulerZ) <= 10 val imageCenter = PointF(image.width / 2f, image.height / 2f) val faceCenter = PointF(bounds.exactCenterX(), bounds.exactCenterY()) val threshold = 0.25f * image.width // e.g., 320 val xDifference = abs(imageCenter.x - faceCenter.x) val yDifference = abs(imageCenter.y - faceCenter.y) val maxDifferenceAllowed = 100 val isXWithinBounds = xDifference <= threshold + maxDifferenceAllowed && xDifference >= threshold - maxDifferenceAllowed val isYWithinBounds = yDifference <= threshold + maxDifferenceAllowed && yDifference >= threshold - maxDifferenceAllowed val isFaceInCenter = isXWithinBounds && isYWithinBounds map.putBoolean("isFaceStraight", isFaceStraight) map.putBoolean("isFaceInCenter", isFaceInCenter) map.putBoolean("hasFace", true) } else { map.putBoolean("hasFace", false) map.putBoolean("isFaceInCenter", false) map.putBoolean("isFaceStraight", false) } map.putBoolean("isStable", true) } catch (e: Exception) { map.putBoolean("hasFace", false) map.putBoolean("isFaceInCenter", false) map.putBoolean("isFaceStraight", false) map.putBoolean("isStable", true) } return map } }