[mob][photos] Precompute face thumbnails for suggestions
This commit is contained in:
parent
6f6f976dec
commit
3fbfa8c0e6
2 changed files with 85 additions and 4 deletions
|
@ -1,3 +1,4 @@
|
|||
import "dart:async" show unawaited;
|
||||
import "dart:math";
|
||||
|
||||
import "package:flutter/foundation.dart" show kDebugMode;
|
||||
|
@ -61,8 +62,9 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
|
|||
),
|
||||
);
|
||||
}
|
||||
final numberOfDifferentSuggestions = snapshot.data!.length;
|
||||
final currentSuggestion = snapshot.data![currentSuggestionIndex];
|
||||
final allSuggestions = snapshot.data!;
|
||||
final numberOfDifferentSuggestions = allSuggestions.length;
|
||||
final currentSuggestion = allSuggestions[currentSuggestionIndex];
|
||||
final int clusterID = currentSuggestion.clusterIDToMerge;
|
||||
final double distance = currentSuggestion.distancePersonToCluster;
|
||||
final bool usingMean = currentSuggestion.usedOnlyMeanForSuggestion;
|
||||
|
@ -90,6 +92,7 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
|
|||
usingMean,
|
||||
files,
|
||||
numberOfDifferentSuggestions,
|
||||
allSuggestions,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -155,8 +158,9 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
|
|||
bool usingMean,
|
||||
List<EnteFile> files,
|
||||
int numberOfSuggestions,
|
||||
List<ClusterSuggestion> allSuggestions,
|
||||
) {
|
||||
return Column(
|
||||
final widgetToReturn = Column(
|
||||
key: ValueKey("cluster_id-$clusterID"),
|
||||
children: <Widget>[
|
||||
if (kDebugMode)
|
||||
|
@ -233,6 +237,28 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
|
|||
),
|
||||
],
|
||||
);
|
||||
// Precompute face thumbnails for next suggestions, in case there are
|
||||
const precompute = 6;
|
||||
const maxComputations = 10;
|
||||
int compCount = 0;
|
||||
|
||||
if (allSuggestions.length > currentSuggestionIndex + 1) {
|
||||
for (final suggestion in allSuggestions.sublist(
|
||||
currentSuggestionIndex + 1,
|
||||
min(allSuggestions.length, currentSuggestionIndex + precompute),
|
||||
)) {
|
||||
final files = suggestion.filesInCluster;
|
||||
final clusterID = suggestion.clusterIDToMerge;
|
||||
for (final file in files.sublist(0, min(files.length, 8))) {
|
||||
unawaited(PersonFaceWidget.precomputeFaceCrops(file, clusterID));
|
||||
compCount++;
|
||||
if (compCount >= maxComputations) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return widgetToReturn;
|
||||
}
|
||||
|
||||
List<Widget> _buildThumbnailWidgets(
|
||||
|
|
|
@ -33,9 +33,64 @@ class PersonFaceWidget extends StatelessWidget {
|
|||
),
|
||||
super(key: key);
|
||||
|
||||
static Future<void> precomputeFaceCrops(file, clusterID) async {
|
||||
try {
|
||||
final Face? face = await FaceMLDataDB.instance.getCoverFaceForPerson(
|
||||
recentFileID: file.uploadedFileID!,
|
||||
clusterID: clusterID,
|
||||
);
|
||||
if (face == null) {
|
||||
debugPrint(
|
||||
"No cover face for cluster $clusterID and recentFile ${file.uploadedFileID}",
|
||||
);
|
||||
return;
|
||||
}
|
||||
final Uint8List? cachedFace = faceCropCache.get(face.faceID);
|
||||
if (cachedFace != null) {
|
||||
return;
|
||||
}
|
||||
final faceCropCacheFile = cachedFaceCropPath(face.faceID);
|
||||
if ((await faceCropCacheFile.exists())) {
|
||||
final data = await faceCropCacheFile.readAsBytes();
|
||||
faceCropCache.put(face.faceID, data);
|
||||
return;
|
||||
}
|
||||
EnteFile? fileForFaceCrop = file;
|
||||
if (face.fileID != file.uploadedFileID!) {
|
||||
fileForFaceCrop =
|
||||
await FilesDB.instance.getAnyUploadedFile(face.fileID);
|
||||
}
|
||||
if (fileForFaceCrop == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final result = await pool.withResource(
|
||||
() async => await getFaceCrops(
|
||||
fileForFaceCrop!,
|
||||
{
|
||||
face.faceID: face.detection.box,
|
||||
},
|
||||
),
|
||||
);
|
||||
final Uint8List? computedCrop = result?[face.faceID];
|
||||
if (computedCrop != null) {
|
||||
faceCropCache.put(face.faceID, computedCrop);
|
||||
faceCropCacheFile.writeAsBytes(computedCrop).ignore();
|
||||
}
|
||||
return;
|
||||
} catch (e, s) {
|
||||
log(
|
||||
"Error getting cover face for cluster $clusterID",
|
||||
error: e,
|
||||
stackTrace: s,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (useGeneratedFaceCrops) {
|
||||
if (!useGeneratedFaceCrops) {
|
||||
return FutureBuilder<Uint8List?>(
|
||||
future: getFaceCrop(),
|
||||
builder: (context, snapshot) {
|
||||
|
|
Loading…
Add table
Reference in a new issue