checkLiveness method
Runs the ONNX model to get liveness score Returns a score between 0 and 1, where higher = more likely to be real
Implementation
Future<bool> checkLiveness(imglib.Image image) async {
// Preprocess image to model input format
final input = _preprocessImage(image);
final runOptions = OrtRunOptions();
// Create input tensor
// Model expects [1, 3, 256, 256] based on training config (resize = dict(height=256, width=256))
final inputOrt = OrtValueTensor.createTensorWithDataList(
input,
[1, 3, 256, 256], // Shape: [batch, channels, height, width]
);
// Run inference
final inputs = {_session.inputNames.first: inputOrt};
final outputs = await _session.runAsync(
runOptions,
inputs,
);
// Get output
final outputTensor = outputs?.first;
if (outputTensor == null) {
throw Exception('No output from model');
}
// Extract score from output
final outputData = outputTensor.value as List<List<double>>;
debugPrint('[ONNX AntiSpoof] Raw output: $outputData');
debugPrint(
'[ONNX AntiSpoof] outputData[0].length: ${outputData[0].length}');
// The output format depends on your model
// Common formats:
// 1. [batch, 2] - probabilities for [fake, real]
// 2. [batch, 1] - single confidence score
bool isReal = false;
if (outputData[0].length == 2) {
List<double> out = outputData[0];
double realProb = out[0];
// double spoofProb = out[1];
if (realProb >= livenessThreshold) {
isReal = true;
}
// Binary classification: [fake_prob, real_prob]
// score = spoofProb; // Real face probability
} else if (outputData[0].length == 1) {
// Single score output
// score = outputData[0][0];
} else if (outputData[0].length == 3) {
final fakeProb = outputData[0][0]; // Index 0
final realProb = outputData[0][1]; // Index 1
final unknownProb = outputData[0][2]; // Index 2
debugPrint(
'[ONNX AntiSpoof] Fake: $fakeProb, Real: $realProb, Unknown: $unknownProb');
// Method 1: Use argmax (like original code)
final maxIndex =
outputData[0].indexOf(outputData[0].reduce((a, b) => a > b ? a : b));
if (maxIndex == 1) {
isReal = true;
debugPrint(
'[ONNX AntiSpoof] outputData[0].length == 3 Decision: REAL (argmax = 1)');
} else {
// Method 2: Fallback - compare real vs fake directly
// Use this if argmax doesn't work well
if (realProb > fakeProb) {
isReal = true;
debugPrint(
'[ONNX AntiSpoof]outputData[0].length == 3 Decision: REAL (realProb > fakeProb)');
} else {
debugPrint(
'[ONNX AntiSpoof]outputData[0].length == 3 Decision: FAKE');
}
}
// Multi-class: take max or specific index
// score = outputData[0].reduce((a, b) => a > b ? a : b);
}
// Release resources
inputOrt.release();
outputTensor.release();
runOptions.release();
return isReal;
}