object_detection_service.dart 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import "dart:isolate";
  2. import "dart:typed_data";
  3. import "package:logging/logging.dart";
  4. import "package:photos/services/object_detection/models/predictions.dart";
  5. import 'package:photos/services/object_detection/models/recognition.dart';
  6. import 'package:photos/services/object_detection/tflite/cocossd_classifier.dart';
  7. import "package:photos/services/object_detection/tflite/mobilenet_classifier.dart";
  8. import "package:photos/services/object_detection/tflite/scene_classifier.dart";
  9. import "package:photos/services/object_detection/utils/isolate_utils.dart";
  10. class ObjectDetectionService {
  11. static const scoreThreshold = 0.5;
  12. final _logger = Logger("ObjectDetectionService");
  13. late CocoSSDClassifier _objectClassifier;
  14. late MobileNetClassifier _mobileNetClassifier;
  15. late SceneClassifier _sceneClassifier;
  16. late IsolateUtils _isolateUtils;
  17. ObjectDetectionService._privateConstructor();
  18. Future<void> init() async {
  19. _isolateUtils = IsolateUtils();
  20. await _isolateUtils.start();
  21. try {
  22. _objectClassifier = CocoSSDClassifier();
  23. } catch (e, s) {
  24. _logger.severe("Could not initialize cocossd", e, s);
  25. }
  26. try {
  27. _mobileNetClassifier = MobileNetClassifier();
  28. } catch (e, s) {
  29. _logger.severe("Could not initialize mobilenet", e, s);
  30. }
  31. try {
  32. _sceneClassifier = SceneClassifier();
  33. } catch (e, s) {
  34. _logger.severe("Could not initialize sceneclassifier", e, s);
  35. }
  36. }
  37. static ObjectDetectionService instance =
  38. ObjectDetectionService._privateConstructor();
  39. Future<List<String>> predict(Uint8List bytes) async {
  40. try {
  41. final results = <String>{};
  42. results.addAll(await _getObjects(bytes));
  43. results.addAll(await _getMobileNetResults(bytes));
  44. results.addAll(await _getSceneResults(bytes));
  45. return results.toList();
  46. } catch (e, s) {
  47. _logger.severe(e, s);
  48. rethrow;
  49. }
  50. }
  51. Future<List<String>> _getObjects(Uint8List bytes) async {
  52. try {
  53. final isolateData = IsolateData(
  54. bytes,
  55. _objectClassifier.interpreter.address,
  56. _objectClassifier.labels,
  57. ClassifierType.cocossd,
  58. );
  59. return _getPredictions(isolateData);
  60. } catch (e, s) {
  61. _logger.severe("Could not run cocossd", e, s);
  62. }
  63. return [];
  64. }
  65. Future<List<String>> _getMobileNetResults(Uint8List bytes) async {
  66. try {
  67. final isolateData = IsolateData(
  68. bytes,
  69. _mobileNetClassifier.interpreter.address,
  70. _mobileNetClassifier.labels,
  71. ClassifierType.mobilenet,
  72. );
  73. return _getPredictions(isolateData);
  74. } catch (e, s) {
  75. _logger.severe("Could not run mobilenet", e, s);
  76. }
  77. return [];
  78. }
  79. Future<List<String>> _getSceneResults(Uint8List bytes) async {
  80. try {
  81. final isolateData = IsolateData(
  82. bytes,
  83. _sceneClassifier.interpreter.address,
  84. _sceneClassifier.labels,
  85. ClassifierType.scenes,
  86. );
  87. return _getPredictions(isolateData);
  88. } catch (e, s) {
  89. _logger.severe("Could not run scene detection", e, s);
  90. }
  91. return [];
  92. }
  93. Future<List<String>> _getPredictions(IsolateData isolateData) async {
  94. final predictions = await _inference(isolateData);
  95. final Set<String> results = {};
  96. for (final Recognition result in predictions.recognitions) {
  97. if (result.score > scoreThreshold) {
  98. results.add(result.label);
  99. }
  100. }
  101. _logger.info(
  102. "Time taken for " +
  103. isolateData.type.toString() +
  104. ": " +
  105. predictions.stats.totalElapsedTime.toString() +
  106. "ms",
  107. );
  108. return results.toList();
  109. }
  110. /// Runs inference in another isolate
  111. Future<Predictions> _inference(IsolateData isolateData) async {
  112. final responsePort = ReceivePort();
  113. _isolateUtils.sendPort.send(
  114. isolateData..responsePort = responsePort.sendPort,
  115. );
  116. return await responsePort.first;
  117. }
  118. }