[mob] FaceMlService static method for full pipeline

This commit is contained in:
laurenspriem 2024-04-16 15:04:15 +05:30
parent e3b8d8975f
commit 618b152f17

View file

@ -204,83 +204,9 @@ class FaceMlService {
try { try {
switch (function) { switch (function) {
case FaceMlOperation.analyzeImage: case FaceMlOperation.analyzeImage:
final int enteFileID = args["enteFileID"] as int; final FaceMlResult result =
final String imagePath = args["filePath"] as String; await FaceMlService.analyzeImageSync(args);
final int faceDetectionAddress = sendPort.send(result.toJsonString());
args["faceDetectionAddress"] as int;
final int faceEmbeddingAddress =
args["faceEmbeddingAddress"] as int;
final resultBuilder =
FaceMlResultBuilder.fromEnteFileID(enteFileID);
dev.log(
"Start analyzing image with uploadedFileID: $enteFileID inside the isolate",
);
final stopwatchTotal = Stopwatch()..start();
final stopwatch = Stopwatch()..start();
// Decode the image once to use for both face detection and alignment
final imageData = await File(imagePath).readAsBytes();
final image = await decodeImageFromData(imageData);
final ByteData imgByteData = await getByteDataFromImage(image);
dev.log('Reading and decoding image took '
'${stopwatch.elapsedMilliseconds} ms');
stopwatch.reset();
// Get the faces
final List<FaceDetectionRelative> faceDetectionResult =
await FaceMlService.detectFacesSync(
image,
imgByteData,
faceDetectionAddress,
resultBuilder: resultBuilder,
);
dev.log(
"${faceDetectionResult.length} faces detected with scores ${faceDetectionResult.map((e) => e.score).toList()}: completed `detectFacesSync` function, in "
"${stopwatch.elapsedMilliseconds} ms");
// If no faces were detected, return a result with no faces. Otherwise, continue.
if (faceDetectionResult.isEmpty) {
dev.log(
"No faceDetectionResult, Completed analyzing image with uploadedFileID $enteFileID, in "
"${stopwatch.elapsedMilliseconds} ms");
sendPort.send(resultBuilder.buildNoFaceDetected().toJsonString());
break;
}
stopwatch.reset();
// Align the faces
final Float32List faceAlignmentResult =
await FaceMlService.alignFacesSync(
image,
imgByteData,
faceDetectionResult,
resultBuilder: resultBuilder,
);
dev.log("Completed `alignFacesSync` function, in "
"${stopwatch.elapsedMilliseconds} ms");
stopwatch.reset();
// Get the embeddings of the faces
final embeddings = await FaceMlService.embedFacesSync(
faceAlignmentResult,
faceEmbeddingAddress,
resultBuilder: resultBuilder,
);
dev.log("Completed `embedFacesSync` function, in "
"${stopwatch.elapsedMilliseconds} ms");
stopwatch.stop();
stopwatchTotal.stop();
dev.log("Finished Analyze image (${embeddings.length} faces) with "
"uploadedFileID $enteFileID, in "
"${stopwatchTotal.elapsedMilliseconds} ms");
sendPort.send(resultBuilder.build().toJsonString());
break; break;
} }
} catch (e, stackTrace) { } catch (e, stackTrace) {
@ -875,6 +801,7 @@ class FaceMlService {
} }
} }
/// Analyzes the given image data by running the full pipeline for faces, using [analyzeImageSync] in the isolate.
Future<FaceMlResult?> analyzeImageInSingleIsolate(EnteFile enteFile) async { Future<FaceMlResult?> analyzeImageInSingleIsolate(EnteFile enteFile) async {
_checkEnteFileForID(enteFile); _checkEnteFileForID(enteFile);
await ensureInitialized(); await ensureInitialized();
@ -931,6 +858,87 @@ class FaceMlService {
return result; return result;
} }
static Future<FaceMlResult> analyzeImageSync(Map args) async {
try {
final int enteFileID = args["enteFileID"] as int;
final String imagePath = args["filePath"] as String;
final int faceDetectionAddress = args["faceDetectionAddress"] as int;
final int faceEmbeddingAddress = args["faceEmbeddingAddress"] as int;
final resultBuilder = FaceMlResultBuilder.fromEnteFileID(enteFileID);
dev.log(
"Start analyzing image with uploadedFileID: $enteFileID inside the isolate",
);
final stopwatchTotal = Stopwatch()..start();
final stopwatch = Stopwatch()..start();
// Decode the image once to use for both face detection and alignment
final imageData = await File(imagePath).readAsBytes();
final image = await decodeImageFromData(imageData);
final ByteData imgByteData = await getByteDataFromImage(image);
dev.log('Reading and decoding image took '
'${stopwatch.elapsedMilliseconds} ms');
stopwatch.reset();
// Get the faces
final List<FaceDetectionRelative> faceDetectionResult =
await FaceMlService.detectFacesSync(
image,
imgByteData,
faceDetectionAddress,
resultBuilder: resultBuilder,
);
dev.log(
"${faceDetectionResult.length} faces detected with scores ${faceDetectionResult.map((e) => e.score).toList()}: completed `detectFacesSync` function, in "
"${stopwatch.elapsedMilliseconds} ms");
// If no faces were detected, return a result with no faces. Otherwise, continue.
if (faceDetectionResult.isEmpty) {
dev.log(
"No faceDetectionResult, Completed analyzing image with uploadedFileID $enteFileID, in "
"${stopwatch.elapsedMilliseconds} ms");
return resultBuilder.buildNoFaceDetected();
}
stopwatch.reset();
// Align the faces
final Float32List faceAlignmentResult =
await FaceMlService.alignFacesSync(
image,
imgByteData,
faceDetectionResult,
resultBuilder: resultBuilder,
);
dev.log("Completed `alignFacesSync` function, in "
"${stopwatch.elapsedMilliseconds} ms");
stopwatch.reset();
// Get the embeddings of the faces
final embeddings = await FaceMlService.embedFacesSync(
faceAlignmentResult,
faceEmbeddingAddress,
resultBuilder: resultBuilder,
);
dev.log("Completed `embedFacesSync` function, in "
"${stopwatch.elapsedMilliseconds} ms");
stopwatch.stop();
stopwatchTotal.stop();
dev.log("Finished Analyze image (${embeddings.length} faces) with "
"uploadedFileID $enteFileID, in "
"${stopwatchTotal.elapsedMilliseconds} ms");
return resultBuilder.build();
} catch (e, s) {
dev.log("Could not analyze image: \n e: $e \n s: $s");
rethrow;
}
}
Future<String?> _getImagePathForML( Future<String?> _getImagePathForML(
EnteFile enteFile, { EnteFile enteFile, {
FileDataForML typeOfData = FileDataForML.fileData, FileDataForML typeOfData = FileDataForML.fileData,