getFaceEmbeddings method

Future<List<Float32List?>> getFaceEmbeddings(
  1. List<Face> faces,
  2. Uint8List imageBytes
)

Generates face embeddings for multiple detected faces.

More efficient than calling getFaceEmbedding multiple times because it decodes the image only once in the isolate.

Returns a list of Float32List embeddings in the same order as faces. Faces that fail to produce embeddings will have null entries.

Implementation

Future<List<Float32List?>> getFaceEmbeddings(
  List<Face> faces,
  Uint8List imageBytes,
) async {
  _requireReady();
  // Four doubles per face. A face whose eye landmarks are unavailable is
  // marked with a NaN quad and comes back as a null entry, matching the
  // previous behavior where the per-face failure happened in the isolate.
  final Float64List eyes = Float64List(faces.length * 4);
  for (int i = 0; i < faces.length; i++) {
    try {
      eyes.setRange(i * 4, i * 4 + 4, _embeddingEyesPayload(faces[i]));
    } catch (_) {
      // Preserve the old per-face failure contract: one malformed face must
      // not abort embeddings for every other face in the batch.
      eyes[i * 4] = double.nan;
      eyes[i * 4 + 1] = double.nan;
      eyes[i * 4 + 2] = double.nan;
      eyes[i * 4 + 3] = double.nan;
    }
  }
  final List<dynamic> result = await _sendDetectionRequest<List<dynamic>>(
    'embeddings',
    {
      'bytes': TransferableTypedData.fromList([imageBytes]),
      'eyes': eyes,
    },
  );
  return result.map((dynamic item) => item as Float32List?).toList();
}