detectAndCrop method

Future<Image?> detectAndCrop(
  1. CameraImage cameraImage,
  2. InputImageRotation rotation,
  3. FaceDetector detector, {
  4. CameraController? cameraController,
})

Detects faces in the camera image, applies rotation, and crops the face region.

This method takes into account platform-specific rotations, especially for iOS, where the front camera needs additional rotation adjustments. It selects the largest face in the frame and returns the cropped face image.

Implementation

Future<img.Image?> detectAndCrop(
  CameraImage cameraImage,
  InputImageRotation rotation,
  FaceDetector detector, {
  CameraController? cameraController,
}) async {
  final inputImage = buildInputImage(cameraImage, rotation);
  final faces = await detector.processImage(inputImage);
  if (faces.isEmpty) return null;

  img.Image fullImage = toImgImage(cameraImage);

  final cropRotation = cameraController != null
      ? getImageRotationForCrop(cameraController)
      : rotation;

  if (Platform.isIOS) {
    fullImage = img.flipHorizontal(fullImage);
  } else {
    fullImage = _applyRotation(fullImage, cropRotation);
  }

  final Face bestFace = faces.reduce(
    (a, b) => a.boundingBox.width > b.boundingBox.width ? a : b,
  );
  final box = bestFace.boundingBox;

  double left;
  final double top = box.top;
  final double faceWidth = box.width;
  final double faceHeight = box.height;

  if (Platform.isIOS) {
    left = fullImage.width - box.right;
  } else {
    left = box.left;
  }

  const double paddingFactor = 0.0;
  final double padX = faceWidth * paddingFactor;
  final double padY = faceHeight * paddingFactor;

  final x = (left - padX).clamp(0, fullImage.width - 1).toInt();
  final y = (top - padY).clamp(0, fullImage.height - 1).toInt();
  final w = (faceWidth + padX * 2).clamp(1, fullImage.width - x).toInt();
  final h = (faceHeight + padY * 2).clamp(1, fullImage.height - y).toInt();

  img.Image cropped = img.copyCrop(
    fullImage,
    x: x,
    y: y,
    width: w,
    height: h,
  );

  final int size = cropped.width < cropped.height
      ? cropped.width
      : cropped.height;
  final int offsetX = (cropped.width - size) ~/ 2;
  final int offsetY = (cropped.height - size) ~/ 2;
  cropped = img.copyCrop(
    cropped,
    x: offsetX,
    y: offsetY,
    width: size,
    height: size,
  );

  if (Platform.isIOS) {
    return _applyRotation(cropped, cropRotation);
  }

  return cropped;
}