[mob] Persist remote feedback before running clustering
This commit is contained in:
parent
18f202d3e4
commit
1996d86835
|
@ -482,6 +482,24 @@ class FaceMLDataDB {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> bulkAssignClusterToPersonID(
|
||||
Map<int, String> clusterToPersonID,) async {
|
||||
final db = await instance.database;
|
||||
final batch = db.batch();
|
||||
for (final entry in clusterToPersonID.entries) {
|
||||
final clusterID = entry.key;
|
||||
final personID = entry.value;
|
||||
batch.insert(
|
||||
clusterPersonTable,
|
||||
{
|
||||
personIdColumn: personID,
|
||||
cluserIDColumn: clusterID,
|
||||
},
|
||||
);
|
||||
}
|
||||
await batch.commit(noResult: true);
|
||||
}
|
||||
|
||||
Future<void> captureNotPersonFeedback({
|
||||
required String personID,
|
||||
required int clusterID,
|
||||
|
|
|
@ -36,8 +36,7 @@ const createFaceClustersTable = '''
|
|||
CREATE TABLE IF NOT EXISTS $faceClustersTable (
|
||||
$fcFaceId TEXT NOT NULL,
|
||||
$fcClusterID INTEGER NOT NULL,
|
||||
PRIMARY KEY($fcFaceId),
|
||||
FOREIGN KEY($fcFaceId) REFERENCES $facesTable($faceIDColumn)
|
||||
PRIMARY KEY($fcFaceId)
|
||||
);
|
||||
''';
|
||||
// -- Creating a non-unique index on clusterID for query optimization
|
||||
|
|
|
@ -84,6 +84,24 @@ class PersonService {
|
|||
return PersonEntity(result.id, data);
|
||||
}
|
||||
|
||||
Future<void> storeRemoteFeedback() async {
|
||||
final entities = await entityService.getEntities(EntityType.person);
|
||||
entities.sort((a, b) => a.updatedAt.compareTo(b.updatedAt));
|
||||
final Map<String, int> faceIdToClusterID = {};
|
||||
final Map<int, String> clusterToPersonID = {};
|
||||
for (var e in entities) {
|
||||
final personData = PersonData.fromJson(json.decode(e.data));
|
||||
for (var cluster in personData.assigned!) {
|
||||
for (var faceId in cluster.faces) {
|
||||
faceIdToClusterID[faceId] = cluster.id;
|
||||
}
|
||||
clusterToPersonID[cluster.id] = e.id;
|
||||
}
|
||||
}
|
||||
await faceMLDataDB.updateClusterIdToFaceId(faceIdToClusterID);
|
||||
await faceMLDataDB.bulkAssignClusterToPersonID(clusterToPersonID);
|
||||
}
|
||||
|
||||
Future<void> updatePerson(PersonEntity updatePerson) async {
|
||||
await entityService.addOrUpdate(
|
||||
EntityType.person,
|
||||
|
|
|
@ -737,6 +737,7 @@ class SearchService {
|
|||
}
|
||||
|
||||
Future<List<GenericSearchResult>> getAllFace(int? limit) async {
|
||||
try {
|
||||
debugPrint("getting faces");
|
||||
final Map<int, Set<int>> fileIdToClusterID =
|
||||
await FaceMLDataDB.instance.getFileIdToClusterIds();
|
||||
|
@ -755,7 +756,8 @@ class SearchService {
|
|||
}
|
||||
final cluserIds = fileIdToClusterID[f.uploadedFileID ?? -1]!;
|
||||
for (final cluster in cluserIds) {
|
||||
final PersonEntity? p = personIdToPerson[clusterIDToPersonID[cluster] ?? ""];
|
||||
final PersonEntity? p =
|
||||
personIdToPerson[clusterIDToPersonID[cluster] ?? ""];
|
||||
if (p != null) {
|
||||
if (personIdToFiles.containsKey(p.remoteID)) {
|
||||
personIdToFiles[p.remoteID]!.add(f);
|
||||
|
@ -807,8 +809,9 @@ class SearchService {
|
|||
}
|
||||
final sortedClusterIds = clusterIdToFiles.keys.toList()
|
||||
..sort(
|
||||
(a, b) =>
|
||||
clusterIdToFiles[b]!.length.compareTo(clusterIdToFiles[a]!.length),
|
||||
(a, b) => clusterIdToFiles[b]!
|
||||
.length
|
||||
.compareTo(clusterIdToFiles[a]!.length),
|
||||
);
|
||||
|
||||
for (final clusterId in sortedClusterIds) {
|
||||
|
@ -817,7 +820,8 @@ class SearchService {
|
|||
final String clusterName = "${files.length}";
|
||||
|
||||
if (clusterIDToPersonID[clusterId] != null) {
|
||||
throw Exception("Cluster $clusterId should not have person id ${clusterIDToPersonID[clusterId]}");
|
||||
throw Exception(
|
||||
"Cluster $clusterId should not have person id ${clusterIDToPersonID[clusterId]}");
|
||||
}
|
||||
if (files.length < 3) {
|
||||
continue;
|
||||
|
@ -849,6 +853,10 @@ class SearchService {
|
|||
} else {
|
||||
return facesResult;
|
||||
}
|
||||
} catch (e, s) {
|
||||
_logger.severe("Error in getAllFace", e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<GenericSearchResult>> getAllLocationTags(int? limit) async {
|
||||
|
|
|
@ -159,6 +159,7 @@ class _FaceDebugSectionWidgetState extends State<FaceDebugSectionWidget> {
|
|||
trailingIcon: Icons.chevron_right_outlined,
|
||||
trailingIconIsMuted: true,
|
||||
onTap: () async {
|
||||
await PersonService.instance.storeRemoteFeedback();
|
||||
await FaceMlService.instance
|
||||
.clusterAllImages(clusterInBuckets: true);
|
||||
Bus.instance.fire(PeopleChangedEvent());
|
||||
|
@ -225,10 +226,15 @@ class _FaceDebugSectionWidgetState extends State<FaceDebugSectionWidget> {
|
|||
"You will need to again re-index all the faces. You can drop feedback if you want to label again",
|
||||
firstButtonLabel: "Yes, confirm",
|
||||
firstButtonOnTap: () async {
|
||||
try {
|
||||
await FaceMLDataDB.instance
|
||||
.dropClustersAndPersonTable(faces: true);
|
||||
Bus.instance.fire(PeopleChangedEvent());
|
||||
showShortToast(context, "Done");
|
||||
} catch (e, s) {
|
||||
_logger.warning('drop feedback failed ', e, s);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue