From 1299e12d92f777c812ece4a9fe8ec0cfaca09799 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Fri, 17 May 2024 11:27:42 +0530 Subject: [PATCH] [mob][photos] Cleanup face debug options --- mobile/lib/face/db.dart | 62 +--- .../face_ml/feedback/cluster_feedback.dart | 1 - .../debug/face_debug_section_widget.dart | 277 +++++------------- 3 files changed, 73 insertions(+), 267 deletions(-) diff --git a/mobile/lib/face/db.dart b/mobile/lib/face/db.dart index 5a6ad72dff..9316916a35 100644 --- a/mobile/lib/face/db.dart +++ b/mobile/lib/face/db.dart @@ -576,60 +576,6 @@ class FaceMLDataDB { } } - /// Returns a map of faceID to record of clusterId and faceEmbeddingBlob - /// - /// Only selects faces with score greater than [minScore] and blur score greater than [minClarity] - Future> getFaceEmbeddingMap({ - double minScore = kMinimumQualityFaceScore, - int minClarity = kLaplacianHardThreshold, - int maxFaces = 20000, - int offset = 0, - int batchSize = 10000, - }) async { - final EnteWatch w = EnteWatch("getFaceEmbeddingMap")..start(); - w.logAndReset( - 'reading as float offset: $offset, maxFaces: $maxFaces, batchSize: $batchSize', - ); - final db = await instance.asyncDB; - - final Map result = {}; - while (true) { - // Query a batch of rows - final List> maps = await db.getAll( - 'SELECT $faceIDColumn, $faceEmbeddingBlob FROM $facesTable' - ' WHERE $faceScore > $minScore AND $faceBlur > $minClarity' - ' ORDER BY $faceIDColumn' - ' DESC LIMIT $batchSize OFFSET $offset', - // facesTable, - // columns: [faceIDColumn, faceEmbeddingBlob], - // where: '$faceScore > $minScore and $faceBlur > $minClarity', - // limit: batchSize, - // offset: offset, - // orderBy: '$faceIDColumn DESC', - ); - // Break the loop if no more rows - if (maps.isEmpty) { - break; - } - final List faceIds = []; - for (final map in maps) { - faceIds.add(map[faceIDColumn] as String); - } - final faceIdToClusterId = await getFaceIdsToClusterIds(faceIds); - for (final map in maps) { - final faceID = map[faceIDColumn] as String; - result[faceID] = - (faceIdToClusterId[faceID], map[faceEmbeddingBlob] as Uint8List); - } - if (result.length >= maxFaces) { - break; - } - offset += batchSize; - } - w.stopWithLog('done reading face embeddings ${result.length}'); - return result; - } - Future> getFaceEmbeddingMapForFile( List fileIDs, ) async { @@ -750,6 +696,7 @@ class FaceMLDataDB { return maps.first['count'] as int; } + /// WARNING: This method does not drop the persons and other feedback. Consider using [dropClustersAndPersonTable] instead. Future resetClusterIDs() async { try { final db = await instance.asyncDB; @@ -972,12 +919,15 @@ class FaceMLDataDB { await db.execute(deletePersonTable); await db.execute(dropClusterPersonTable); - await db.execute(dropClusterSummaryTable); await db.execute(dropNotPersonFeedbackTable); - + await db.execute(dropClusterSummaryTable); + await db.execute(dropFaceClustersTable); + await db.execute(createClusterPersonTable); await db.execute(createNotPersonFeedbackTable); await db.execute(createClusterSummaryTable); + await db.execute(createFaceClustersTable); + await db.execute(fcClusterIDIndex); } catch (e, s) { _logger.severe('Error dropping clusters and person table', e, s); } diff --git a/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart b/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart index 248a77ac2a..f8908f06c4 100644 --- a/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart +++ b/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart @@ -463,7 +463,6 @@ class ClusterFeedbackService { Future createFakeClustersByBlurValue() async { try { // Delete old clusters - await FaceMLDataDB.instance.resetClusterIDs(); await FaceMLDataDB.instance.dropClustersAndPersonTable(); final List persons = await PersonService.instance.getPersons(); diff --git a/mobile/lib/ui/settings/debug/face_debug_section_widget.dart b/mobile/lib/ui/settings/debug/face_debug_section_widget.dart index 5c590818a0..363d08699c 100644 --- a/mobile/lib/ui/settings/debug/face_debug_section_widget.dart +++ b/mobile/lib/ui/settings/debug/face_debug_section_widget.dart @@ -64,8 +64,8 @@ class _FaceDebugSectionWidgetState extends State { if (snapshot.hasData) { return CaptionedTextWidget( title: LocalSettings.instance.isFaceIndexingEnabled - ? "Disable faces (${snapshot.data!})" - : "Enable faces (${snapshot.data!})", + ? "Disable faces (${snapshot.data!} files done)" + : "Enable faces (${snapshot.data!} files done)", ); } return const SizedBox.shrink(); @@ -90,6 +90,7 @@ class _FaceDebugSectionWidgetState extends State { } }, ), + sectionOptionSpacing, MenuItemWidget( captionedTextWidget: FutureBuilder( future: FaceMLDataDB.instance.getIndexedFileCount(), @@ -119,64 +120,7 @@ class _FaceDebugSectionWidgetState extends State { } }, ), - // MenuItemWidget( - // captionedTextWidget: FutureBuilder( - // future: FaceMLDataDB.instance.getTotalFaceCount(), - // builder: (context, snapshot) { - // if (snapshot.hasData) { - // return CaptionedTextWidget( - // title: "${snapshot.data!} high quality faces", - // ); - // } - // return const SizedBox.shrink(); - // }, - // ), - // pressedColor: getEnteColorScheme(context).fillFaint, - // trailingIcon: Icons.chevron_right_outlined, - // trailingIconIsMuted: true, - // onTap: () async { - // final faces75 = await FaceMLDataDB.instance - // .getTotalFaceCount(minFaceScore: 0.75); - // final faces78 = await FaceMLDataDB.instance - // .getTotalFaceCount(minFaceScore: kMinHighQualityFaceScore); - // final blurryFaceCount = - // await FaceMLDataDB.instance.getBlurryFaceCount(15); - // showShortToast(context, "$blurryFaceCount blurry faces"); - // }, - // ), - // MenuItemWidget( - // captionedTextWidget: const CaptionedTextWidget( - // title: "Analyze file ID 25728869", - // ), - // pressedColor: getEnteColorScheme(context).fillFaint, - // trailingIcon: Icons.chevron_right_outlined, - // trailingIconIsMuted: true, - // onTap: () async { - // try { - // final enteFile = await SearchService.instance.getAllFiles().then( - // (value) => value.firstWhere( - // (element) => element.uploadedFileID == 25728869, - // ), - // ); - // _logger.info( - // 'File with ID ${enteFile.uploadedFileID} has name ${enteFile.displayName}', - // ); - // FaceMlService.instance.isImageIndexRunning = true; - // final result = await FaceMlService.instance - // .analyzeImageInSingleIsolate(enteFile); - // if (result != null) { - // final resultJson = result.toJsonString(); - // _logger.info('result: $resultJson'); - // } - // FaceMlService.instance.isImageIndexRunning = false; - // } catch (e, s) { - // _logger.severe('indexing failed ', e, s); - // await showGenericErrorDialog(context: context, error: e); - // } finally { - // FaceMlService.instance.isImageIndexRunning = false; - // } - // }, - // ), + sectionOptionSpacing, MenuItemWidget( captionedTextWidget: FutureBuilder( future: FaceMLDataDB.instance.getClusteredToTotalFacesRatio(), @@ -207,25 +151,6 @@ class _FaceDebugSectionWidgetState extends State { }, ), sectionOptionSpacing, - MenuItemWidget( - captionedTextWidget: const CaptionedTextWidget( - title: "Reset feedback", - ), - pressedColor: getEnteColorScheme(context).fillFaint, - trailingIcon: Icons.chevron_right_outlined, - trailingIconIsMuted: true, - onTap: () async { - try { - await FaceMLDataDB.instance.dropFeedbackTables(); - Bus.instance.fire(PeopleChangedEvent()); - showShortToast(context, "Done"); - } catch (e, s) { - _logger.warning('reset feedback failed ', e, s); - await showGenericErrorDialog(context: context, error: e); - } - }, - ), - sectionOptionSpacing, MenuItemWidget( captionedTextWidget: const CaptionedTextWidget( title: "Check for mixed clusters", @@ -252,67 +177,6 @@ class _FaceDebugSectionWidgetState extends State { }, ), sectionOptionSpacing, - MenuItemWidget( - captionedTextWidget: const CaptionedTextWidget( - title: "Reset feedback & clusters", - ), - pressedColor: getEnteColorScheme(context).fillFaint, - trailingIcon: Icons.chevron_right_outlined, - trailingIconIsMuted: true, - alwaysShowSuccessState: true, - onTap: () async { - await showChoiceDialog( - context, - title: "Are you sure?", - body: - "You will need to again cluster all the faces. You can drop feedback if you want to return to original cluster labels", - firstButtonLabel: "Yes, confirm", - firstButtonOnTap: () async { - try { - await FaceMLDataDB.instance.resetClusterIDs(); - await FaceMLDataDB.instance.dropClustersAndPersonTable(); - Bus.instance.fire(PeopleChangedEvent()); - showShortToast(context, "Done"); - } catch (e, s) { - _logger.warning('reset feedback failed ', e, s); - await showGenericErrorDialog(context: context, error: e); - } - }, - ); - }, - ), - sectionOptionSpacing, - MenuItemWidget( - captionedTextWidget: const CaptionedTextWidget( - title: "Drop People and clusterMapping", - ), - pressedColor: getEnteColorScheme(context).fillFaint, - trailingIcon: Icons.chevron_right_outlined, - trailingIconIsMuted: true, - onTap: () async { - await showChoiceDialog( - context, - title: "Are you sure?", - body: - "This will delete the people and all respective mappings of people to clusters", - firstButtonLabel: "Yes, confirm", - firstButtonOnTap: () async { - try { - final List persons = - await PersonService.instance.getPersons(); - for (final PersonEntity p in persons) { - await PersonService.instance.deletePerson(p.remoteID); - } - Bus.instance.fire(PeopleChangedEvent()); - showShortToast(context, "Done"); - } catch (e, s) { - _logger.warning('peopleToPersonMapping remove failed ', e, s); - await showGenericErrorDialog(context: context, error: e); - } - }, - ); - }, - ), MenuItemWidget( captionedTextWidget: const CaptionedTextWidget( title: "Sync person mappings ", @@ -331,38 +195,72 @@ class _FaceDebugSectionWidgetState extends State { } }, ), - // sectionOptionSpacing, - // MenuItemWidget( - // captionedTextWidget: const CaptionedTextWidget( - // title: "Rank blurs", - // ), - // pressedColor: getEnteColorScheme(context).fillFaint, - // trailingIcon: Icons.chevron_right_outlined, - // trailingIconIsMuted: true, - // onTap: () async { - // await showChoiceDialog( - // context, - // title: "Are you sure?", - // body: - // "This will delete all clusters and put blurry faces in separate clusters per ten points.", - // firstButtonLabel: "Yes, confirm", - // firstButtonOnTap: () async { - // try { - // await ClusterFeedbackService.instance - // .createFakeClustersByBlurValue(); - // showShortToast(context, "Done"); - // } catch (e, s) { - // _logger.warning('Failed to rank faces on blur values ', e, s); - // await showGenericErrorDialog(context: context, error: e); - // } - // }, - // ); - // }, - // ), sectionOptionSpacing, MenuItemWidget( captionedTextWidget: const CaptionedTextWidget( - title: "Drop embeddings & feedback", + title: "Reset feedback", + ), + pressedColor: getEnteColorScheme(context).fillFaint, + trailingIcon: Icons.chevron_right_outlined, + trailingIconIsMuted: true, + alwaysShowSuccessState: true, + onTap: () async { + await showChoiceDialog( + context, + title: "Are you sure?", + body: + "This will drop all people and their related feedback. It will keep clustering labels and embeddings untouched.", + firstButtonLabel: "Yes, confirm", + firstButtonOnTap: () async { + try { + await FaceMLDataDB.instance.dropFeedbackTables(); + Bus.instance.fire(PeopleChangedEvent()); + showShortToast(context, "Done"); + } catch (e, s) { + _logger.warning('reset feedback failed ', e, s); + await showGenericErrorDialog(context: context, error: e); + } + }, + ); + }, + ), + sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: const CaptionedTextWidget( + title: "Reset feedback and clustering", + ), + pressedColor: getEnteColorScheme(context).fillFaint, + trailingIcon: Icons.chevron_right_outlined, + trailingIconIsMuted: true, + onTap: () async { + await showChoiceDialog( + context, + title: "Are you sure?", + body: + "This will delete all people, their related feedback and clustering labels. It will keep embeddings untouched.", + firstButtonLabel: "Yes, confirm", + firstButtonOnTap: () async { + try { + final List persons = + await PersonService.instance.getPersons(); + for (final PersonEntity p in persons) { + await PersonService.instance.deletePerson(p.remoteID); + } + await FaceMLDataDB.instance.dropClustersAndPersonTable(); + Bus.instance.fire(PeopleChangedEvent()); + showShortToast(context, "Done"); + } catch (e, s) { + _logger.warning('peopleToPersonMapping remove failed ', e, s); + await showGenericErrorDialog(context: context, error: e); + } + }, + ); + }, + ), + sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: const CaptionedTextWidget( + title: "Reset everything (embeddings)", ), pressedColor: getEnteColorScheme(context).fillFaint, trailingIcon: Icons.chevron_right_outlined, @@ -388,47 +286,6 @@ class _FaceDebugSectionWidgetState extends State { ); }, ), - if (kDebugMode) sectionOptionSpacing, - if (kDebugMode) - MenuItemWidget( - captionedTextWidget: FutureBuilder( - future: FaceMLDataDB.instance.getIndexedFileCount(), - builder: (context, snapshot) { - if (snapshot.hasData) { - return CaptionedTextWidget( - title: "Read embeddings for ${snapshot.data!} files", - ); - } - return const CaptionedTextWidget( - title: "Loading...", - ); - }, - ), - pressedColor: getEnteColorScheme(context).fillFaint, - trailingIcon: Icons.chevron_right_outlined, - trailingIconIsMuted: true, - onTap: () async { - final int totalFaces = - await FaceMLDataDB.instance.getTotalFaceCount(); - _logger.info('start reading embeddings for $totalFaces faces'); - final time = DateTime.now(); - try { - final result = await FaceMLDataDB.instance - .getFaceEmbeddingMap(maxFaces: totalFaces); - final endTime = DateTime.now(); - _logger.info( - 'Read embeddings of ${result.length} faces in ${time.difference(endTime).inSeconds} secs', - ); - showShortToast( - context, - "Read embeddings of ${result.length} faces in ${time.difference(endTime).inSeconds} secs", - ); - } catch (e, s) { - _logger.warning('read embeddings failed ', e, s); - await showGenericErrorDialog(context: context, error: e); - } - }, - ), ], ); }