@souscheflabs/ml-vision 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +274 -0
  2. package/dist/components/DetectionOverlay.d.ts +57 -0
  3. package/dist/components/DetectionOverlay.js +133 -0
  4. package/dist/components/index.d.ts +4 -0
  5. package/dist/components/index.js +9 -0
  6. package/dist/core/CacheManager.d.ts +168 -0
  7. package/dist/core/CacheManager.js +331 -0
  8. package/dist/core/MLVisionProvider.d.ts +90 -0
  9. package/dist/core/MLVisionProvider.js +188 -0
  10. package/dist/core/ServerClient.d.ts +131 -0
  11. package/dist/core/ServerClient.js +291 -0
  12. package/dist/core/index.d.ts +6 -0
  13. package/dist/core/index.js +18 -0
  14. package/dist/hooks/classLabels.d.ts +35 -0
  15. package/dist/hooks/classLabels.js +439 -0
  16. package/dist/hooks/classLabelsCoco.d.ts +43 -0
  17. package/dist/hooks/classLabelsCoco.js +103 -0
  18. package/dist/hooks/index.d.ts +8 -0
  19. package/dist/hooks/index.js +27 -0
  20. package/dist/hooks/useMultiBarcodeScanner.d.ts +34 -0
  21. package/dist/hooks/useMultiBarcodeScanner.js +290 -0
  22. package/dist/hooks/useProductDetector.d.ts +38 -0
  23. package/dist/hooks/useProductDetector.js +679 -0
  24. package/dist/hooks/useReceiptScanner.d.ts +37 -0
  25. package/dist/hooks/useReceiptScanner.js +405 -0
  26. package/dist/hooks/useVideoScanner.d.ts +118 -0
  27. package/dist/hooks/useVideoScanner.js +383 -0
  28. package/dist/index.d.ts +58 -0
  29. package/dist/index.js +130 -0
  30. package/dist/processors/detectionProcessor.d.ts +86 -0
  31. package/dist/processors/detectionProcessor.js +124 -0
  32. package/dist/processors/index.d.ts +5 -0
  33. package/dist/processors/index.js +16 -0
  34. package/dist/processors/tfliteFrameProcessor.d.ts +90 -0
  35. package/dist/processors/tfliteFrameProcessor.js +213 -0
  36. package/dist/types/barcode.d.ts +91 -0
  37. package/dist/types/barcode.js +19 -0
  38. package/dist/types/detection.d.ts +166 -0
  39. package/dist/types/detection.js +8 -0
  40. package/dist/types/index.d.ts +126 -0
  41. package/dist/types/index.js +25 -0
  42. package/dist/types/ocr.d.ts +202 -0
  43. package/dist/types/ocr.js +8 -0
  44. package/dist/utils/imagePreprocessor.d.ts +85 -0
  45. package/dist/utils/imagePreprocessor.js +304 -0
  46. package/dist/utils/yoloProcessor.d.ts +40 -0
  47. package/dist/utils/yoloProcessor.js +154 -0
  48. package/package.json +78 -0
@@ -0,0 +1,331 @@
1
+ "use strict";
2
+ /**
3
+ * CacheManager - MMKV-based caching for ML Vision results
4
+ *
5
+ * Provides fast, synchronous caching for:
6
+ * - Barcode to product lookups
7
+ * - Product recognition results
8
+ * - Receipt parsing results
9
+ * - Model metadata
10
+ *
11
+ * Uses react-native-mmkv for ~30x faster access than AsyncStorage.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.CacheManager = exports.CACHE_TTL = void 0;
15
+ exports.createCacheManager = createCacheManager;
16
+ // ============================================================================
17
+ // Cache Configuration
18
+ // ============================================================================
19
+ /**
20
+ * Default TTL values (in milliseconds)
21
+ */
22
+ exports.CACHE_TTL = {
23
+ /** Barcode lookups - 7 days */
24
+ BARCODE: 7 * 24 * 60 * 60 * 1000,
25
+ /** Product recognition - 24 hours */
26
+ PRODUCT: 24 * 60 * 60 * 1000,
27
+ /** Receipt parsing - 1 hour */
28
+ RECEIPT: 60 * 60 * 1000,
29
+ /** Model metadata - until manually cleared */
30
+ MODEL: Infinity,
31
+ /** Server responses - 5 minutes */
32
+ SERVER: 5 * 60 * 1000,
33
+ };
34
+ /**
35
+ * Cache key prefixes for namespacing
36
+ */
37
+ const CACHE_PREFIX = {
38
+ BARCODE: 'mlv_barcode_',
39
+ PRODUCT: 'mlv_product_',
40
+ RECEIPT: 'mlv_receipt_',
41
+ MODEL: 'mlv_model_',
42
+ CONFIG: 'mlv_config_',
43
+ };
44
+ // ============================================================================
45
+ // CacheManager Class
46
+ // ============================================================================
47
+ /**
48
+ * CacheManager provides fast key-value caching using MMKV
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const cache = new CacheManager(mmkvInstance);
53
+ *
54
+ * // Cache a barcode lookup
55
+ * cache.setBarcode('0123456789012', {
56
+ * barcode: '0123456789012',
57
+ * format: 'ean-13',
58
+ * productId: 'prod_123',
59
+ * productName: 'Example Product',
60
+ * found: true,
61
+ * });
62
+ *
63
+ * // Retrieve later
64
+ * const product = cache.getBarcode('0123456789012');
65
+ * ```
66
+ */
67
+ class CacheManager {
68
+ constructor(storage, customTTL) {
69
+ this.storage = storage;
70
+ this.defaultTTL = { ...exports.CACHE_TTL, ...customTTL };
71
+ }
72
+ // ==========================================================================
73
+ // Barcode Cache Methods
74
+ // ==========================================================================
75
+ /**
76
+ * Cache a barcode lookup result
77
+ */
78
+ setBarcode(barcode, data, ttl) {
79
+ const entry = {
80
+ data,
81
+ timestamp: Date.now(),
82
+ ttl: ttl ?? this.defaultTTL.BARCODE,
83
+ };
84
+ const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
85
+ this.storage.set(key, JSON.stringify(entry));
86
+ }
87
+ /**
88
+ * Get a cached barcode lookup
89
+ * @returns The cached data or null if not found/expired
90
+ */
91
+ getBarcode(barcode) {
92
+ const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
93
+ const cached = this.storage.getString(key);
94
+ if (!cached)
95
+ return null;
96
+ try {
97
+ const entry = JSON.parse(cached);
98
+ if (this.isExpired(entry)) {
99
+ this.storage.delete(key);
100
+ return null;
101
+ }
102
+ return entry.data;
103
+ }
104
+ catch {
105
+ this.storage.delete(key);
106
+ return null;
107
+ }
108
+ }
109
+ /**
110
+ * Check if a barcode is cached
111
+ */
112
+ hasBarcode(barcode) {
113
+ return this.getBarcode(barcode) !== null;
114
+ }
115
+ /**
116
+ * Delete a cached barcode
117
+ */
118
+ deleteBarcode(barcode) {
119
+ const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
120
+ this.storage.delete(key);
121
+ }
122
+ // ==========================================================================
123
+ // Product Recognition Cache Methods
124
+ // ==========================================================================
125
+ /**
126
+ * Cache product recognition results for an image
127
+ * @param imageHash - Hash of the image (e.g., MD5 or perceptual hash)
128
+ */
129
+ setProductRecognition(imageHash, data, ttl) {
130
+ const entry = {
131
+ data,
132
+ timestamp: Date.now(),
133
+ ttl: ttl ?? this.defaultTTL.PRODUCT,
134
+ };
135
+ const key = `${CACHE_PREFIX.PRODUCT}${imageHash}`;
136
+ this.storage.set(key, JSON.stringify(entry));
137
+ }
138
+ /**
139
+ * Get cached product recognition for an image
140
+ */
141
+ getProductRecognition(imageHash) {
142
+ const key = `${CACHE_PREFIX.PRODUCT}${imageHash}`;
143
+ const cached = this.storage.getString(key);
144
+ if (!cached)
145
+ return null;
146
+ try {
147
+ const entry = JSON.parse(cached);
148
+ if (this.isExpired(entry)) {
149
+ this.storage.delete(key);
150
+ return null;
151
+ }
152
+ return entry.data;
153
+ }
154
+ catch {
155
+ this.storage.delete(key);
156
+ return null;
157
+ }
158
+ }
159
+ // ==========================================================================
160
+ // Model Metadata Cache Methods
161
+ // ==========================================================================
162
+ /**
163
+ * Store model metadata
164
+ */
165
+ setModelMetadata(modelId, metadata) {
166
+ const key = `${CACHE_PREFIX.MODEL}${modelId}`;
167
+ this.storage.set(key, JSON.stringify(metadata));
168
+ }
169
+ /**
170
+ * Get model metadata
171
+ */
172
+ getModelMetadata(modelId) {
173
+ const key = `${CACHE_PREFIX.MODEL}${modelId}`;
174
+ const cached = this.storage.getString(key);
175
+ if (!cached)
176
+ return null;
177
+ try {
178
+ return JSON.parse(cached);
179
+ }
180
+ catch {
181
+ return null;
182
+ }
183
+ }
184
+ // ==========================================================================
185
+ // Config Cache Methods
186
+ // ==========================================================================
187
+ /**
188
+ * Store a configuration value
189
+ */
190
+ setConfig(key, value) {
191
+ const fullKey = `${CACHE_PREFIX.CONFIG}${key}`;
192
+ this.storage.set(fullKey, JSON.stringify(value));
193
+ }
194
+ /**
195
+ * Get a configuration value
196
+ */
197
+ getConfig(key, defaultValue) {
198
+ const fullKey = `${CACHE_PREFIX.CONFIG}${key}`;
199
+ const cached = this.storage.getString(fullKey);
200
+ if (!cached)
201
+ return defaultValue;
202
+ try {
203
+ return JSON.parse(cached);
204
+ }
205
+ catch {
206
+ return defaultValue;
207
+ }
208
+ }
209
+ // ==========================================================================
210
+ // Cache Management Methods
211
+ // ==========================================================================
212
+ /**
213
+ * Clear all expired entries from the cache
214
+ * Call this periodically (e.g., on app start)
215
+ */
216
+ cleanupExpired() {
217
+ let removed = 0;
218
+ const allKeys = this.storage.getAllKeys();
219
+ for (const key of allKeys) {
220
+ // Only process our prefixed keys
221
+ const isOurKey = Object.values(CACHE_PREFIX).some((prefix) => key.startsWith(prefix));
222
+ if (!isOurKey)
223
+ continue;
224
+ // Skip model metadata (no TTL)
225
+ if (key.startsWith(CACHE_PREFIX.MODEL))
226
+ continue;
227
+ const value = this.storage.getString(key);
228
+ if (!value)
229
+ continue;
230
+ try {
231
+ const entry = JSON.parse(value);
232
+ if (this.isExpired(entry)) {
233
+ this.storage.delete(key);
234
+ removed++;
235
+ }
236
+ }
237
+ catch {
238
+ // Invalid entry, remove it
239
+ this.storage.delete(key);
240
+ removed++;
241
+ }
242
+ }
243
+ return removed;
244
+ }
245
+ /**
246
+ * Clear all ML Vision cache entries
247
+ */
248
+ clearAll() {
249
+ const allKeys = this.storage.getAllKeys();
250
+ for (const key of allKeys) {
251
+ const isOurKey = Object.values(CACHE_PREFIX).some((prefix) => key.startsWith(prefix));
252
+ if (isOurKey) {
253
+ this.storage.delete(key);
254
+ }
255
+ }
256
+ }
257
+ /**
258
+ * Clear cache by type
259
+ */
260
+ clearByType(type) {
261
+ const prefix = CACHE_PREFIX[type];
262
+ const allKeys = this.storage.getAllKeys();
263
+ for (const key of allKeys) {
264
+ if (key.startsWith(prefix)) {
265
+ this.storage.delete(key);
266
+ }
267
+ }
268
+ }
269
+ /**
270
+ * Get cache statistics
271
+ */
272
+ getStats() {
273
+ const allKeys = this.storage.getAllKeys();
274
+ let barcodeEntries = 0;
275
+ let productEntries = 0;
276
+ let receiptEntries = 0;
277
+ let totalSizeBytes = 0;
278
+ for (const key of allKeys) {
279
+ if (key.startsWith(CACHE_PREFIX.BARCODE)) {
280
+ barcodeEntries++;
281
+ }
282
+ else if (key.startsWith(CACHE_PREFIX.PRODUCT)) {
283
+ productEntries++;
284
+ }
285
+ else if (key.startsWith(CACHE_PREFIX.RECEIPT)) {
286
+ receiptEntries++;
287
+ }
288
+ // Estimate size
289
+ const value = this.storage.getString(key);
290
+ if (value) {
291
+ totalSizeBytes += key.length + value.length;
292
+ }
293
+ }
294
+ return {
295
+ barcodeEntries,
296
+ productEntries,
297
+ receiptEntries,
298
+ totalSizeBytes,
299
+ };
300
+ }
301
+ // ==========================================================================
302
+ // Private Helper Methods
303
+ // ==========================================================================
304
+ /**
305
+ * Check if a cache entry has expired
306
+ */
307
+ isExpired(entry) {
308
+ if (entry.ttl === Infinity)
309
+ return false;
310
+ return Date.now() - entry.timestamp > entry.ttl;
311
+ }
312
+ }
313
+ exports.CacheManager = CacheManager;
314
+ // ============================================================================
315
+ // Factory Function
316
+ // ============================================================================
317
+ /**
318
+ * Create a CacheManager instance
319
+ * This is the recommended way to create a CacheManager
320
+ *
321
+ * @example
322
+ * ```typescript
323
+ * import { MMKV } from 'react-native-mmkv';
324
+ *
325
+ * const storage = new MMKV({ id: 'ml-vision-cache' });
326
+ * const cache = createCacheManager(storage);
327
+ * ```
328
+ */
329
+ function createCacheManager(storage, customTTL) {
330
+ return new CacheManager(storage, customTTL);
331
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * MLVisionProvider - Context provider for ML Vision functionality
3
+ *
4
+ * Provides:
5
+ * - Configuration management
6
+ * - Cache manager instance
7
+ * - Server client for fallback inference
8
+ * - Model manager for TFLite models
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { MLVisionProvider } from '@souschef/ml-vision';
13
+ *
14
+ * function App() {
15
+ * return (
16
+ * <MLVisionProvider
17
+ * config={{
18
+ * serverUrl: 'http://192.168.1.100:8000',
19
+ * cacheEnabled: true,
20
+ * }}
21
+ * >
22
+ * <YourApp />
23
+ * </MLVisionProvider>
24
+ * );
25
+ * }
26
+ * ```
27
+ */
28
+ import React, { type ReactNode } from 'react';
29
+ import type { MMKV } from 'react-native-mmkv';
30
+ import { CacheManager } from './CacheManager';
31
+ import { ServerClient } from './ServerClient';
32
+ import type { MLVisionConfig, ServerHealthResponse } from '../types';
33
+ /**
34
+ * Context value provided by MLVisionProvider
35
+ */
36
+ export interface MLVisionContextValue {
37
+ /** Merged configuration */
38
+ config: Required<MLVisionConfig>;
39
+ /** Whether the provider is fully initialized */
40
+ isInitialized: boolean;
41
+ /** Cache manager instance (null if caching disabled) */
42
+ cacheManager: CacheManager | null;
43
+ /** Server client for fallback inference (null if no serverUrl) */
44
+ serverClient: ServerClient | null;
45
+ /** Whether the server is available */
46
+ serverAvailable: boolean;
47
+ /** Server health info */
48
+ serverHealth: ServerHealthResponse | null;
49
+ /** Check server health */
50
+ checkServerHealth: () => Promise<ServerHealthResponse | null>;
51
+ /** Update configuration at runtime */
52
+ updateConfig: (updates: Partial<MLVisionConfig>) => void;
53
+ }
54
+ export interface MLVisionProviderProps {
55
+ children: ReactNode;
56
+ /** Configuration options */
57
+ config?: MLVisionConfig;
58
+ /** MMKV storage instance for caching (required if cacheEnabled) */
59
+ storage?: MMKV;
60
+ /** Callback when initialization completes */
61
+ onInitialized?: () => void;
62
+ /** Callback on initialization error */
63
+ onError?: (error: Error) => void;
64
+ }
65
+ /**
66
+ * MLVisionProvider - Wrap your app with this provider to use ML Vision hooks
67
+ */
68
+ export declare function MLVisionProvider({ children, config: userConfig, storage, onInitialized, onError, }: MLVisionProviderProps): React.ReactElement;
69
+ /**
70
+ * Hook to access the MLVision context
71
+ *
72
+ * @throws Error if used outside of MLVisionProvider
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * function MyComponent() {
77
+ * const { config, serverAvailable, cacheManager } = useMLVisionContext();
78
+ *
79
+ * if (!serverAvailable) {
80
+ * console.log('Running in offline mode');
81
+ * }
82
+ * }
83
+ * ```
84
+ */
85
+ export declare function useMLVisionContext(): MLVisionContextValue;
86
+ /**
87
+ * Hook to check if MLVision is initialized
88
+ * Returns false if used outside provider (won't throw)
89
+ */
90
+ export declare function useMLVisionReady(): boolean;
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MLVisionProvider = MLVisionProvider;
4
+ exports.useMLVisionContext = useMLVisionContext;
5
+ exports.useMLVisionReady = useMLVisionReady;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ /**
8
+ * MLVisionProvider - Context provider for ML Vision functionality
9
+ *
10
+ * Provides:
11
+ * - Configuration management
12
+ * - Cache manager instance
13
+ * - Server client for fallback inference
14
+ * - Model manager for TFLite models
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { MLVisionProvider } from '@souschef/ml-vision';
19
+ *
20
+ * function App() {
21
+ * return (
22
+ * <MLVisionProvider
23
+ * config={{
24
+ * serverUrl: 'http://192.168.1.100:8000',
25
+ * cacheEnabled: true,
26
+ * }}
27
+ * >
28
+ * <YourApp />
29
+ * </MLVisionProvider>
30
+ * );
31
+ * }
32
+ * ```
33
+ */
34
+ const react_1 = require("react");
35
+ const CacheManager_1 = require("./CacheManager");
36
+ const ServerClient_1 = require("./ServerClient");
37
+ // ============================================================================
38
+ // Default Configuration
39
+ // ============================================================================
40
+ const DEFAULT_CONFIG = {
41
+ serverUrl: '',
42
+ serverTimeout: 5000,
43
+ cacheEnabled: true,
44
+ cacheTTL: 24 * 60 * 60 * 1000, // 24 hours
45
+ modelUpdateCheck: true,
46
+ enableGPUDelegate: true,
47
+ };
48
+ // ============================================================================
49
+ // Context
50
+ // ============================================================================
51
+ const MLVisionContext = (0, react_1.createContext)(null);
52
+ // ============================================================================
53
+ // Provider Component
54
+ // ============================================================================
55
+ /**
56
+ * MLVisionProvider - Wrap your app with this provider to use ML Vision hooks
57
+ */
58
+ function MLVisionProvider({ children, config: userConfig, storage, onInitialized, onError, }) {
59
+ // Merge user config with defaults
60
+ const [config, setConfig] = (0, react_1.useState)(() => ({
61
+ ...DEFAULT_CONFIG,
62
+ ...userConfig,
63
+ }));
64
+ const [isInitialized, setIsInitialized] = (0, react_1.useState)(false);
65
+ const [serverAvailable, setServerAvailable] = (0, react_1.useState)(false);
66
+ const [serverHealth, setServerHealth] = (0, react_1.useState)(null);
67
+ // Create cache manager
68
+ const cacheManager = (0, react_1.useMemo)(() => {
69
+ if (!config.cacheEnabled || !storage) {
70
+ return null;
71
+ }
72
+ return (0, CacheManager_1.createCacheManager)(storage);
73
+ }, [config.cacheEnabled, storage]);
74
+ // Create server client
75
+ const serverClient = (0, react_1.useMemo)(() => {
76
+ if (!config.serverUrl) {
77
+ return null;
78
+ }
79
+ return (0, ServerClient_1.createServerClient)(config.serverUrl, config.serverTimeout);
80
+ }, [config.serverUrl, config.serverTimeout]);
81
+ // Check server health
82
+ const checkServerHealth = (0, react_1.useCallback)(async () => {
83
+ if (!serverClient) {
84
+ setServerAvailable(false);
85
+ setServerHealth(null);
86
+ return null;
87
+ }
88
+ try {
89
+ const health = await serverClient.checkHealth();
90
+ setServerAvailable(health.status === 'healthy');
91
+ setServerHealth(health);
92
+ return health;
93
+ }
94
+ catch {
95
+ setServerAvailable(false);
96
+ setServerHealth(null);
97
+ return null;
98
+ }
99
+ }, [serverClient]);
100
+ // Update config at runtime
101
+ const updateConfig = (0, react_1.useCallback)((updates) => {
102
+ setConfig((prev) => ({ ...prev, ...updates }));
103
+ }, []);
104
+ // Initialize on mount
105
+ (0, react_1.useEffect)(() => {
106
+ async function initialize() {
107
+ try {
108
+ // Clean up expired cache entries
109
+ if (cacheManager) {
110
+ const removed = cacheManager.cleanupExpired();
111
+ if (removed > 0) {
112
+ console.log(`[MLVision] Cleaned up ${removed} expired cache entries`);
113
+ }
114
+ }
115
+ // Check server health if configured
116
+ if (serverClient) {
117
+ await checkServerHealth();
118
+ }
119
+ setIsInitialized(true);
120
+ onInitialized?.();
121
+ }
122
+ catch (error) {
123
+ const err = error instanceof Error ? error : new Error('Initialization failed');
124
+ console.error('[MLVision] Initialization error:', err);
125
+ onError?.(err);
126
+ // Still mark as initialized so the app can work in offline mode
127
+ setIsInitialized(true);
128
+ }
129
+ }
130
+ initialize();
131
+ }, [cacheManager, serverClient, checkServerHealth, onInitialized, onError]);
132
+ // Context value
133
+ const contextValue = (0, react_1.useMemo)(() => ({
134
+ config,
135
+ isInitialized,
136
+ cacheManager,
137
+ serverClient,
138
+ serverAvailable,
139
+ serverHealth,
140
+ checkServerHealth,
141
+ updateConfig,
142
+ }), [
143
+ config,
144
+ isInitialized,
145
+ cacheManager,
146
+ serverClient,
147
+ serverAvailable,
148
+ serverHealth,
149
+ checkServerHealth,
150
+ updateConfig,
151
+ ]);
152
+ return ((0, jsx_runtime_1.jsx)(MLVisionContext.Provider, { value: contextValue, children: children }));
153
+ }
154
+ // ============================================================================
155
+ // Hook
156
+ // ============================================================================
157
+ /**
158
+ * Hook to access the MLVision context
159
+ *
160
+ * @throws Error if used outside of MLVisionProvider
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * function MyComponent() {
165
+ * const { config, serverAvailable, cacheManager } = useMLVisionContext();
166
+ *
167
+ * if (!serverAvailable) {
168
+ * console.log('Running in offline mode');
169
+ * }
170
+ * }
171
+ * ```
172
+ */
173
+ function useMLVisionContext() {
174
+ const context = (0, react_1.useContext)(MLVisionContext);
175
+ if (!context) {
176
+ throw new Error('useMLVisionContext must be used within an MLVisionProvider. ' +
177
+ 'Wrap your app with <MLVisionProvider> to use ML Vision hooks.');
178
+ }
179
+ return context;
180
+ }
181
+ /**
182
+ * Hook to check if MLVision is initialized
183
+ * Returns false if used outside provider (won't throw)
184
+ */
185
+ function useMLVisionReady() {
186
+ const context = (0, react_1.useContext)(MLVisionContext);
187
+ return context?.isInitialized ?? false;
188
+ }