process method

FaceMeshResult process(
  1. FaceMeshImage image, {
  2. NormalizedRect? roi,
  3. FaceMeshBox? box,
  4. double boxScale = _boxScale,
  5. bool boxMakeSquare = true,
  6. int rotationDegrees = 0,
  7. bool mirrorHorizontal = false,
})

Processes an image and returns face landmarks.

By default, this processes using the internal ROI tracking state. To process the full frame or restrict processing to a region, provide either:

  • roi as a normalized rectangle, or
  • box as a pixel-space bounding box (converted to an ROI internally).

To force full-frame inference without passing a region each time, disable ROI tracking at creation via enableRoiTracking.

When box is provided, it is converted into a square ROI by default (using the max of width/height) and optionally expanded by boxScale.

Implementation

FaceMeshResult process(
  FaceMeshImage image, {
  NormalizedRect? roi,
  FaceMeshBox? box,
  double boxScale = _boxScale,
  bool boxMakeSquare = true,
  int rotationDegrees = 0,
  bool mirrorHorizontal = false,
}) {
  _ensureNotClosed();
  if (roi != null && box != null) {
    throw ArgumentError('Provide either roi or box, not both.');
  }
  if (rotationDegrees != 0 &&
      rotationDegrees != 90 &&
      rotationDegrees != 180 &&
      rotationDegrees != 270) {
    throw ArgumentError('rotationDegrees must be one of {0, 90, 180, 270}.');
  }
  final int logicalWidth = (rotationDegrees == 90 || rotationDegrees == 270)
      ? image.height
      : image.width;
  final int logicalHeight = (rotationDegrees == 90 || rotationDegrees == 270)
      ? image.width
      : image.height;
  final NormalizedRect? effectiveRoi =
      roi ??
      (box != null
          ? _normalizedRectFromBox(
              box,
              imageWidth: logicalWidth,
              imageHeight: logicalHeight,
              scale: boxScale,
              makeSquare: boxMakeSquare,
            )
          : null);
  final _NativeImage nativeImage = _toNativeImage(image);
  final ffi.Pointer<MpNormalizedRect> roiPtr = effectiveRoi != null
      ? _toNativeRect(effectiveRoi)
      : ffi.nullptr;
  FaceMeshResult? processed;
  try {
    final ffi.Pointer<MpFaceMeshResult> resultPtr = faceBindings
        .mp_face_mesh_process(
          _context,
          nativeImage.image,
          roiPtr == ffi.nullptr ? ffi.nullptr : roiPtr,
          rotationDegrees,
          mirrorHorizontal ? 1 : 0,
        );
    if (resultPtr == ffi.nullptr) {
      throw MediapipeFaceMeshException(
        _readCString(faceBindings.mp_face_mesh_last_error(_context)) ??
            'Native face mesh error.',
      );
    }
    processed = _copyResult(resultPtr.ref);
    faceBindings.mp_face_mesh_release_result(resultPtr);
  } finally {
    pkg_ffi.calloc.free(nativeImage.pixels);
    pkg_ffi.calloc.free(nativeImage.image);
    if (roiPtr != ffi.nullptr) {
      pkg_ffi.calloc.free(roiPtr);
    }
  }
  return processed;
}