callWithScore method

Future<({List<List<double>> landmarks, double? score})> callWithScore(
  1. Mat faceCrop, {
  2. Float32List? buffer,
})

Returns the 468 3D landmark points in normalized coordinates plus the model's face-presence score in the range 0.0 to 1.0 (higher means more confident the crop contains a face). score is null when the model does not expose a presence output.

Example:

final faceCropMat = cv.imdecode(bytes, cv.IMREAD_COLOR);
final result = await faceLandmark.callWithScore(faceCropMat);
final meshPoints = result.landmarks;
final presence = result.score;
faceCropMat.dispose();

Implementation

Future<({List<List<double>> landmarks, double? score})> callWithScore(
  cv.Mat faceCrop, {
  Float32List? buffer,
}) async {
  final CompiledModel? compiledModel = _compiledModel;
  if (compiledModel != null) {
    // Copying runAsync is the official LiteRT pattern for host-side data
    // (the C++ Write/Read API is lock+memcpy+unlock); the Metal accelerator
    // only supports MetalBufferPacked tensor buffers, so host zero-copy is
    // not available on the GPU path.
    final ImageTensor pack = convertImageToTensor(
      faceCrop,
      outW: _inW,
      outH: _inH,
      buffer: buffer ?? _scratchBuf,
    );
    final List<Float32List> outputs = await compiledModel.runAsync([
      pack.tensorNHWC,
    ]);
    return (
      landmarks: _unpackLandmarks(
        outputs[_bestIdx],
        _inW,
        _inH,
        pack.padding,
        clamp: true,
        normalizeZ: true,
      ),
      score: _scoreIdx == -1 ? null : sigmoidClipped(outputs[_scoreIdx][0]),
    );
  }

  final ImageTensor pack = convertImageToTensor(
    faceCrop,
    outW: _inW,
    outH: _inH,
    buffer: buffer ?? _scratchBuf,
  );

  if (_iso == null) {
    _views.inputs[0].setAll(0, pack.tensorNHWC);
    _itp!.invoke();
    return (
      landmarks: _unpackLandmarks(
        _views.outputs[_bestIdx],
        _inW,
        _inH,
        pack.padding,
        clamp: true,
        normalizeZ: true,
      ),
      score: _scoreIdx == -1
          ? null
          : sigmoidClipped(_views.outputs[_scoreIdx][0]),
    );
  } else {
    fillNHWC4D(pack.tensorNHWC, _input4dCache, _inH, _inW);
    final List<List<List<List<List<double>>>>> inputs = [_input4dCache];
    await _iso!.runForMultipleInputs(inputs, _outputsCache);

    final Float32List bestFlat = flattenDynamicTensor(
      _outputsCache[_bestIdx],
    );
    final double? score = _scoreIdx == -1
        ? null
        : sigmoidClipped(flattenDynamicTensor(_outputsCache[_scoreIdx])[0]);
    return (
      landmarks: _unpackLandmarks(
        bestFlat,
        _inW,
        _inH,
        pack.padding,
        clamp: true,
        normalizeZ: true,
      ),
      score: score,
    );
  }
}