face_debug_section_widget.dart 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import "dart:async";
  2. import "package:flutter/foundation.dart";
  3. import 'package:flutter/material.dart';
  4. import "package:logging/logging.dart";
  5. import "package:photos/core/event_bus.dart";
  6. import "package:photos/events/people_changed_event.dart";
  7. import "package:photos/extensions/stop_watch.dart";
  8. import "package:photos/face/db.dart";
  9. import "package:photos/face/model/person.dart";
  10. import "package:photos/services/face_ml/face_ml_service.dart";
  11. import "package:photos/services/face_ml/feedback/cluster_feedback.dart";
  12. import 'package:photos/theme/ente_theme.dart';
  13. import 'package:photos/ui/components/captioned_text_widget.dart';
  14. import 'package:photos/ui/components/expandable_menu_item_widget.dart';
  15. import 'package:photos/ui/components/menu_item_widget/menu_item_widget.dart';
  16. import 'package:photos/ui/settings/common_settings.dart';
  17. import "package:photos/utils/dialog_util.dart";
  18. import "package:photos/utils/local_settings.dart";
  19. import 'package:photos/utils/toast_util.dart';
  20. class FaceDebugSectionWidget extends StatefulWidget {
  21. const FaceDebugSectionWidget({Key? key}) : super(key: key);
  22. @override
  23. State<FaceDebugSectionWidget> createState() => _FaceDebugSectionWidgetState();
  24. }
  25. class _FaceDebugSectionWidgetState extends State<FaceDebugSectionWidget> {
  26. Timer? _timer;
  27. @override
  28. void initState() {
  29. super.initState();
  30. _timer = Timer.periodic(const Duration(seconds: 5), (timer) {
  31. setState(() {
  32. // Your state update logic here
  33. });
  34. });
  35. }
  36. @override
  37. void dispose() {
  38. _timer?.cancel();
  39. super.dispose();
  40. }
  41. @override
  42. Widget build(BuildContext context) {
  43. return ExpandableMenuItemWidget(
  44. title: "Face Beta",
  45. selectionOptionsWidget: _getSectionOptions(context),
  46. leadingIcon: Icons.bug_report_outlined,
  47. );
  48. }
  49. Widget _getSectionOptions(BuildContext context) {
  50. final Logger _logger = Logger("FaceDebugSectionWidget");
  51. return Column(
  52. children: [
  53. MenuItemWidget(
  54. captionedTextWidget: FutureBuilder<Set<int>>(
  55. future: FaceMLDataDB.instance.getIndexedFileIds(),
  56. builder: (context, snapshot) {
  57. if (snapshot.hasData) {
  58. return CaptionedTextWidget(
  59. title: LocalSettings.instance.isFaceIndexingEnabled
  60. ? "Disable Indexing (${snapshot.data!.length})"
  61. : "Enable indexing (${snapshot.data!.length})",
  62. );
  63. }
  64. return const SizedBox.shrink();
  65. },
  66. ),
  67. pressedColor: getEnteColorScheme(context).fillFaint,
  68. trailingIcon: Icons.chevron_right_outlined,
  69. trailingIconIsMuted: true,
  70. onTap: () async {
  71. try {
  72. final isEnabled =
  73. await LocalSettings.instance.toggleFaceIndexing();
  74. if (isEnabled) {
  75. FaceMlService.instance.indexAllImages().ignore();
  76. } else {
  77. FaceMlService.instance.pauseIndexing();
  78. }
  79. if (mounted) {
  80. setState(() {});
  81. }
  82. } catch (e, s) {
  83. _logger.warning('indexing failed ', e, s);
  84. await showGenericErrorDialog(context: context, error: e);
  85. }
  86. },
  87. ),
  88. MenuItemWidget(
  89. captionedTextWidget: const CaptionedTextWidget(
  90. title: "Run Clustering",
  91. ),
  92. pressedColor: getEnteColorScheme(context).fillFaint,
  93. trailingIcon: Icons.chevron_right_outlined,
  94. trailingIconIsMuted: true,
  95. onTap: () async {
  96. await FaceMlService.instance.clusterAllImages(minFaceScore: 0.75);
  97. Bus.instance.fire(PeopleChangedEvent());
  98. showShortToast(context, "Done");
  99. },
  100. ),
  101. sectionOptionSpacing,
  102. MenuItemWidget(
  103. captionedTextWidget: const CaptionedTextWidget(
  104. title: "Reset feedback & labels",
  105. ),
  106. pressedColor: getEnteColorScheme(context).fillFaint,
  107. trailingIcon: Icons.chevron_right_outlined,
  108. trailingIconIsMuted: true,
  109. onTap: () async {
  110. await FaceMLDataDB.instance.resetClusterIDs();
  111. await FaceMLDataDB.instance.dropClustersAndPeople();
  112. Bus.instance.fire(PeopleChangedEvent());
  113. showShortToast(context, "Done");
  114. },
  115. ),
  116. sectionOptionSpacing,
  117. MenuItemWidget(
  118. captionedTextWidget: const CaptionedTextWidget(
  119. title: "Drop embeddings & feedback",
  120. ),
  121. pressedColor: getEnteColorScheme(context).fillFaint,
  122. trailingIcon: Icons.chevron_right_outlined,
  123. trailingIconIsMuted: true,
  124. onTap: () async {
  125. await showChoiceDialog(
  126. context,
  127. title: "Are you sure?",
  128. body:
  129. "You will need to again re-index all the faces. You can drop feedback if you want to label again",
  130. firstButtonLabel: "Yes, confirm",
  131. firstButtonOnTap: () async {
  132. await FaceMLDataDB.instance.dropClustersAndPeople(faces: true);
  133. Bus.instance.fire(PeopleChangedEvent());
  134. showShortToast(context, "Done");
  135. },
  136. );
  137. },
  138. ),
  139. if (kDebugMode) sectionOptionSpacing,
  140. if (kDebugMode)
  141. MenuItemWidget(
  142. captionedTextWidget: const CaptionedTextWidget(
  143. title: "Pull Embeddings From Local",
  144. ),
  145. pressedColor: getEnteColorScheme(context).fillFaint,
  146. trailingIcon: Icons.chevron_right_outlined,
  147. trailingIconIsMuted: true,
  148. onTap: () async {
  149. try {
  150. final List<Person> persons =
  151. await FaceMLDataDB.instance.getPeople();
  152. final EnteWatch w = EnteWatch('feedback')..start();
  153. for (final Person p in persons) {
  154. await ClusterFeedbackService.instance
  155. .getSuggestionsUsingMean(p);
  156. w.logAndReset('suggestion calculated for ${p.attr.name}');
  157. }
  158. w.log("done with feedback");
  159. showShortToast(context, "done avg");
  160. // await FaceMLDataDB.instance.bulkInsertFaces([]);
  161. // final EnteWatch watch = EnteWatch("face_time")..start();
  162. // final results = await downloadZip();
  163. // watch.logAndReset('downloaded and de-serialized');
  164. // await FaceMLDataDB.instance.bulkInsertFaces(results);
  165. // watch.logAndReset('inserted in to db');
  166. // showShortToast(context, "Got ${results.length} results");
  167. } catch (e, s) {
  168. _logger.warning('download failed ', e, s);
  169. await showGenericErrorDialog(context: context, error: e);
  170. }
  171. // _showKeyAttributesDialog(context);
  172. },
  173. ),
  174. if (kDebugMode) sectionOptionSpacing,
  175. if (kDebugMode)
  176. MenuItemWidget(
  177. captionedTextWidget: FutureBuilder<Set<int>>(
  178. future: FaceMLDataDB.instance.getIndexedFileIds(),
  179. builder: (context, snapshot) {
  180. if (snapshot.hasData) {
  181. return CaptionedTextWidget(
  182. title: "Read embeddings for ${snapshot.data!.length} files",
  183. );
  184. }
  185. return const CaptionedTextWidget(
  186. title: "Loading...",
  187. );
  188. },
  189. ),
  190. pressedColor: getEnteColorScheme(context).fillFaint,
  191. trailingIcon: Icons.chevron_right_outlined,
  192. trailingIconIsMuted: true,
  193. onTap: () async {
  194. final EnteWatch watch = EnteWatch("read_embeddings")..start();
  195. final result = await FaceMLDataDB.instance.getFaceEmbeddingMap();
  196. watch.logAndReset('read embeddings ${result.length} ');
  197. showShortToast(
  198. context,
  199. "Done in ${watch.elapsed.inSeconds} secs",
  200. );
  201. },
  202. ),
  203. ],
  204. );
  205. }
  206. }