processCameraImage method

Future<Face?> processCameraImage(
  1. InputImage inputImage, {
  2. required Size screenSize,
  3. required Size regionSize,
  4. int stabilityCount = 10,
  5. double eyeOpenProbability = 0.75,
  6. dynamic onFaceLiveStatusChange(
    1. FaceStatus
    )?,
})

stabilityCount Number of continuous steady shots required. eyeOpenProbability Probability of eyes being open.

Implementation

Future<Face?> processCameraImage(
  InputImage inputImage, {
  required Size screenSize,
  required Size regionSize,
  int stabilityCount = 10,
  double eyeOpenProbability = 0.75,
  Function(FaceStatus)? onFaceLiveStatusChange,
}) async {
  final List<Face> faces = await _faceDetector.processImage(inputImage);

  if (faces.isNotEmpty && faces.length == 1) {
    Face face = faces.first;

    /// Complete organ and part check.
    bool isLandmarks = _checkLandmarks(face);
    var isFaceRegionInside = _isFaceRegionInside(
        boundingBox: face.boundingBox,
        screenSize: screenSize,
        cameraSize: inputImage.metadata!.size,
        regionSize: regionSize);

    if (isLandmarks && isFaceRegionInside) {
      _tempFaces.add(face);
      if (_tempFaces.length > stabilityCount) {
        // Detect Smile
        if (!_isSmilePassed) {
          onFaceLiveStatusChange?.call(FaceStatus.smile);
          bool isSmiling = (face.smilingProbability ?? 0.0) > 0.8;

          if (isSmiling) {
            _isSmilePassed = true;
          } else {
            return null;
          }
        }

        // A blink is defined as closing and reopening the eyes within 2 seconds.
        bool eyesOpen = (face.leftEyeOpenProbability ?? 0.0) > 0.75 &&
            (face.rightEyeOpenProbability ?? 0.0) > 0.75;
        bool eyesClosed = (face.leftEyeOpenProbability ?? 1.0) < 0.25 &&
            (face.rightEyeOpenProbability ?? 1.0) < 0.25;

        onFaceLiveStatusChange?.call(FaceStatus.blink);

        if (_handleBlinkState(eyesOpen, eyesClosed)) {
          _faceDetector.close();
          _tempFaces.clear();
          onFaceLiveStatusChange?.call(FaceStatus.finish);
          return face;
        }
      }
    } else {
      /// Not in the frame, need restart the process
      _resetAllStates();
      onFaceLiveStatusChange?.call(FaceStatus.outside);
    }
  } else {
    _tempFaces.clear();
    onFaceLiveStatusChange?.call(FaceStatus.outside);
  }
  return null;
}