Hello ducky (#1382)
|
@ -3,7 +3,7 @@
|
|||
package="io.ente.photos">
|
||||
<application android:name="${applicationName}"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/launcher_icon"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:allowBackup="false"
|
||||
|
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 70 B After Width: | Height: | Size: 69 B |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 70 B After Width: | Height: | Size: 69 B |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 69 B |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 69 B |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_foreground"
|
||||
android:inset="26%" />
|
||||
</foreground>
|
||||
</adaptive-icon>
|
|
@ -2,5 +2,4 @@
|
|||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 5 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 11 KiB |
|
@ -4,6 +4,7 @@
|
|||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
<item name="android:windowSplashScreenBackground">#000000</item>
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
<item name="android:windowSplashScreenBackground">#ffffff</item>
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||
|
|
BIN
assets/ente.png
Normal file
After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 14 KiB |
BIN
assets/launcher_icon/adaptive_icon.png
Normal file
After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 9 KiB |
BIN
assets/launcher_icon/icon.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
assets/splash-icon-dark.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
assets/splash-icon-light.png
Normal file
After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB |
|
@ -1,8 +1,6 @@
|
|||
PODS:
|
||||
- background_fetch (1.1.6):
|
||||
- Flutter
|
||||
- camera_avfoundation (0.0.1):
|
||||
- Flutter
|
||||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- ReachabilitySwift
|
||||
|
@ -165,8 +163,6 @@ PODS:
|
|||
- FMDB (>= 2.7.5)
|
||||
- tflite_flutter (0.1.0):
|
||||
- Flutter
|
||||
- tflite_flutter_helper (0.0.1):
|
||||
- Flutter
|
||||
- Toast (4.0.0)
|
||||
- uni_links (0.0.1):
|
||||
- Flutter
|
||||
|
@ -182,7 +178,6 @@ PODS:
|
|||
|
||||
DEPENDENCIES:
|
||||
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
|
||||
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- device_info (from `.symlinks/plugins/device_info/ios`)
|
||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||
|
@ -214,7 +209,6 @@ DEPENDENCIES:
|
|||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
- tflite_flutter (from `.symlinks/plugins/tflite_flutter/ios`)
|
||||
- tflite_flutter_helper (from `.symlinks/plugins/tflite_flutter_helper/ios`)
|
||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
|
||||
|
@ -246,8 +240,6 @@ SPEC REPOS:
|
|||
EXTERNAL SOURCES:
|
||||
background_fetch:
|
||||
:path: ".symlinks/plugins/background_fetch/ios"
|
||||
camera_avfoundation:
|
||||
:path: ".symlinks/plugins/camera_avfoundation/ios"
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
device_info:
|
||||
|
@ -310,8 +302,6 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/sqflite/ios"
|
||||
tflite_flutter:
|
||||
:path: ".symlinks/plugins/tflite_flutter/ios"
|
||||
tflite_flutter_helper:
|
||||
:path: ".symlinks/plugins/tflite_flutter_helper/ios"
|
||||
uni_links:
|
||||
:path: ".symlinks/plugins/uni_links/ios"
|
||||
url_launcher_ios:
|
||||
|
@ -325,7 +315,6 @@ EXTERNAL SOURCES:
|
|||
|
||||
SPEC CHECKSUMS:
|
||||
background_fetch: bc9b44b0bf8b434e282a2ac9be8662800a0296ed
|
||||
camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb
|
||||
connectivity_plus: 53efb943fc2882c8512d84c45707bcabc4c36076
|
||||
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
|
||||
Firebase: bd152f0f3d278c4060c5c71359db08ebcfd5a3e2
|
||||
|
@ -375,7 +364,6 @@ SPEC CHECKSUMS:
|
|||
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
|
||||
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
|
||||
tflite_flutter: 9157a660578930a99728974f247369af1c3595d5
|
||||
tflite_flutter_helper: 543b46b6bd064b21c92ea6e54bc0b29f1ce74cb5
|
||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
|
|
|
@ -276,7 +276,6 @@
|
|||
"${BUILT_PRODUCTS_DIR}/SentryPrivate/SentryPrivate.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/Toast/Toast.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/background_fetch/background_fetch.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/camera_avfoundation/camera_avfoundation.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/device_info/device_info.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/fk_user_agent/fk_user_agent.framework",
|
||||
|
@ -307,7 +306,6 @@
|
|||
"${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/tflite_flutter/tflite_flutter.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/tflite_flutter_helper/tflite_flutter_helper.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/uni_links/uni_links.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework",
|
||||
|
@ -333,7 +331,6 @@
|
|||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SentryPrivate.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/background_fetch.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/camera_avfoundation.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fk_user_agent.framework",
|
||||
|
@ -364,7 +361,6 @@
|
|||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/tflite_flutter.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/tflite_flutter_helper.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/uni_links.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework",
|
||||
|
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 831 B After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 831 B After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 6 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 6 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 69 B |
Before Width: | Height: | Size: 70 B After Width: | Height: | Size: 69 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 38 KiB |
|
@ -64,10 +64,10 @@
|
|||
</dict>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>FLTEnableImpeller</key>
|
||||
<false />
|
||||
<key>FLTEnableWideGamut</key>
|
||||
<false/>
|
||||
<key>FLTEnableImpeller</key>
|
||||
<false/>
|
||||
<key>FLTEnableWideGamut</key>
|
||||
<false/>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>Please allow ente to lock itself with FaceID or TouchID</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
|
|
|
@ -29,7 +29,7 @@ import 'package:photos/services/local_file_update_service.dart';
|
|||
import 'package:photos/services/local_sync_service.dart';
|
||||
import "package:photos/services/location_service.dart";
|
||||
import 'package:photos/services/memories_service.dart';
|
||||
import "package:photos/services/object_detection/object_detection_service.dart";
|
||||
// import "package:photos/services/object_detection/object_detection_service.dart";
|
||||
import 'package:photos/services/push_service.dart';
|
||||
import 'package:photos/services/remote_sync_service.dart';
|
||||
import 'package:photos/services/search_service.dart';
|
||||
|
@ -190,9 +190,9 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
|
|||
// Can not including existing tf/ml binaries as they are not being built
|
||||
// from source.
|
||||
// See https://gitlab.com/fdroid/fdroiddata/-/merge_requests/12671#note_1294346819
|
||||
if (!UpdateService.instance.isFdroidFlavor()) {
|
||||
unawaited(ObjectDetectionService.instance.init());
|
||||
}
|
||||
// if (!UpdateService.instance.isFdroidFlavor()) {
|
||||
// unawaited(ObjectDetectionService.instance.init());
|
||||
// }
|
||||
|
||||
_logger.info("Initialization done");
|
||||
}
|
||||
|
|
|
@ -1,157 +1,157 @@
|
|||
import "dart:isolate";
|
||||
import "dart:math";
|
||||
import "dart:typed_data";
|
||||
// import "dart:isolate";
|
||||
// import "dart:math";
|
||||
// import "dart:typed_data";
|
||||
|
||||
import "package:logging/logging.dart";
|
||||
import "package:photos/services/object_detection/models/predictions.dart";
|
||||
import 'package:photos/services/object_detection/models/recognition.dart';
|
||||
import 'package:photos/services/object_detection/tflite/cocossd_classifier.dart';
|
||||
import "package:photos/services/object_detection/tflite/mobilenet_classifier.dart";
|
||||
import "package:photos/services/object_detection/tflite/scene_classifier.dart";
|
||||
import "package:photos/services/object_detection/utils/isolate_utils.dart";
|
||||
// import "package:logging/logging.dart";
|
||||
// import "package:photos/services/object_detection/models/predictions.dart";
|
||||
// import 'package:photos/services/object_detection/models/recognition.dart';
|
||||
// import 'package:photos/services/object_detection/tflite/cocossd_classifier.dart';
|
||||
// import "package:photos/services/object_detection/tflite/mobilenet_classifier.dart";
|
||||
// import "package:photos/services/object_detection/tflite/scene_classifier.dart";
|
||||
// import "package:photos/services/object_detection/utils/isolate_utils.dart";
|
||||
|
||||
class ObjectDetectionService {
|
||||
static const scoreThreshold = 0.35;
|
||||
// class ObjectDetectionService {
|
||||
// static const scoreThreshold = 0.35;
|
||||
|
||||
final _logger = Logger("ObjectDetectionService");
|
||||
// final _logger = Logger("ObjectDetectionService");
|
||||
|
||||
late CocoSSDClassifier _objectClassifier;
|
||||
late MobileNetClassifier _mobileNetClassifier;
|
||||
late SceneClassifier _sceneClassifier;
|
||||
// late CocoSSDClassifier _objectClassifier;
|
||||
// late MobileNetClassifier _mobileNetClassifier;
|
||||
// late SceneClassifier _sceneClassifier;
|
||||
|
||||
late IsolateUtils _isolateUtils;
|
||||
// late IsolateUtils _isolateUtils;
|
||||
|
||||
ObjectDetectionService._privateConstructor();
|
||||
bool inInitiated = false;
|
||||
// ObjectDetectionService._privateConstructor();
|
||||
// bool inInitiated = false;
|
||||
|
||||
Future<void> init() async {
|
||||
_isolateUtils = IsolateUtils();
|
||||
await _isolateUtils.start();
|
||||
try {
|
||||
_objectClassifier = CocoSSDClassifier();
|
||||
} catch (e, s) {
|
||||
_logger.severe("Could not initialize cocossd", e, s);
|
||||
}
|
||||
try {
|
||||
_mobileNetClassifier = MobileNetClassifier();
|
||||
} catch (e, s) {
|
||||
_logger.severe("Could not initialize mobilenet", e, s);
|
||||
}
|
||||
try {
|
||||
_sceneClassifier = SceneClassifier();
|
||||
} catch (e, s) {
|
||||
_logger.severe("Could not initialize sceneclassifier", e, s);
|
||||
}
|
||||
inInitiated = true;
|
||||
}
|
||||
// Future<void> init() async {
|
||||
// _isolateUtils = IsolateUtils();
|
||||
// await _isolateUtils.start();
|
||||
// try {
|
||||
// _objectClassifier = CocoSSDClassifier();
|
||||
// } catch (e, s) {
|
||||
// _logger.severe("Could not initialize cocossd", e, s);
|
||||
// }
|
||||
// try {
|
||||
// _mobileNetClassifier = MobileNetClassifier();
|
||||
// } catch (e, s) {
|
||||
// _logger.severe("Could not initialize mobilenet", e, s);
|
||||
// }
|
||||
// try {
|
||||
// _sceneClassifier = SceneClassifier();
|
||||
// } catch (e, s) {
|
||||
// _logger.severe("Could not initialize sceneclassifier", e, s);
|
||||
// }
|
||||
// inInitiated = true;
|
||||
// }
|
||||
|
||||
static ObjectDetectionService instance =
|
||||
ObjectDetectionService._privateConstructor();
|
||||
// static ObjectDetectionService instance =
|
||||
// ObjectDetectionService._privateConstructor();
|
||||
|
||||
Future<Map<String, double>> predict(Uint8List bytes) async {
|
||||
try {
|
||||
if (!inInitiated) {
|
||||
return Future.error("ObjectDetectionService init is not completed");
|
||||
}
|
||||
final results = <String, double>{};
|
||||
final methods = [_getObjects, _getMobileNetResults, _getSceneResults];
|
||||
// Future<Map<String, double>> predict(Uint8List bytes) async {
|
||||
// try {
|
||||
// if (!inInitiated) {
|
||||
// return Future.error("ObjectDetectionService init is not completed");
|
||||
// }
|
||||
// final results = <String, double>{};
|
||||
// final methods = [_getObjects, _getMobileNetResults, _getSceneResults];
|
||||
|
||||
for (var method in methods) {
|
||||
final methodResults = await method(bytes);
|
||||
methodResults.forEach((key, value) {
|
||||
results.update(
|
||||
key,
|
||||
(existingValue) => max(existingValue, value),
|
||||
ifAbsent: () => value,
|
||||
);
|
||||
});
|
||||
}
|
||||
return results;
|
||||
} catch (e, s) {
|
||||
_logger.severe(e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
// for (var method in methods) {
|
||||
// final methodResults = await method(bytes);
|
||||
// methodResults.forEach((key, value) {
|
||||
// results.update(
|
||||
// key,
|
||||
// (existingValue) => max(existingValue, value),
|
||||
// ifAbsent: () => value,
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
// return results;
|
||||
// } catch (e, s) {
|
||||
// _logger.severe(e, s);
|
||||
// rethrow;
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<Map<String, double>> _getObjects(Uint8List bytes) async {
|
||||
try {
|
||||
final isolateData = IsolateData(
|
||||
bytes,
|
||||
_objectClassifier.interpreter.address,
|
||||
_objectClassifier.labels,
|
||||
ClassifierType.cocossd,
|
||||
);
|
||||
return _getPredictions(isolateData);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Could not run cocossd", e, s);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
// Future<Map<String, double>> _getObjects(Uint8List bytes) async {
|
||||
// try {
|
||||
// final isolateData = IsolateData(
|
||||
// bytes,
|
||||
// _objectClassifier.interpreter.address,
|
||||
// _objectClassifier.labels,
|
||||
// ClassifierType.cocossd,
|
||||
// );
|
||||
// return _getPredictions(isolateData);
|
||||
// } catch (e, s) {
|
||||
// _logger.severe("Could not run cocossd", e, s);
|
||||
// }
|
||||
// return {};
|
||||
// }
|
||||
|
||||
Future<Map<String, double>> _getMobileNetResults(Uint8List bytes) async {
|
||||
try {
|
||||
final isolateData = IsolateData(
|
||||
bytes,
|
||||
_mobileNetClassifier.interpreter.address,
|
||||
_mobileNetClassifier.labels,
|
||||
ClassifierType.mobilenet,
|
||||
);
|
||||
return _getPredictions(isolateData);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Could not run mobilenet", e, s);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
// Future<Map<String, double>> _getMobileNetResults(Uint8List bytes) async {
|
||||
// try {
|
||||
// final isolateData = IsolateData(
|
||||
// bytes,
|
||||
// _mobileNetClassifier.interpreter.address,
|
||||
// _mobileNetClassifier.labels,
|
||||
// ClassifierType.mobilenet,
|
||||
// );
|
||||
// return _getPredictions(isolateData);
|
||||
// } catch (e, s) {
|
||||
// _logger.severe("Could not run mobilenet", e, s);
|
||||
// }
|
||||
// return {};
|
||||
// }
|
||||
|
||||
Future<Map<String, double>> _getSceneResults(Uint8List bytes) async {
|
||||
try {
|
||||
final isolateData = IsolateData(
|
||||
bytes,
|
||||
_sceneClassifier.interpreter.address,
|
||||
_sceneClassifier.labels,
|
||||
ClassifierType.scenes,
|
||||
);
|
||||
return _getPredictions(isolateData);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Could not run scene detection", e, s);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
// Future<Map<String, double>> _getSceneResults(Uint8List bytes) async {
|
||||
// try {
|
||||
// final isolateData = IsolateData(
|
||||
// bytes,
|
||||
// _sceneClassifier.interpreter.address,
|
||||
// _sceneClassifier.labels,
|
||||
// ClassifierType.scenes,
|
||||
// );
|
||||
// return _getPredictions(isolateData);
|
||||
// } catch (e, s) {
|
||||
// _logger.severe("Could not run scene detection", e, s);
|
||||
// }
|
||||
// return {};
|
||||
// }
|
||||
|
||||
Future<Map<String, double>> _getPredictions(IsolateData isolateData) async {
|
||||
final predictions = await _inference(isolateData);
|
||||
final Map<String, double> results = {};
|
||||
// Future<Map<String, double>> _getPredictions(IsolateData isolateData) async {
|
||||
// final predictions = await _inference(isolateData);
|
||||
// final Map<String, double> results = {};
|
||||
|
||||
if (predictions.error == null) {
|
||||
for (final Recognition result in predictions.recognitions!) {
|
||||
if (result.score > scoreThreshold) {
|
||||
// Update the result score only if it's higher than the current score
|
||||
if (!results.containsKey(result.label) ||
|
||||
results[result.label]! < result.score) {
|
||||
results[result.label] = result.score;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (predictions.error == null) {
|
||||
// for (final Recognition result in predictions.recognitions!) {
|
||||
// if (result.score > scoreThreshold) {
|
||||
// // Update the result score only if it's higher than the current score
|
||||
// if (!results.containsKey(result.label) ||
|
||||
// results[result.label]! < result.score) {
|
||||
// results[result.label] = result.score;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
_logger.info(
|
||||
"Time taken for ${isolateData.type}: ${predictions.stats!.totalElapsedTime}ms",
|
||||
);
|
||||
} else {
|
||||
_logger.severe(
|
||||
"Error while fetching predictions for ${isolateData.type}",
|
||||
predictions.error,
|
||||
);
|
||||
}
|
||||
// _logger.info(
|
||||
// "Time taken for ${isolateData.type}: ${predictions.stats!.totalElapsedTime}ms",
|
||||
// );
|
||||
// } else {
|
||||
// _logger.severe(
|
||||
// "Error while fetching predictions for ${isolateData.type}",
|
||||
// predictions.error,
|
||||
// );
|
||||
// }
|
||||
|
||||
return results;
|
||||
}
|
||||
// return results;
|
||||
// }
|
||||
|
||||
/// Runs inference in another isolate
|
||||
Future<Predictions> _inference(IsolateData isolateData) async {
|
||||
final responsePort = ReceivePort();
|
||||
_isolateUtils.sendPort.send(
|
||||
isolateData..responsePort = responsePort.sendPort,
|
||||
);
|
||||
return await responsePort.first;
|
||||
}
|
||||
}
|
||||
// /// Runs inference in another isolate
|
||||
// Future<Predictions> _inference(IsolateData isolateData) async {
|
||||
// final responsePort = ReceivePort();
|
||||
// _isolateUtils.sendPort.send(
|
||||
// isolateData..responsePort = responsePort.sendPort,
|
||||
// );
|
||||
// return await responsePort.first;
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1,89 +1,89 @@
|
|||
import "dart:math";
|
||||
// import "dart:math";
|
||||
|
||||
import 'package:image/image.dart' as image_lib;
|
||||
import "package:logging/logging.dart";
|
||||
import "package:photos/services/object_detection/models/predictions.dart";
|
||||
import "package:tflite_flutter/tflite_flutter.dart";
|
||||
import "package:tflite_flutter_helper/tflite_flutter_helper.dart";
|
||||
// import 'package:image/image.dart' as image_lib;
|
||||
// import "package:logging/logging.dart";
|
||||
// import "package:photos/services/object_detection/models/predictions.dart";
|
||||
// import "package:tflite_flutter/tflite_flutter.dart";
|
||||
// import "package:tflite_flutter_helper/tflite_flutter_helper.dart";
|
||||
|
||||
abstract class Classifier {
|
||||
// Path to the model
|
||||
String get modelPath;
|
||||
// abstract class Classifier {
|
||||
// // Path to the model
|
||||
// String get modelPath;
|
||||
|
||||
// Path to the labels
|
||||
String get labelPath;
|
||||
// // Path to the labels
|
||||
// String get labelPath;
|
||||
|
||||
// Input size expected by the model (for eg. width = height = 224)
|
||||
int get inputSize;
|
||||
// // Input size expected by the model (for eg. width = height = 224)
|
||||
// int get inputSize;
|
||||
|
||||
// Logger implementation for the specific classifier
|
||||
Logger get logger;
|
||||
// // Logger implementation for the specific classifier
|
||||
// Logger get logger;
|
||||
|
||||
Predictions? predict(image_lib.Image image);
|
||||
// Predictions? predict(image_lib.Image image);
|
||||
|
||||
/// Instance of Interpreter
|
||||
late Interpreter _interpreter;
|
||||
// /// Instance of Interpreter
|
||||
// late Interpreter _interpreter;
|
||||
|
||||
/// Labels file loaded as list
|
||||
late List<String> _labels;
|
||||
// /// Labels file loaded as list
|
||||
// late List<String> _labels;
|
||||
|
||||
/// Shapes of output tensors
|
||||
late List<List<int>> _outputShapes;
|
||||
// /// Shapes of output tensors
|
||||
// late List<List<int>> _outputShapes;
|
||||
|
||||
/// Types of output tensors
|
||||
late List<TfLiteType> _outputTypes;
|
||||
// /// Types of output tensors
|
||||
// late List<TfLiteType> _outputTypes;
|
||||
|
||||
/// Gets the interpreter instance
|
||||
Interpreter get interpreter => _interpreter;
|
||||
// /// Gets the interpreter instance
|
||||
// Interpreter get interpreter => _interpreter;
|
||||
|
||||
/// Gets the loaded labels
|
||||
List<String> get labels => _labels;
|
||||
// /// Gets the loaded labels
|
||||
// List<String> get labels => _labels;
|
||||
|
||||
/// Gets the output shapes
|
||||
List<List<int>> get outputShapes => _outputShapes;
|
||||
// /// Gets the output shapes
|
||||
// List<List<int>> get outputShapes => _outputShapes;
|
||||
|
||||
/// Gets the output types
|
||||
List<TfLiteType> get outputTypes => _outputTypes;
|
||||
// /// Gets the output types
|
||||
// List<TfLiteType> get outputTypes => _outputTypes;
|
||||
|
||||
/// Loads interpreter from asset
|
||||
void loadModel(Interpreter? interpreter) async {
|
||||
try {
|
||||
_interpreter = interpreter ??
|
||||
await Interpreter.fromAsset(
|
||||
modelPath,
|
||||
options: InterpreterOptions()..threads = 4,
|
||||
);
|
||||
final outputTensors = _interpreter.getOutputTensors();
|
||||
_outputShapes = [];
|
||||
_outputTypes = [];
|
||||
for (var tensor in outputTensors) {
|
||||
_outputShapes.add(tensor.shape);
|
||||
_outputTypes.add(tensor.type);
|
||||
}
|
||||
logger.info("Interpreter initialized");
|
||||
} catch (e, s) {
|
||||
logger.severe("Error while creating interpreter", e, s);
|
||||
}
|
||||
}
|
||||
// /// Loads interpreter from asset
|
||||
// void loadModel(Interpreter? interpreter) async {
|
||||
// try {
|
||||
// _interpreter = interpreter ??
|
||||
// await Interpreter.fromAsset(
|
||||
// modelPath,
|
||||
// options: InterpreterOptions()..threads = 4,
|
||||
// );
|
||||
// final outputTensors = _interpreter.getOutputTensors();
|
||||
// _outputShapes = [];
|
||||
// _outputTypes = [];
|
||||
// for (var tensor in outputTensors) {
|
||||
// _outputShapes.add(tensor.shape);
|
||||
// _outputTypes.add(tensor.type);
|
||||
// }
|
||||
// logger.info("Interpreter initialized");
|
||||
// } catch (e, s) {
|
||||
// logger.severe("Error while creating interpreter", e, s);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Loads labels from assets
|
||||
void loadLabels(List<String>? labels) async {
|
||||
try {
|
||||
_labels = labels ?? await FileUtil.loadLabels(labelPath);
|
||||
logger.info("Labels initialized");
|
||||
} catch (e, s) {
|
||||
logger.severe("Error while loading labels", e, s);
|
||||
}
|
||||
}
|
||||
// /// Loads labels from assets
|
||||
// void loadLabels(List<String>? labels) async {
|
||||
// try {
|
||||
// _labels = labels ?? await FileUtil.loadLabels(labelPath);
|
||||
// logger.info("Labels initialized");
|
||||
// } catch (e, s) {
|
||||
// logger.severe("Error while loading labels", e, s);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Pre-process the image
|
||||
TensorImage getProcessedImage(TensorImage inputImage) {
|
||||
final padSize = max(inputImage.height, inputImage.width);
|
||||
final imageProcessor = ImageProcessorBuilder()
|
||||
.add(ResizeWithCropOrPadOp(padSize, padSize))
|
||||
.add(ResizeOp(inputSize, inputSize, ResizeMethod.BILINEAR))
|
||||
.build();
|
||||
inputImage = imageProcessor.process(inputImage);
|
||||
return inputImage;
|
||||
}
|
||||
}
|
||||
// /// Pre-process the image
|
||||
// TensorImage getProcessedImage(TensorImage inputImage) {
|
||||
// final padSize = max(inputImage.height, inputImage.width);
|
||||
// final imageProcessor = ImageProcessorBuilder()
|
||||
// .add(ResizeWithCropOrPadOp(padSize, padSize))
|
||||
// .add(ResizeOp(inputSize, inputSize, ResizeMethod.BILINEAR))
|
||||
// .build();
|
||||
// inputImage = imageProcessor.process(inputImage);
|
||||
// return inputImage;
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1,115 +1,115 @@
|
|||
import 'dart:math';
|
||||
// import 'dart:math';
|
||||
|
||||
import 'package:image/image.dart' as image_lib;
|
||||
import "package:logging/logging.dart";
|
||||
import 'package:photos/services/object_detection/models/predictions.dart';
|
||||
import 'package:photos/services/object_detection/models/recognition.dart';
|
||||
import "package:photos/services/object_detection/models/stats.dart";
|
||||
import "package:photos/services/object_detection/tflite/classifier.dart";
|
||||
import "package:tflite_flutter/tflite_flutter.dart";
|
||||
import "package:tflite_flutter_helper/tflite_flutter_helper.dart";
|
||||
// import 'package:image/image.dart' as image_lib;
|
||||
// import "package:logging/logging.dart";
|
||||
// import 'package:photos/services/object_detection/models/predictions.dart';
|
||||
// import 'package:photos/services/object_detection/models/recognition.dart';
|
||||
// import "package:photos/services/object_detection/models/stats.dart";
|
||||
// import "package:photos/services/object_detection/tflite/classifier.dart";
|
||||
// import "package:tflite_flutter/tflite_flutter.dart";
|
||||
// import "package:tflite_flutter_helper/tflite_flutter_helper.dart";
|
||||
|
||||
/// Classifier
|
||||
class CocoSSDClassifier extends Classifier {
|
||||
static final _logger = Logger("CocoSSDClassifier");
|
||||
static const double threshold = 0.4;
|
||||
// /// Classifier
|
||||
// class CocoSSDClassifier extends Classifier {
|
||||
// static final _logger = Logger("CocoSSDClassifier");
|
||||
// static const double threshold = 0.4;
|
||||
|
||||
@override
|
||||
String get modelPath => "models/cocossd/model.tflite";
|
||||
// @override
|
||||
// String get modelPath => "models/cocossd/model.tflite";
|
||||
|
||||
@override
|
||||
String get labelPath => "assets/models/cocossd/labels.txt";
|
||||
// @override
|
||||
// String get labelPath => "assets/models/cocossd/labels.txt";
|
||||
|
||||
@override
|
||||
int get inputSize => 300;
|
||||
// @override
|
||||
// int get inputSize => 300;
|
||||
|
||||
@override
|
||||
Logger get logger => _logger;
|
||||
// @override
|
||||
// Logger get logger => _logger;
|
||||
|
||||
static const int numResults = 10;
|
||||
// static const int numResults = 10;
|
||||
|
||||
CocoSSDClassifier({
|
||||
Interpreter? interpreter,
|
||||
List<String>? labels,
|
||||
}) {
|
||||
loadModel(interpreter);
|
||||
loadLabels(labels);
|
||||
}
|
||||
// CocoSSDClassifier({
|
||||
// Interpreter? interpreter,
|
||||
// List<String>? labels,
|
||||
// }) {
|
||||
// loadModel(interpreter);
|
||||
// loadLabels(labels);
|
||||
// }
|
||||
|
||||
@override
|
||||
Predictions? predict(image_lib.Image image) {
|
||||
final predictStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
// @override
|
||||
// Predictions? predict(image_lib.Image image) {
|
||||
// final predictStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
final preProcessStart = DateTime.now().millisecondsSinceEpoch;
|
||||
// final preProcessStart = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
// Create TensorImage from image
|
||||
TensorImage inputImage = TensorImage.fromImage(image);
|
||||
// // Create TensorImage from image
|
||||
// TensorImage inputImage = TensorImage.fromImage(image);
|
||||
|
||||
// Pre-process TensorImage
|
||||
inputImage = getProcessedImage(inputImage);
|
||||
// // Pre-process TensorImage
|
||||
// inputImage = getProcessedImage(inputImage);
|
||||
|
||||
final preProcessElapsedTime =
|
||||
DateTime.now().millisecondsSinceEpoch - preProcessStart;
|
||||
// final preProcessElapsedTime =
|
||||
// DateTime.now().millisecondsSinceEpoch - preProcessStart;
|
||||
|
||||
// TensorBuffers for output tensors
|
||||
final outputLocations = TensorBufferFloat(outputShapes[0]);
|
||||
final outputClasses = TensorBufferFloat(outputShapes[1]);
|
||||
final outputScores = TensorBufferFloat(outputShapes[2]);
|
||||
final numLocations = TensorBufferFloat(outputShapes[3]);
|
||||
// // TensorBuffers for output tensors
|
||||
// final outputLocations = TensorBufferFloat(outputShapes[0]);
|
||||
// final outputClasses = TensorBufferFloat(outputShapes[1]);
|
||||
// final outputScores = TensorBufferFloat(outputShapes[2]);
|
||||
// final numLocations = TensorBufferFloat(outputShapes[3]);
|
||||
|
||||
// Inputs object for runForMultipleInputs
|
||||
// Use [TensorImage.buffer] or [TensorBuffer.buffer] to pass by reference
|
||||
final inputs = [inputImage.buffer];
|
||||
// // Inputs object for runForMultipleInputs
|
||||
// // Use [TensorImage.buffer] or [TensorBuffer.buffer] to pass by reference
|
||||
// final inputs = [inputImage.buffer];
|
||||
|
||||
// Outputs map
|
||||
final outputs = {
|
||||
0: outputLocations.buffer,
|
||||
1: outputClasses.buffer,
|
||||
2: outputScores.buffer,
|
||||
3: numLocations.buffer,
|
||||
};
|
||||
// // Outputs map
|
||||
// final outputs = {
|
||||
// 0: outputLocations.buffer,
|
||||
// 1: outputClasses.buffer,
|
||||
// 2: outputScores.buffer,
|
||||
// 3: numLocations.buffer,
|
||||
// };
|
||||
|
||||
final inferenceTimeStart = DateTime.now().millisecondsSinceEpoch;
|
||||
// final inferenceTimeStart = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
// run inference
|
||||
interpreter.runForMultipleInputs(inputs, outputs);
|
||||
// // run inference
|
||||
// interpreter.runForMultipleInputs(inputs, outputs);
|
||||
|
||||
final inferenceTimeElapsed =
|
||||
DateTime.now().millisecondsSinceEpoch - inferenceTimeStart;
|
||||
// final inferenceTimeElapsed =
|
||||
// DateTime.now().millisecondsSinceEpoch - inferenceTimeStart;
|
||||
|
||||
// Maximum number of results to show
|
||||
final resultsCount = min(numResults, numLocations.getIntValue(0));
|
||||
// // Maximum number of results to show
|
||||
// final resultsCount = min(numResults, numLocations.getIntValue(0));
|
||||
|
||||
// Using labelOffset = 1 as ??? at index 0
|
||||
const labelOffset = 1;
|
||||
// // Using labelOffset = 1 as ??? at index 0
|
||||
// const labelOffset = 1;
|
||||
|
||||
final recognitions = <Recognition>[];
|
||||
// final recognitions = <Recognition>[];
|
||||
|
||||
for (int i = 0; i < resultsCount; i++) {
|
||||
// Prediction score
|
||||
final score = outputScores.getDoubleValue(i);
|
||||
// for (int i = 0; i < resultsCount; i++) {
|
||||
// // Prediction score
|
||||
// final score = outputScores.getDoubleValue(i);
|
||||
|
||||
// Label string
|
||||
final labelIndex = outputClasses.getIntValue(i) + labelOffset;
|
||||
final label = labels.elementAt(labelIndex);
|
||||
// // Label string
|
||||
// final labelIndex = outputClasses.getIntValue(i) + labelOffset;
|
||||
// final label = labels.elementAt(labelIndex);
|
||||
|
||||
if (score > threshold) {
|
||||
recognitions.add(
|
||||
Recognition(i, label, score),
|
||||
);
|
||||
}
|
||||
}
|
||||
// if (score > threshold) {
|
||||
// recognitions.add(
|
||||
// Recognition(i, label, score),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
final predictElapsedTime =
|
||||
DateTime.now().millisecondsSinceEpoch - predictStartTime;
|
||||
return Predictions(
|
||||
recognitions,
|
||||
Stats(
|
||||
predictElapsedTime,
|
||||
predictElapsedTime,
|
||||
inferenceTimeElapsed,
|
||||
preProcessElapsedTime,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// final predictElapsedTime =
|
||||
// DateTime.now().millisecondsSinceEpoch - predictStartTime;
|
||||
// return Predictions(
|
||||
// recognitions,
|
||||
// Stats(
|
||||
// predictElapsedTime,
|
||||
// predictElapsedTime,
|
||||
// inferenceTimeElapsed,
|
||||
// preProcessElapsedTime,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1,83 +1,83 @@
|
|||
import 'package:image/image.dart' as image_lib;
|
||||
import "package:logging/logging.dart";
|
||||
import 'package:photos/services/object_detection/models/predictions.dart';
|
||||
import 'package:photos/services/object_detection/models/recognition.dart';
|
||||
import "package:photos/services/object_detection/models/stats.dart";
|
||||
import "package:photos/services/object_detection/tflite/classifier.dart";
|
||||
import "package:tflite_flutter/tflite_flutter.dart";
|
||||
import "package:tflite_flutter_helper/tflite_flutter_helper.dart";
|
||||
// import 'package:image/image.dart' as image_lib;
|
||||
// import "package:logging/logging.dart";
|
||||
// import 'package:photos/services/object_detection/models/predictions.dart';
|
||||
// import 'package:photos/services/object_detection/models/recognition.dart';
|
||||
// import "package:photos/services/object_detection/models/stats.dart";
|
||||
// import "package:photos/services/object_detection/tflite/classifier.dart";
|
||||
// import "package:tflite_flutter/tflite_flutter.dart";
|
||||
// import "package:tflite_flutter_helper/tflite_flutter_helper.dart";
|
||||
|
||||
// Source: https://tfhub.dev/tensorflow/lite-model/mobilenet_v1_1.0_224/1/default/1
|
||||
class MobileNetClassifier extends Classifier {
|
||||
static final _logger = Logger("MobileNetClassifier");
|
||||
static const double threshold = 0.4;
|
||||
// // Source: https://tfhub.dev/tensorflow/lite-model/mobilenet_v1_1.0_224/1/default/1
|
||||
// class MobileNetClassifier extends Classifier {
|
||||
// static final _logger = Logger("MobileNetClassifier");
|
||||
// static const double threshold = 0.4;
|
||||
|
||||
@override
|
||||
String get modelPath => "models/mobilenet/mobilenet_v1_1.0_224_quant.tflite";
|
||||
// @override
|
||||
// String get modelPath => "models/mobilenet/mobilenet_v1_1.0_224_quant.tflite";
|
||||
|
||||
@override
|
||||
String get labelPath =>
|
||||
"assets/models/mobilenet/labels_mobilenet_quant_v1_224.txt";
|
||||
// @override
|
||||
// String get labelPath =>
|
||||
// "assets/models/mobilenet/labels_mobilenet_quant_v1_224.txt";
|
||||
|
||||
@override
|
||||
int get inputSize => 224;
|
||||
// @override
|
||||
// int get inputSize => 224;
|
||||
|
||||
@override
|
||||
Logger get logger => _logger;
|
||||
// @override
|
||||
// Logger get logger => _logger;
|
||||
|
||||
MobileNetClassifier({
|
||||
Interpreter? interpreter,
|
||||
List<String>? labels,
|
||||
}) {
|
||||
loadModel(interpreter);
|
||||
loadLabels(labels);
|
||||
}
|
||||
// MobileNetClassifier({
|
||||
// Interpreter? interpreter,
|
||||
// List<String>? labels,
|
||||
// }) {
|
||||
// loadModel(interpreter);
|
||||
// loadLabels(labels);
|
||||
// }
|
||||
|
||||
@override
|
||||
Predictions? predict(image_lib.Image image) {
|
||||
final predictStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
// @override
|
||||
// Predictions? predict(image_lib.Image image) {
|
||||
// final predictStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
final preProcessStart = DateTime.now().millisecondsSinceEpoch;
|
||||
// final preProcessStart = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
// Create TensorImage from image
|
||||
TensorImage inputImage = TensorImage.fromImage(image);
|
||||
// // Create TensorImage from image
|
||||
// TensorImage inputImage = TensorImage.fromImage(image);
|
||||
|
||||
// Pre-process TensorImage
|
||||
inputImage = getProcessedImage(inputImage);
|
||||
// // Pre-process TensorImage
|
||||
// inputImage = getProcessedImage(inputImage);
|
||||
|
||||
final preProcessElapsedTime =
|
||||
DateTime.now().millisecondsSinceEpoch - preProcessStart;
|
||||
// final preProcessElapsedTime =
|
||||
// DateTime.now().millisecondsSinceEpoch - preProcessStart;
|
||||
|
||||
// TensorBuffers for output tensors
|
||||
final output = TensorBufferUint8(outputShapes[0]);
|
||||
final inferenceTimeStart = DateTime.now().millisecondsSinceEpoch;
|
||||
// run inference
|
||||
interpreter.run(inputImage.buffer, output.buffer);
|
||||
// // TensorBuffers for output tensors
|
||||
// final output = TensorBufferUint8(outputShapes[0]);
|
||||
// final inferenceTimeStart = DateTime.now().millisecondsSinceEpoch;
|
||||
// // run inference
|
||||
// interpreter.run(inputImage.buffer, output.buffer);
|
||||
|
||||
final inferenceTimeElapsed =
|
||||
DateTime.now().millisecondsSinceEpoch - inferenceTimeStart;
|
||||
// final inferenceTimeElapsed =
|
||||
// DateTime.now().millisecondsSinceEpoch - inferenceTimeStart;
|
||||
|
||||
final recognitions = <Recognition>[];
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
final score = output.getDoubleValue(i) / 255;
|
||||
final label = labels.elementAt(i);
|
||||
if (score >= threshold) {
|
||||
recognitions.add(
|
||||
Recognition(i, label, score),
|
||||
);
|
||||
}
|
||||
}
|
||||
// final recognitions = <Recognition>[];
|
||||
// for (int i = 0; i < labels.length; i++) {
|
||||
// final score = output.getDoubleValue(i) / 255;
|
||||
// final label = labels.elementAt(i);
|
||||
// if (score >= threshold) {
|
||||
// recognitions.add(
|
||||
// Recognition(i, label, score),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
final predictElapsedTime =
|
||||
DateTime.now().millisecondsSinceEpoch - predictStartTime;
|
||||
return Predictions(
|
||||
recognitions,
|
||||
Stats(
|
||||
predictElapsedTime,
|
||||
predictElapsedTime,
|
||||
inferenceTimeElapsed,
|
||||
preProcessElapsedTime,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// final predictElapsedTime =
|
||||
// DateTime.now().millisecondsSinceEpoch - predictStartTime;
|
||||
// return Predictions(
|
||||
// recognitions,
|
||||
// Stats(
|
||||
// predictElapsedTime,
|
||||
// predictElapsedTime,
|
||||
// inferenceTimeElapsed,
|
||||
// preProcessElapsedTime,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1,88 +1,88 @@
|
|||
import "package:flutter/foundation.dart";
|
||||
import 'package:image/image.dart' as image_lib;
|
||||
import "package:logging/logging.dart";
|
||||
import 'package:photos/services/object_detection/models/predictions.dart';
|
||||
import 'package:photos/services/object_detection/models/recognition.dart';
|
||||
import "package:photos/services/object_detection/models/stats.dart";
|
||||
import "package:photos/services/object_detection/tflite/classifier.dart";
|
||||
import "package:tflite_flutter/tflite_flutter.dart";
|
||||
import "package:tflite_flutter_helper/tflite_flutter_helper.dart";
|
||||
// import "package:flutter/foundation.dart";
|
||||
// import 'package:image/image.dart' as image_lib;
|
||||
// import "package:logging/logging.dart";
|
||||
// import 'package:photos/services/object_detection/models/predictions.dart';
|
||||
// import 'package:photos/services/object_detection/models/recognition.dart';
|
||||
// import "package:photos/services/object_detection/models/stats.dart";
|
||||
// import "package:photos/services/object_detection/tflite/classifier.dart";
|
||||
// import "package:tflite_flutter/tflite_flutter.dart";
|
||||
// import "package:tflite_flutter_helper/tflite_flutter_helper.dart";
|
||||
|
||||
// Source: https://tfhub.dev/sayannath/lite-model/image-scene/1
|
||||
class SceneClassifier extends Classifier {
|
||||
static final _logger = Logger("SceneClassifier");
|
||||
static const double threshold = 0.35;
|
||||
// // Source: https://tfhub.dev/sayannath/lite-model/image-scene/1
|
||||
// class SceneClassifier extends Classifier {
|
||||
// static final _logger = Logger("SceneClassifier");
|
||||
// static const double threshold = 0.35;
|
||||
|
||||
@override
|
||||
String get modelPath => "models/scenes/model.tflite";
|
||||
// @override
|
||||
// String get modelPath => "models/scenes/model.tflite";
|
||||
|
||||
@override
|
||||
String get labelPath => "assets/models/scenes/labels.txt";
|
||||
// @override
|
||||
// String get labelPath => "assets/models/scenes/labels.txt";
|
||||
|
||||
@override
|
||||
int get inputSize => 224;
|
||||
// @override
|
||||
// int get inputSize => 224;
|
||||
|
||||
@override
|
||||
Logger get logger => _logger;
|
||||
// @override
|
||||
// Logger get logger => _logger;
|
||||
|
||||
SceneClassifier({
|
||||
Interpreter? interpreter,
|
||||
List<String>? labels,
|
||||
}) {
|
||||
loadModel(interpreter);
|
||||
loadLabels(labels);
|
||||
}
|
||||
// SceneClassifier({
|
||||
// Interpreter? interpreter,
|
||||
// List<String>? labels,
|
||||
// }) {
|
||||
// loadModel(interpreter);
|
||||
// loadLabels(labels);
|
||||
// }
|
||||
|
||||
@override
|
||||
Predictions? predict(image_lib.Image image) {
|
||||
final predictStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
// @override
|
||||
// Predictions? predict(image_lib.Image image) {
|
||||
// final predictStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
final preProcessStart = DateTime.now().millisecondsSinceEpoch;
|
||||
// final preProcessStart = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
// Create TensorImage from image
|
||||
TensorImage inputImage = TensorImage.fromImage(image);
|
||||
// // Create TensorImage from image
|
||||
// TensorImage inputImage = TensorImage.fromImage(image);
|
||||
|
||||
// Pre-process TensorImage
|
||||
inputImage = getProcessedImage(inputImage);
|
||||
final list = inputImage.getTensorBuffer().getDoubleList();
|
||||
final input = list.reshape([1, inputSize, inputSize, 3]);
|
||||
// // Pre-process TensorImage
|
||||
// inputImage = getProcessedImage(inputImage);
|
||||
// final list = inputImage.getTensorBuffer().getDoubleList();
|
||||
// final input = list.reshape([1, inputSize, inputSize, 3]);
|
||||
|
||||
final preProcessElapsedTime =
|
||||
DateTime.now().millisecondsSinceEpoch - preProcessStart;
|
||||
// final preProcessElapsedTime =
|
||||
// DateTime.now().millisecondsSinceEpoch - preProcessStart;
|
||||
|
||||
final output = TensorBufferFloat(outputShapes[0]);
|
||||
// final output = TensorBufferFloat(outputShapes[0]);
|
||||
|
||||
final inferenceTimeStart = DateTime.now().millisecondsSinceEpoch;
|
||||
interpreter.run(input, output.buffer);
|
||||
final inferenceTimeElapsed =
|
||||
DateTime.now().millisecondsSinceEpoch - inferenceTimeStart;
|
||||
// final inferenceTimeStart = DateTime.now().millisecondsSinceEpoch;
|
||||
// interpreter.run(input, output.buffer);
|
||||
// final inferenceTimeElapsed =
|
||||
// DateTime.now().millisecondsSinceEpoch - inferenceTimeStart;
|
||||
|
||||
final recognitions = <Recognition>[];
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
final score = output.getDoubleValue(i);
|
||||
final label = labels.elementAt(i);
|
||||
if (score >= threshold) {
|
||||
recognitions.add(
|
||||
Recognition(i, label, score),
|
||||
);
|
||||
} else if (kDebugMode && score > 0.2) {
|
||||
debugPrint("scenePrediction score $label is below threshold: $score");
|
||||
}
|
||||
}
|
||||
debugPrint(
|
||||
"Total lables ${labels.length} + reccg ${recognitions.map((e) => e.label).toSet()}",
|
||||
);
|
||||
// final recognitions = <Recognition>[];
|
||||
// for (int i = 0; i < labels.length; i++) {
|
||||
// final score = output.getDoubleValue(i);
|
||||
// final label = labels.elementAt(i);
|
||||
// if (score >= threshold) {
|
||||
// recognitions.add(
|
||||
// Recognition(i, label, score),
|
||||
// );
|
||||
// } else if (kDebugMode && score > 0.2) {
|
||||
// debugPrint("scenePrediction score $label is below threshold: $score");
|
||||
// }
|
||||
// }
|
||||
// debugPrint(
|
||||
// "Total lables ${labels.length} + reccg ${recognitions.map((e) => e.label).toSet()}",
|
||||
// );
|
||||
|
||||
final predictElapsedTime =
|
||||
DateTime.now().millisecondsSinceEpoch - predictStartTime;
|
||||
return Predictions(
|
||||
recognitions,
|
||||
Stats(
|
||||
predictElapsedTime,
|
||||
predictElapsedTime,
|
||||
inferenceTimeElapsed,
|
||||
preProcessElapsedTime,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// final predictElapsedTime =
|
||||
// DateTime.now().millisecondsSinceEpoch - predictStartTime;
|
||||
// return Predictions(
|
||||
// recognitions,
|
||||
// Stats(
|
||||
// predictElapsedTime,
|
||||
// predictElapsedTime,
|
||||
// inferenceTimeElapsed,
|
||||
// preProcessElapsedTime,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1,88 +1,88 @@
|
|||
import 'dart:isolate';
|
||||
import "dart:typed_data";
|
||||
// import 'dart:isolate';
|
||||
// import "dart:typed_data";
|
||||
|
||||
import 'package:image/image.dart' as imgLib;
|
||||
import "package:photos/services/object_detection/models/predictions.dart";
|
||||
import "package:photos/services/object_detection/tflite/classifier.dart";
|
||||
import 'package:photos/services/object_detection/tflite/cocossd_classifier.dart';
|
||||
import "package:photos/services/object_detection/tflite/mobilenet_classifier.dart";
|
||||
import "package:photos/services/object_detection/tflite/scene_classifier.dart";
|
||||
import 'package:tflite_flutter/tflite_flutter.dart';
|
||||
// import 'package:image/image.dart' as imgLib;
|
||||
// import "package:photos/services/object_detection/models/predictions.dart";
|
||||
// import "package:photos/services/object_detection/tflite/classifier.dart";
|
||||
// import 'package:photos/services/object_detection/tflite/cocossd_classifier.dart';
|
||||
// import "package:photos/services/object_detection/tflite/mobilenet_classifier.dart";
|
||||
// import "package:photos/services/object_detection/tflite/scene_classifier.dart";
|
||||
// import 'package:tflite_flutter/tflite_flutter.dart';
|
||||
|
||||
/// Manages separate Isolate instance for inference
|
||||
class IsolateUtils {
|
||||
static const String debugName = "InferenceIsolate";
|
||||
// /// Manages separate Isolate instance for inference
|
||||
// class IsolateUtils {
|
||||
// static const String debugName = "InferenceIsolate";
|
||||
|
||||
late SendPort _sendPort;
|
||||
final _receivePort = ReceivePort();
|
||||
// late SendPort _sendPort;
|
||||
// final _receivePort = ReceivePort();
|
||||
|
||||
SendPort get sendPort => _sendPort;
|
||||
// SendPort get sendPort => _sendPort;
|
||||
|
||||
Future<void> start() async {
|
||||
await Isolate.spawn<SendPort>(
|
||||
entryPoint,
|
||||
_receivePort.sendPort,
|
||||
debugName: debugName,
|
||||
);
|
||||
// Future<void> start() async {
|
||||
// await Isolate.spawn<SendPort>(
|
||||
// entryPoint,
|
||||
// _receivePort.sendPort,
|
||||
// debugName: debugName,
|
||||
// );
|
||||
|
||||
_sendPort = await _receivePort.first;
|
||||
}
|
||||
// _sendPort = await _receivePort.first;
|
||||
// }
|
||||
|
||||
static void entryPoint(SendPort sendPort) async {
|
||||
final port = ReceivePort();
|
||||
sendPort.send(port.sendPort);
|
||||
// static void entryPoint(SendPort sendPort) async {
|
||||
// final port = ReceivePort();
|
||||
// sendPort.send(port.sendPort);
|
||||
|
||||
await for (final IsolateData isolateData in port) {
|
||||
final classifier = _getClassifier(isolateData);
|
||||
final image = imgLib.decodeImage(isolateData.input);
|
||||
try {
|
||||
final results = classifier.predict(image!);
|
||||
isolateData.responsePort.send(results);
|
||||
} catch (e) {
|
||||
isolateData.responsePort.send(Predictions(null, null, error: e));
|
||||
}
|
||||
}
|
||||
}
|
||||
// await for (final IsolateData isolateData in port) {
|
||||
// final classifier = _getClassifier(isolateData);
|
||||
// final image = imgLib.decodeImage(isolateData.input);
|
||||
// try {
|
||||
// final results = classifier.predict(image!);
|
||||
// isolateData.responsePort.send(results);
|
||||
// } catch (e) {
|
||||
// isolateData.responsePort.send(Predictions(null, null, error: e));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
static Classifier _getClassifier(IsolateData isolateData) {
|
||||
final interpreter = Interpreter.fromAddress(isolateData.interpreterAddress);
|
||||
if (isolateData.type == ClassifierType.cocossd) {
|
||||
return CocoSSDClassifier(
|
||||
interpreter: interpreter,
|
||||
labels: isolateData.labels,
|
||||
);
|
||||
} else if (isolateData.type == ClassifierType.mobilenet) {
|
||||
return MobileNetClassifier(
|
||||
interpreter: interpreter,
|
||||
labels: isolateData.labels,
|
||||
);
|
||||
} else {
|
||||
return SceneClassifier(
|
||||
interpreter: interpreter,
|
||||
labels: isolateData.labels,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// static Classifier _getClassifier(IsolateData isolateData) {
|
||||
// final interpreter = Interpreter.fromAddress(isolateData.interpreterAddress);
|
||||
// if (isolateData.type == ClassifierType.cocossd) {
|
||||
// return CocoSSDClassifier(
|
||||
// interpreter: interpreter,
|
||||
// labels: isolateData.labels,
|
||||
// );
|
||||
// } else if (isolateData.type == ClassifierType.mobilenet) {
|
||||
// return MobileNetClassifier(
|
||||
// interpreter: interpreter,
|
||||
// labels: isolateData.labels,
|
||||
// );
|
||||
// } else {
|
||||
// return SceneClassifier(
|
||||
// interpreter: interpreter,
|
||||
// labels: isolateData.labels,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Bundles data to pass between Isolate
|
||||
class IsolateData {
|
||||
Uint8List input;
|
||||
int interpreterAddress;
|
||||
List<String> labels;
|
||||
ClassifierType type;
|
||||
late SendPort responsePort;
|
||||
// /// Bundles data to pass between Isolate
|
||||
// class IsolateData {
|
||||
// Uint8List input;
|
||||
// int interpreterAddress;
|
||||
// List<String> labels;
|
||||
// ClassifierType type;
|
||||
// late SendPort responsePort;
|
||||
|
||||
IsolateData(
|
||||
this.input,
|
||||
this.interpreterAddress,
|
||||
this.labels,
|
||||
this.type,
|
||||
);
|
||||
}
|
||||
// IsolateData(
|
||||
// this.input,
|
||||
// this.interpreterAddress,
|
||||
// this.labels,
|
||||
// this.type,
|
||||
// );
|
||||
// }
|
||||
|
||||
enum ClassifierType {
|
||||
cocossd,
|
||||
mobilenet,
|
||||
scenes,
|
||||
}
|
||||
// enum ClassifierType {
|
||||
// cocossd,
|
||||
// mobilenet,
|
||||
// scenes,
|
||||
// }
|
||||
|
|
|
@ -7,7 +7,7 @@ import 'package:photos/models/file/file.dart';
|
|||
import 'package:photos/models/file/file_type.dart';
|
||||
import "package:photos/models/metadata/file_magic.dart";
|
||||
import "package:photos/services/file_magic_service.dart";
|
||||
import "package:photos/services/update_service.dart";
|
||||
// import "package:photos/services/update_service.dart";
|
||||
import 'package:photos/theme/ente_theme.dart';
|
||||
import 'package:photos/ui/components/buttons/icon_button_widget.dart';
|
||||
import "package:photos/ui/components/divider_widget.dart";
|
||||
|
@ -20,7 +20,7 @@ import "package:photos/ui/viewer/file_details/creation_time_item_widget.dart";
|
|||
import 'package:photos/ui/viewer/file_details/exif_item_widgets.dart';
|
||||
import "package:photos/ui/viewer/file_details/file_properties_item_widget.dart";
|
||||
import "package:photos/ui/viewer/file_details/location_tags_widget.dart";
|
||||
import "package:photos/ui/viewer/file_details/objects_item_widget.dart";
|
||||
// import "package:photos/ui/viewer/file_details/objects_item_widget.dart";
|
||||
import "package:photos/utils/exif_util.dart";
|
||||
|
||||
class FileDetailsWidget extends StatefulWidget {
|
||||
|
@ -177,12 +177,12 @@ class _FileDetailsWidgetState extends State<FileDetailsWidget> {
|
|||
]);
|
||||
}
|
||||
|
||||
if (!UpdateService.instance.isFdroidFlavor()) {
|
||||
fileDetailsTiles.addAll([
|
||||
ObjectsItemWidget(file),
|
||||
const FileDetailsDivider(),
|
||||
]);
|
||||
}
|
||||
// if (!UpdateService.instance.isFdroidFlavor()) {
|
||||
// fileDetailsTiles.addAll([
|
||||
// ObjectsItemWidget(file),
|
||||
// const FileDetailsDivider(),
|
||||
// ]);
|
||||
// }
|
||||
|
||||
if (file.uploadedFileID != null && file.updationTime != null) {
|
||||
fileDetailsTiles.addAll(
|
||||
|
@ -280,7 +280,8 @@ class _FileDetailsWidgetState extends State<FileDetailsWidget> {
|
|||
if (imageWidth != null && imageLength != null) {
|
||||
_exifData["resolution"] = '$imageWidth x $imageLength';
|
||||
final double megaPixels =
|
||||
(imageWidth.values.firstAsInt() * imageLength.values.firstAsInt()) / 1000000;
|
||||
(imageWidth.values.firstAsInt() * imageLength.values.firstAsInt()) /
|
||||
1000000;
|
||||
final double roundedMegaPixels = (megaPixels * 10).round() / 10.0;
|
||||
_exifData['megaPixels'] = roundedMegaPixels..toStringAsFixed(1);
|
||||
} else {
|
||||
|
|
|
@ -1,67 +1,67 @@
|
|||
import "package:flutter/foundation.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:logging/logging.dart";
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/models/file/file.dart';
|
||||
import "package:photos/services/object_detection/object_detection_service.dart";
|
||||
import "package:photos/ui/components/buttons/chip_button_widget.dart";
|
||||
import "package:photos/ui/components/info_item_widget.dart";
|
||||
import "package:photos/utils/thumbnail_util.dart";
|
||||
// import "package:flutter/foundation.dart";
|
||||
// import "package:flutter/material.dart";
|
||||
// import "package:logging/logging.dart";
|
||||
// import "package:photos/generated/l10n.dart";
|
||||
// import 'package:photos/models/file/file.dart';
|
||||
// import "package:photos/services/object_detection/object_detection_service.dart";
|
||||
// import "package:photos/ui/components/buttons/chip_button_widget.dart";
|
||||
// import "package:photos/ui/components/info_item_widget.dart";
|
||||
// import "package:photos/utils/thumbnail_util.dart";
|
||||
|
||||
class ObjectsItemWidget extends StatelessWidget {
|
||||
final EnteFile file;
|
||||
const ObjectsItemWidget(this.file, {super.key});
|
||||
// class ObjectsItemWidget extends StatelessWidget {
|
||||
// final EnteFile file;
|
||||
// const ObjectsItemWidget(this.file, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InfoItemWidget(
|
||||
key: const ValueKey("Objects"),
|
||||
leadingIcon: Icons.image_search_outlined,
|
||||
subtitleSection: _objectTags(context, file),
|
||||
hasChipButtons: true,
|
||||
);
|
||||
}
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return InfoItemWidget(
|
||||
// key: const ValueKey("Objects"),
|
||||
// leadingIcon: Icons.image_search_outlined,
|
||||
// subtitleSection: _objectTags(context, file),
|
||||
// hasChipButtons: true,
|
||||
// );
|
||||
// }
|
||||
|
||||
Future<List<ChipButtonWidget>> _objectTags(
|
||||
BuildContext context,
|
||||
EnteFile file,
|
||||
) async {
|
||||
try {
|
||||
final chipButtons = <ChipButtonWidget>[];
|
||||
var objectTags = <String, double>{};
|
||||
final thumbnail = await getThumbnail(file);
|
||||
if (thumbnail != null) {
|
||||
objectTags = await ObjectDetectionService.instance.predict(thumbnail);
|
||||
}
|
||||
if (objectTags.isEmpty) {
|
||||
return [
|
||||
ChipButtonWidget(
|
||||
S.of(context).noResults,
|
||||
noChips: true,
|
||||
),
|
||||
];
|
||||
}
|
||||
// sort by values
|
||||
objectTags = Map.fromEntries(
|
||||
objectTags.entries.toList()
|
||||
..sort((e1, e2) => e2.value.compareTo(e1.value)),
|
||||
);
|
||||
// Future<List<ChipButtonWidget>> _objectTags(
|
||||
// BuildContext context,
|
||||
// EnteFile file,
|
||||
// ) async {
|
||||
// try {
|
||||
// final chipButtons = <ChipButtonWidget>[];
|
||||
// var objectTags = <String, double>{};
|
||||
// final thumbnail = await getThumbnail(file);
|
||||
// if (thumbnail != null) {
|
||||
// objectTags = await ObjectDetectionService.instance.predict(thumbnail);
|
||||
// }
|
||||
// if (objectTags.isEmpty) {
|
||||
// return [
|
||||
// ChipButtonWidget(
|
||||
// S.of(context).noResults,
|
||||
// noChips: true,
|
||||
// ),
|
||||
// ];
|
||||
// }
|
||||
// // sort by values
|
||||
// objectTags = Map.fromEntries(
|
||||
// objectTags.entries.toList()
|
||||
// ..sort((e1, e2) => e2.value.compareTo(e1.value)),
|
||||
// );
|
||||
|
||||
for (MapEntry<String, double> entry in objectTags.entries) {
|
||||
chipButtons.add(
|
||||
ChipButtonWidget(
|
||||
entry.key +
|
||||
(kDebugMode
|
||||
? "-" + (entry.value * 100).round().toString()
|
||||
: ""),
|
||||
),
|
||||
);
|
||||
}
|
||||
// for (MapEntry<String, double> entry in objectTags.entries) {
|
||||
// chipButtons.add(
|
||||
// ChipButtonWidget(
|
||||
// entry.key +
|
||||
// (kDebugMode
|
||||
// ? "-" + (entry.value * 100).round().toString()
|
||||
// : ""),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
return chipButtons;
|
||||
} catch (e, s) {
|
||||
Logger("ObjctsItemWidget").info(e, s);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
// return chipButtons;
|
||||
// } catch (e, s) {
|
||||
// Logger("ObjctsItemWidget").info(e, s);
|
||||
// return [];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'dart:math';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import "package:path/path.dart";
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
import 'package:photos/core/constants.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
|
|
87
pubspec.lock
|
@ -193,46 +193,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
camera:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: camera
|
||||
sha256: "3ad71371b8168a4c8012c0b40a53c05afc75d46cc688b0f37b4611a841d47b25"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.8+1"
|
||||
camera_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: camera_android
|
||||
sha256: "665d62c1f334722c7519ca5d3b94ad68ecaa801691870602da5638a42c1fff67"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.8+3"
|
||||
camera_avfoundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: camera_avfoundation
|
||||
sha256: "1a416e452b30955b392f4efbf23291d3f2ba3660a85e1628859eb62d2a2bab26"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.13+2"
|
||||
camera_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: camera_platform_interface
|
||||
sha256: "60fa0bb62a4f3bf3a7c413e31e4cd01b69c779ccc8e4668904a24581b86c316b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.1"
|
||||
camera_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: camera_web
|
||||
sha256: "18cdbee5441e9a6fb129fdd9b68a06d1b8c5236932ba97d5faeaefe80db2e5bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1+6"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -258,6 +218,14 @@ packages:
|
|||
url: "https://github.com/ente-io/chewie.git"
|
||||
source: git
|
||||
version: "1.7.0"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -663,13 +631,13 @@ packages:
|
|||
source: hosted
|
||||
version: "5.7.2+3"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct main"
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
sha256: "559c600f056e7c704bd843723c21e01b5fba47e8824bd02422165bcc02a5de1d"
|
||||
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3"
|
||||
version: "0.13.1"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
|
@ -735,10 +703,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_native_splash
|
||||
sha256: "6777a3abb974021a39b5fdd2d46a03ca390e03903b6351f21d10e7ecc969f12d"
|
||||
sha256: ecff62b3b893f2f665de7e4ad3de89f738941fcfcaaba8ee601e749efafa4698
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.16"
|
||||
version: "2.3.2"
|
||||
flutter_password_strength:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -910,10 +878,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: html
|
||||
sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8"
|
||||
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.15.3"
|
||||
version: "0.15.4"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -950,10 +918,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: image
|
||||
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
|
||||
sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.0"
|
||||
version: "4.0.17"
|
||||
image_editor:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1397,10 +1365,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4"
|
||||
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
version: "5.4.0"
|
||||
photo_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1886,15 +1854,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.1"
|
||||
tflite_flutter_helper:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: a7d7a59a33f7cffa0a2a12ab05625807622cc97a
|
||||
resolved-ref: a7d7a59a33f7cffa0a2a12ab05625807622cc97a
|
||||
url: "https://github.com/elephantum/tflite_flutter_helper.git"
|
||||
source: git
|
||||
version: "0.3.0"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1963,10 +1922,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: universal_io
|
||||
sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d"
|
||||
sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "2.2.2"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -2212,10 +2171,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5"
|
||||
sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
version: "6.3.0"
|
||||
xmlstream:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
34
pubspec.yaml
|
@ -65,13 +65,12 @@ dependencies:
|
|||
flutter_email_sender: ^5.2.0
|
||||
flutter_image_compress: ^1.1.0
|
||||
flutter_inappwebview: ^5.5.0+2
|
||||
flutter_launcher_icons: ^0.9.3
|
||||
flutter_local_notifications: ^12.0.4
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_map: ^4.0.0
|
||||
flutter_map_marker_cluster: ^1.1.1
|
||||
flutter_native_splash: ^2.2.0+1
|
||||
flutter_native_splash: ^2.3.1
|
||||
flutter_password_strength: ^0.1.6
|
||||
flutter_secure_storage: ^8.0.0
|
||||
flutter_sodium: ^0.2.0
|
||||
|
@ -80,7 +79,7 @@ dependencies:
|
|||
freezed_annotation: ^2.2.0
|
||||
google_nav_bar: ^5.0.5
|
||||
http: ^0.13.4
|
||||
image: ^3.0.2
|
||||
image: ^4.0.17
|
||||
image_editor: ^1.3.0
|
||||
in_app_purchase: ^3.0.7
|
||||
intl: ^0.18.0
|
||||
|
@ -128,10 +127,10 @@ dependencies:
|
|||
syncfusion_flutter_core: ^19.2.49
|
||||
syncfusion_flutter_sliders: ^19.2.49
|
||||
tflite_flutter: ^0.9.0
|
||||
tflite_flutter_helper:
|
||||
git:
|
||||
url: https://github.com/elephantum/tflite_flutter_helper.git # Fixes https://github.com/am15h/tflite_flutter_helper/issues/57
|
||||
ref: a7d7a59a33f7cffa0a2a12ab05625807622cc97a
|
||||
# tflite_flutter_helper:
|
||||
# git:
|
||||
# url: https://github.com/elephantum/tflite_flutter_helper.git # Fixes https://github.com/am15h/tflite_flutter_helper/issues/57
|
||||
# ref: a7d7a59a33f7cffa0a2a12ab05625807622cc97a
|
||||
tuple: ^2.0.0
|
||||
uni_links: ^0.5.1
|
||||
url_launcher: ^6.0.3
|
||||
|
@ -168,6 +167,7 @@ dev_dependencies:
|
|||
build_runner: ^2.3.3
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
flutter_lints: ^2.0.1
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
@ -177,18 +177,20 @@ dev_dependencies:
|
|||
json_serializable: ^6.6.1
|
||||
test: ^1.22.0
|
||||
|
||||
flutter_icons:
|
||||
android: "launcher_icon"
|
||||
adaptive_icon_foreground: "assets/launcher_icon/ente-icon-foreground.png"
|
||||
adaptive_icon_background: "#ffffff"
|
||||
flutter_launcher_icons:
|
||||
android: true
|
||||
ios: true
|
||||
image_path: "assets/icon-light.png"
|
||||
image_path: "assets/launcher_icon/icon.png"
|
||||
adaptive_icon_foreground: "assets/launcher_icon/adaptive_icon.png"
|
||||
adaptive_icon_background: "#ffffff"
|
||||
remove_alpha_ios: true
|
||||
min_sdk_android: 21
|
||||
|
||||
flutter_native_splash:
|
||||
color: "#ffffff"
|
||||
color_dark: "#000000"
|
||||
image: assets/splash-screen-light.png
|
||||
image_dark: assets/splash-screen-dark.png
|
||||
image: assets/splash-icon-light.png
|
||||
image_dark: assets/splash-icon-dark.png
|
||||
android_fullscreen: true
|
||||
android_gravity: center
|
||||
ios_content_mode: center
|
||||
|
@ -198,8 +200,8 @@ flutter_native_splash:
|
|||
# Please note that the splash screen will be clipped to a circle on the center of the screen.
|
||||
# App icon without an icon background: This should be 1152×1152 pixels, and fit within a circle
|
||||
# 768 pixels in diameter.
|
||||
image: assets/splash-screen-light.png
|
||||
image_dark: assets/splash-screen-dark.png
|
||||
image: assets/splash-icon-light.png
|
||||
image_dark: assets/splash-icon-dark.png
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
|