@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.
- package/README.md +274 -0
- package/dist/components/DetectionOverlay.d.ts +57 -0
- package/dist/components/DetectionOverlay.js +133 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +9 -0
- package/dist/core/CacheManager.d.ts +168 -0
- package/dist/core/CacheManager.js +331 -0
- package/dist/core/MLVisionProvider.d.ts +90 -0
- package/dist/core/MLVisionProvider.js +188 -0
- package/dist/core/ServerClient.d.ts +131 -0
- package/dist/core/ServerClient.js +291 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +18 -0
- package/dist/hooks/classLabels.d.ts +35 -0
- package/dist/hooks/classLabels.js +439 -0
- package/dist/hooks/classLabelsCoco.d.ts +43 -0
- package/dist/hooks/classLabelsCoco.js +103 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.js +27 -0
- package/dist/hooks/useMultiBarcodeScanner.d.ts +34 -0
- package/dist/hooks/useMultiBarcodeScanner.js +290 -0
- package/dist/hooks/useProductDetector.d.ts +38 -0
- package/dist/hooks/useProductDetector.js +679 -0
- package/dist/hooks/useReceiptScanner.d.ts +37 -0
- package/dist/hooks/useReceiptScanner.js +405 -0
- package/dist/hooks/useVideoScanner.d.ts +118 -0
- package/dist/hooks/useVideoScanner.js +383 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +130 -0
- package/dist/processors/detectionProcessor.d.ts +86 -0
- package/dist/processors/detectionProcessor.js +124 -0
- package/dist/processors/index.d.ts +5 -0
- package/dist/processors/index.js +16 -0
- package/dist/processors/tfliteFrameProcessor.d.ts +90 -0
- package/dist/processors/tfliteFrameProcessor.js +213 -0
- package/dist/types/barcode.d.ts +91 -0
- package/dist/types/barcode.js +19 -0
- package/dist/types/detection.d.ts +166 -0
- package/dist/types/detection.js +8 -0
- package/dist/types/index.d.ts +126 -0
- package/dist/types/index.js +25 -0
- package/dist/types/ocr.d.ts +202 -0
- package/dist/types/ocr.js +8 -0
- package/dist/utils/imagePreprocessor.d.ts +85 -0
- package/dist/utils/imagePreprocessor.js +304 -0
- package/dist/utils/yoloProcessor.d.ts +40 -0
- package/dist/utils/yoloProcessor.js +154 -0
- package/package.json +78 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object Detection Types
|
|
3
|
+
*
|
|
4
|
+
* Types for visual product detection (fridge, pantry, spice rack scanning).
|
|
5
|
+
* Used with TFLite models for on-device inference.
|
|
6
|
+
*/
|
|
7
|
+
import type { BaseDetectionResult } from './index';
|
|
8
|
+
/**
|
|
9
|
+
* High-level product categories for detection
|
|
10
|
+
*/
|
|
11
|
+
export type ProductCategory = 'produce' | 'meat' | 'dairy' | 'packaged' | 'beverage' | 'condiment' | 'spice' | 'bakery' | 'frozen' | 'snack' | 'unknown';
|
|
12
|
+
/**
|
|
13
|
+
* Detailed produce types
|
|
14
|
+
*/
|
|
15
|
+
export type ProduceType = 'apple' | 'banana' | 'orange' | 'lemon' | 'lime' | 'tomato' | 'potato' | 'onion' | 'garlic' | 'carrot' | 'broccoli' | 'lettuce' | 'cucumber' | 'pepper' | 'avocado' | 'mango' | 'strawberry' | 'blueberry' | 'grape' | 'watermelon' | 'pineapple' | 'other_fruit' | 'other_vegetable';
|
|
16
|
+
/**
|
|
17
|
+
* Produce quality assessment
|
|
18
|
+
*/
|
|
19
|
+
export type ProduceQuality = 'fresh' | 'ripe' | 'overripe' | 'spoiled' | 'unknown';
|
|
20
|
+
/**
|
|
21
|
+
* Data for detected products
|
|
22
|
+
*/
|
|
23
|
+
export interface ProductData {
|
|
24
|
+
/** Primary category */
|
|
25
|
+
category: ProductCategory;
|
|
26
|
+
/** Specific item type if classified */
|
|
27
|
+
itemType?: string;
|
|
28
|
+
/** Subcategory for more detail */
|
|
29
|
+
subcategory?: string;
|
|
30
|
+
/** Detected brand name if visible */
|
|
31
|
+
brand?: string;
|
|
32
|
+
/** Product name if recognized */
|
|
33
|
+
name?: string;
|
|
34
|
+
/** Class label from the model */
|
|
35
|
+
classLabel: string;
|
|
36
|
+
/** Class index from the model */
|
|
37
|
+
classIndex: number;
|
|
38
|
+
/** Suggested matches from your product database */
|
|
39
|
+
suggestedMatches?: ProductMatch[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Suggested product match from database
|
|
43
|
+
*/
|
|
44
|
+
export interface ProductMatch {
|
|
45
|
+
/** Product ID in your database */
|
|
46
|
+
productId: string;
|
|
47
|
+
/** Product name */
|
|
48
|
+
name: string;
|
|
49
|
+
/** Match confidence (0-1) */
|
|
50
|
+
matchConfidence: number;
|
|
51
|
+
/** Image URL if available */
|
|
52
|
+
imageUrl?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extended data for produce items
|
|
56
|
+
*/
|
|
57
|
+
export interface ProduceData extends ProductData {
|
|
58
|
+
category: 'produce';
|
|
59
|
+
/** Specific produce type */
|
|
60
|
+
produceType: ProduceType;
|
|
61
|
+
/** Variety if identifiable (e.g., "Granny Smith" for apple) */
|
|
62
|
+
variety?: string;
|
|
63
|
+
/** Quality assessment */
|
|
64
|
+
quality: ProduceQuality;
|
|
65
|
+
/** Ripeness level (0-1) */
|
|
66
|
+
ripenessScore?: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Complete product detection result
|
|
70
|
+
*/
|
|
71
|
+
export interface ProductDetectionResult extends BaseDetectionResult {
|
|
72
|
+
type: 'product';
|
|
73
|
+
data: ProductData | ProduceData;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Model selection for detection
|
|
77
|
+
*/
|
|
78
|
+
export type DetectionModel = 'fast' | 'accurate';
|
|
79
|
+
/**
|
|
80
|
+
* Options for useProductDetector hook
|
|
81
|
+
*/
|
|
82
|
+
export interface UseProductDetectorOptions {
|
|
83
|
+
/** Model to use: 'fast' (on-device TFLite) or 'accurate' (server) */
|
|
84
|
+
model?: DetectionModel;
|
|
85
|
+
/** Maximum detections per image (default: 20) */
|
|
86
|
+
maxDetections?: number;
|
|
87
|
+
/** Minimum confidence threshold (default: 0.5) */
|
|
88
|
+
minConfidence?: number;
|
|
89
|
+
/** Categories to detect (default: all) */
|
|
90
|
+
categories?: ProductCategory[];
|
|
91
|
+
/** Enable server fallback for low-confidence results (default: true) */
|
|
92
|
+
serverFallback?: boolean;
|
|
93
|
+
/** Confidence threshold below which to use server (default: 0.4) */
|
|
94
|
+
serverFallbackThreshold?: number;
|
|
95
|
+
/** Server URL (uses MLVisionProvider config if not specified) */
|
|
96
|
+
serverUrl?: string;
|
|
97
|
+
/** Callback when products are detected */
|
|
98
|
+
onDetected?: (products: ProductDetectionResult[]) => void;
|
|
99
|
+
/** Callback on error */
|
|
100
|
+
onError?: (error: Error) => void;
|
|
101
|
+
/** Enable haptic feedback (default: true) */
|
|
102
|
+
hapticFeedback?: boolean;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* TensorflowModel type placeholder
|
|
106
|
+
* The actual type comes from react-native-fast-tflite
|
|
107
|
+
* This is intentionally loose to avoid type conflicts
|
|
108
|
+
*/
|
|
109
|
+
export type TensorflowModel = any;
|
|
110
|
+
/**
|
|
111
|
+
* Return type for useProductDetector hook
|
|
112
|
+
*/
|
|
113
|
+
export interface UseProductDetectorReturn {
|
|
114
|
+
/** Whether the model is loaded and ready */
|
|
115
|
+
isModelLoaded: boolean;
|
|
116
|
+
/** Whether currently detecting */
|
|
117
|
+
isDetecting: boolean;
|
|
118
|
+
/** Array of detected products */
|
|
119
|
+
detections: ProductDetectionResult[];
|
|
120
|
+
/** Current error if any */
|
|
121
|
+
error: Error | null;
|
|
122
|
+
/** Model version string */
|
|
123
|
+
modelVersion: string;
|
|
124
|
+
/** The loaded TFLite model (for frame processor use) */
|
|
125
|
+
model: TensorflowModel | null;
|
|
126
|
+
/** Detect products in a photo */
|
|
127
|
+
detectProducts: (uri: string) => Promise<ProductDetectionResult[]>;
|
|
128
|
+
/** Detect products in current camera frame */
|
|
129
|
+
detectInFrame: () => Promise<ProductDetectionResult[]>;
|
|
130
|
+
/** Check for and download model updates */
|
|
131
|
+
updateModel: () => Promise<void>;
|
|
132
|
+
/** Clear all detections */
|
|
133
|
+
clearDetections: () => void;
|
|
134
|
+
frameProcessor: unknown;
|
|
135
|
+
modelInfo: {
|
|
136
|
+
name: string;
|
|
137
|
+
version: string;
|
|
138
|
+
sizeBytes: number;
|
|
139
|
+
lastUpdated: Date;
|
|
140
|
+
type: 'detection';
|
|
141
|
+
isLoaded: boolean;
|
|
142
|
+
} | null;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* TFLite model output format (YOLOv8 style)
|
|
146
|
+
*/
|
|
147
|
+
export interface TFLiteDetectionOutput {
|
|
148
|
+
/** Bounding boxes [x, y, w, h] normalized 0-1 */
|
|
149
|
+
boxes: number[][];
|
|
150
|
+
/** Class indices */
|
|
151
|
+
classes: number[];
|
|
152
|
+
/** Confidence scores */
|
|
153
|
+
scores: number[];
|
|
154
|
+
/** Number of detections */
|
|
155
|
+
numDetections: number;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Class label mapping for the model
|
|
159
|
+
*/
|
|
160
|
+
export interface ClassLabelMap {
|
|
161
|
+
[classIndex: number]: {
|
|
162
|
+
label: string;
|
|
163
|
+
category: ProductCategory;
|
|
164
|
+
subcategory?: string;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @souschef/ml-vision Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Core types for the ML Vision package. These types are designed to be
|
|
5
|
+
* compatible with your existing Sous Chef app patterns.
|
|
6
|
+
*/
|
|
7
|
+
export * from './barcode';
|
|
8
|
+
export * from './detection';
|
|
9
|
+
export * from './ocr';
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for the MLVisionProvider
|
|
12
|
+
*/
|
|
13
|
+
export interface MLVisionConfig {
|
|
14
|
+
/** URL for the ML inference server (your Docker server) */
|
|
15
|
+
serverUrl?: string;
|
|
16
|
+
/** Timeout for server requests in milliseconds (default: 5000) */
|
|
17
|
+
serverTimeout?: number;
|
|
18
|
+
/** Enable MMKV caching for results (default: true) */
|
|
19
|
+
cacheEnabled?: boolean;
|
|
20
|
+
/** Cache TTL in milliseconds (default: 24 hours) */
|
|
21
|
+
cacheTTL?: number;
|
|
22
|
+
/** Check for model updates on app start (default: true) */
|
|
23
|
+
modelUpdateCheck?: boolean;
|
|
24
|
+
/** Enable GPU delegates for on-device inference (default: true) */
|
|
25
|
+
enableGPUDelegate?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Bounding box for detected items
|
|
29
|
+
*/
|
|
30
|
+
export interface BoundingBox {
|
|
31
|
+
/** X coordinate (0-1 normalized) */
|
|
32
|
+
x: number;
|
|
33
|
+
/** Y coordinate (0-1 normalized) */
|
|
34
|
+
y: number;
|
|
35
|
+
/** Width (0-1 normalized) */
|
|
36
|
+
width: number;
|
|
37
|
+
/** Height (0-1 normalized) */
|
|
38
|
+
height: number;
|
|
39
|
+
/** Rotation in degrees (optional) */
|
|
40
|
+
rotation?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Base detection result that all specific results extend
|
|
44
|
+
*/
|
|
45
|
+
export interface BaseDetectionResult {
|
|
46
|
+
/** Unique identifier for this detection */
|
|
47
|
+
id: string;
|
|
48
|
+
/** Confidence score (0-1) */
|
|
49
|
+
confidence: number;
|
|
50
|
+
/** Bounding box in the image */
|
|
51
|
+
boundingBox?: BoundingBox;
|
|
52
|
+
/** Whether this was processed on-device or via server */
|
|
53
|
+
source: 'on_device' | 'server';
|
|
54
|
+
/** Processing time in milliseconds */
|
|
55
|
+
processingTimeMs: number;
|
|
56
|
+
/** Timestamp of detection */
|
|
57
|
+
timestamp: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Information about a loaded ML model
|
|
61
|
+
*/
|
|
62
|
+
export interface ModelInfo {
|
|
63
|
+
/** Model identifier */
|
|
64
|
+
id: string;
|
|
65
|
+
/** Human-readable name */
|
|
66
|
+
name: string;
|
|
67
|
+
/** Semantic version */
|
|
68
|
+
version: string;
|
|
69
|
+
/** File size in bytes */
|
|
70
|
+
sizeBytes: number;
|
|
71
|
+
/** When the model was last updated */
|
|
72
|
+
lastUpdated: Date;
|
|
73
|
+
/** Model type */
|
|
74
|
+
type: 'detection' | 'classification' | 'ocr';
|
|
75
|
+
/** Whether the model is currently loaded */
|
|
76
|
+
isLoaded: boolean;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Model download progress
|
|
80
|
+
*/
|
|
81
|
+
export interface ModelDownloadProgress {
|
|
82
|
+
modelId: string;
|
|
83
|
+
bytesDownloaded: number;
|
|
84
|
+
totalBytes: number;
|
|
85
|
+
progress: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Cache entry wrapper
|
|
89
|
+
*/
|
|
90
|
+
export interface CacheEntry<T> {
|
|
91
|
+
data: T;
|
|
92
|
+
timestamp: number;
|
|
93
|
+
ttl: number;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Cache statistics
|
|
97
|
+
*/
|
|
98
|
+
export interface CacheStats {
|
|
99
|
+
barcodeEntries: number;
|
|
100
|
+
productEntries: number;
|
|
101
|
+
receiptEntries: number;
|
|
102
|
+
totalSizeBytes: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Server health response
|
|
106
|
+
*/
|
|
107
|
+
export interface ServerHealthResponse {
|
|
108
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
109
|
+
version: string;
|
|
110
|
+
models: {
|
|
111
|
+
id: string;
|
|
112
|
+
loaded: boolean;
|
|
113
|
+
lastUsed?: string;
|
|
114
|
+
}[];
|
|
115
|
+
gpuAvailable: boolean;
|
|
116
|
+
gpuMemoryUsed?: number;
|
|
117
|
+
gpuMemoryTotal?: number;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Server error response
|
|
121
|
+
*/
|
|
122
|
+
export interface ServerErrorResponse {
|
|
123
|
+
error: string;
|
|
124
|
+
code: string;
|
|
125
|
+
details?: Record<string, unknown>;
|
|
126
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @souschef/ml-vision Type Definitions
|
|
4
|
+
*
|
|
5
|
+
* Core types for the ML Vision package. These types are designed to be
|
|
6
|
+
* compatible with your existing Sous Chef app patterns.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
__exportStar(require("./barcode"), exports);
|
|
24
|
+
__exportStar(require("./detection"), exports);
|
|
25
|
+
__exportStar(require("./ocr"), exports);
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OCR and Receipt Scanning Types
|
|
3
|
+
*
|
|
4
|
+
* Types for text recognition and receipt parsing functionality.
|
|
5
|
+
* Uses MLKit Text Recognition on-device with server fallback.
|
|
6
|
+
*/
|
|
7
|
+
import type { BaseDetectionResult, BoundingBox } from './index';
|
|
8
|
+
/**
|
|
9
|
+
* A line of recognized text
|
|
10
|
+
*/
|
|
11
|
+
export interface TextLine {
|
|
12
|
+
/** The recognized text content */
|
|
13
|
+
text: string;
|
|
14
|
+
/** Confidence score (0-1) */
|
|
15
|
+
confidence: number;
|
|
16
|
+
/** Bounding box of the text line */
|
|
17
|
+
boundingBox: BoundingBox;
|
|
18
|
+
/** Language code if detected */
|
|
19
|
+
language?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A block of text (paragraph)
|
|
23
|
+
*/
|
|
24
|
+
export interface TextBlock {
|
|
25
|
+
/** All text in the block */
|
|
26
|
+
text: string;
|
|
27
|
+
/** Individual lines */
|
|
28
|
+
lines: TextLine[];
|
|
29
|
+
/** Bounding box of the entire block */
|
|
30
|
+
boundingBox: BoundingBox;
|
|
31
|
+
/** Confidence score (0-1) */
|
|
32
|
+
confidence: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Complete text recognition result
|
|
36
|
+
*/
|
|
37
|
+
export interface TextRecognitionResult {
|
|
38
|
+
/** All recognized text concatenated */
|
|
39
|
+
fullText: string;
|
|
40
|
+
/** Text blocks (paragraphs) */
|
|
41
|
+
blocks: TextBlock[];
|
|
42
|
+
/** All lines across all blocks */
|
|
43
|
+
lines: TextLine[];
|
|
44
|
+
/** Detected language */
|
|
45
|
+
language?: string;
|
|
46
|
+
/** Overall confidence */
|
|
47
|
+
confidence: number;
|
|
48
|
+
/** Processing source */
|
|
49
|
+
source: 'on_device' | 'server';
|
|
50
|
+
/** Processing time in ms */
|
|
51
|
+
processingTimeMs: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A parsed item from a receipt
|
|
55
|
+
*/
|
|
56
|
+
export interface ReceiptItem {
|
|
57
|
+
/** Item name as it appears on receipt */
|
|
58
|
+
name: string;
|
|
59
|
+
/** Cleaned/normalized item name */
|
|
60
|
+
normalizedName?: string;
|
|
61
|
+
/** Quantity purchased */
|
|
62
|
+
quantity?: number;
|
|
63
|
+
/** Unit of measurement */
|
|
64
|
+
unit?: string;
|
|
65
|
+
/** Price per unit */
|
|
66
|
+
unitPrice?: number;
|
|
67
|
+
/** Total price for this item */
|
|
68
|
+
totalPrice?: number;
|
|
69
|
+
/** Confidence in the parsing (0-1) */
|
|
70
|
+
confidence: number;
|
|
71
|
+
/** Original text from receipt */
|
|
72
|
+
rawText: string;
|
|
73
|
+
/** Line number in receipt */
|
|
74
|
+
lineNumber: number;
|
|
75
|
+
/** Whether this item needs manual review */
|
|
76
|
+
needsReview: boolean;
|
|
77
|
+
/** Suggested product matches from database */
|
|
78
|
+
suggestedMatches?: {
|
|
79
|
+
productId: string;
|
|
80
|
+
name: string;
|
|
81
|
+
confidence: number;
|
|
82
|
+
}[];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Receipt metadata
|
|
86
|
+
*/
|
|
87
|
+
export interface ReceiptMetadata {
|
|
88
|
+
/** Store name if detected */
|
|
89
|
+
storeName?: string;
|
|
90
|
+
/** Store location/address */
|
|
91
|
+
storeAddress?: string;
|
|
92
|
+
/** Receipt date if detected */
|
|
93
|
+
date?: Date;
|
|
94
|
+
/** Receipt time */
|
|
95
|
+
time?: string;
|
|
96
|
+
/** Transaction/receipt number */
|
|
97
|
+
transactionId?: string;
|
|
98
|
+
/** Subtotal before tax */
|
|
99
|
+
subtotal?: number;
|
|
100
|
+
/** Tax amount */
|
|
101
|
+
tax?: number;
|
|
102
|
+
/** Total amount */
|
|
103
|
+
total?: number;
|
|
104
|
+
/** Payment method */
|
|
105
|
+
paymentMethod?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Complete receipt scan result
|
|
109
|
+
*/
|
|
110
|
+
export interface ReceiptScanResult extends BaseDetectionResult {
|
|
111
|
+
type: 'receipt';
|
|
112
|
+
/** Parsed items from the receipt */
|
|
113
|
+
items: ReceiptItem[];
|
|
114
|
+
/** Receipt metadata */
|
|
115
|
+
metadata: ReceiptMetadata;
|
|
116
|
+
/** Raw OCR result */
|
|
117
|
+
rawText: string;
|
|
118
|
+
/** All text lines */
|
|
119
|
+
textLines: TextLine[];
|
|
120
|
+
/** Overall parsing confidence */
|
|
121
|
+
confidence: number;
|
|
122
|
+
/** Number of items that need review */
|
|
123
|
+
itemsNeedingReview: number;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Known store formats for optimized parsing
|
|
127
|
+
*/
|
|
128
|
+
export type KnownStore = 'walmart' | 'target' | 'kroger' | 'safeway' | 'costco' | 'trader_joes' | 'whole_foods' | 'publix' | 'aldi' | 'unknown';
|
|
129
|
+
/**
|
|
130
|
+
* Options for useReceiptScanner hook
|
|
131
|
+
*/
|
|
132
|
+
export interface UseReceiptScannerOptions {
|
|
133
|
+
/** Enable server fallback for complex receipts (default: true) */
|
|
134
|
+
serverFallback?: boolean;
|
|
135
|
+
/** Server URL (uses MLVisionProvider config if not specified) */
|
|
136
|
+
serverUrl?: string;
|
|
137
|
+
/** Minimum confidence to accept an item (default: 0.7) */
|
|
138
|
+
minConfidence?: number;
|
|
139
|
+
/** Known store formats for optimized parsing */
|
|
140
|
+
recognizedStores?: KnownStore[];
|
|
141
|
+
/** Callback when items are detected */
|
|
142
|
+
onItemDetected?: (item: ReceiptItem) => void;
|
|
143
|
+
/** Callback when parsing is complete */
|
|
144
|
+
onParseComplete?: (result: ReceiptScanResult) => void;
|
|
145
|
+
/** Callback on error */
|
|
146
|
+
onError?: (error: Error) => void;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Return type for useReceiptScanner hook
|
|
150
|
+
*/
|
|
151
|
+
export interface UseReceiptScannerReturn {
|
|
152
|
+
/** Whether currently processing */
|
|
153
|
+
isProcessing: boolean;
|
|
154
|
+
/** Parsed receipt items */
|
|
155
|
+
items: ReceiptItem[];
|
|
156
|
+
/** Receipt metadata */
|
|
157
|
+
metadata: ReceiptMetadata | null;
|
|
158
|
+
/** Raw OCR text */
|
|
159
|
+
rawText: string;
|
|
160
|
+
/** Overall confidence */
|
|
161
|
+
confidence: number;
|
|
162
|
+
/** Processing source */
|
|
163
|
+
source: 'on_device' | 'server' | null;
|
|
164
|
+
/** Current error if any */
|
|
165
|
+
error: Error | null;
|
|
166
|
+
/** Scan a receipt photo */
|
|
167
|
+
scanReceipt: (uri: string) => Promise<ReceiptScanResult>;
|
|
168
|
+
/** Scan current camera frame */
|
|
169
|
+
scanFrame: () => Promise<ReceiptScanResult>;
|
|
170
|
+
/** Confirm an item is correct */
|
|
171
|
+
confirmItem: (item: ReceiptItem) => void;
|
|
172
|
+
/** Reject/remove an item */
|
|
173
|
+
rejectItem: (item: ReceiptItem) => void;
|
|
174
|
+
/** Edit an item */
|
|
175
|
+
editItem: (item: ReceiptItem, updates: Partial<ReceiptItem>) => void;
|
|
176
|
+
/** Clear all results */
|
|
177
|
+
clearResults: () => void;
|
|
178
|
+
frameProcessor: unknown;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Receipt line classification
|
|
182
|
+
*/
|
|
183
|
+
export type ReceiptLineType = 'item' | 'subtotal' | 'tax' | 'total' | 'payment' | 'store_info' | 'date_time' | 'transaction' | 'discount' | 'unknown';
|
|
184
|
+
/**
|
|
185
|
+
* Parsed receipt line before item extraction
|
|
186
|
+
*/
|
|
187
|
+
export interface ParsedReceiptLine {
|
|
188
|
+
/** Original text */
|
|
189
|
+
text: string;
|
|
190
|
+
/** Classified line type */
|
|
191
|
+
type: ReceiptLineType;
|
|
192
|
+
/** Extracted values */
|
|
193
|
+
values: {
|
|
194
|
+
name?: string;
|
|
195
|
+
quantity?: number;
|
|
196
|
+
price?: number;
|
|
197
|
+
};
|
|
198
|
+
/** Line number */
|
|
199
|
+
lineNumber: number;
|
|
200
|
+
/** Confidence in classification */
|
|
201
|
+
confidence: number;
|
|
202
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Preprocessor for TFLite Models
|
|
3
|
+
*
|
|
4
|
+
* Converts images to the format expected by TFLite models:
|
|
5
|
+
* - Resized to model input size (e.g., 640x640)
|
|
6
|
+
* - Normalized to [0, 1] range
|
|
7
|
+
* - As Float32Array in NHWC format (batch, height, width, channels)
|
|
8
|
+
*
|
|
9
|
+
* This implementation uses react-native-skia for image manipulation.
|
|
10
|
+
* Install with: npm install @shopify/react-native-skia
|
|
11
|
+
*/
|
|
12
|
+
export interface PreprocessOptions {
|
|
13
|
+
/** Target width (default: 640) */
|
|
14
|
+
width?: number;
|
|
15
|
+
/** Target height (default: 640) */
|
|
16
|
+
height?: number;
|
|
17
|
+
/** Normalize to [0, 1] range (default: true) */
|
|
18
|
+
normalize?: boolean;
|
|
19
|
+
/** Whether to apply letterboxing to maintain aspect ratio (default: true) */
|
|
20
|
+
letterbox?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface PreprocessResult {
|
|
23
|
+
/** Preprocessed pixel data as Float32Array */
|
|
24
|
+
data: Float32Array;
|
|
25
|
+
/** Original image width */
|
|
26
|
+
originalWidth: number;
|
|
27
|
+
/** Original image height */
|
|
28
|
+
originalHeight: number;
|
|
29
|
+
/** Scale factors for mapping back to original */
|
|
30
|
+
scale: {
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
};
|
|
34
|
+
/** Padding applied (if letterboxing) */
|
|
35
|
+
padding: {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Preprocess an image for TFLite model inference
|
|
42
|
+
*
|
|
43
|
+
* @param uri Image URI (file:// or http://)
|
|
44
|
+
* @param options Preprocessing options
|
|
45
|
+
* @returns Preprocessed image data
|
|
46
|
+
*/
|
|
47
|
+
export declare function preprocessImage(uri: string, options?: PreprocessOptions): Promise<PreprocessResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Preprocess a VisionCamera frame for TFLite inference
|
|
50
|
+
*
|
|
51
|
+
* This requires vision-camera-resize-plugin to be installed:
|
|
52
|
+
* npm install vision-camera-resize-plugin
|
|
53
|
+
*
|
|
54
|
+
* Usage in a frame processor:
|
|
55
|
+
* ```
|
|
56
|
+
* const frameProcessor = useFrameProcessor((frame) => {
|
|
57
|
+
* 'worklet';
|
|
58
|
+
* const resized = resize(frame, {
|
|
59
|
+
* size: { width: 640, height: 640 },
|
|
60
|
+
* pixelFormat: 'rgb',
|
|
61
|
+
* dataType: 'float32',
|
|
62
|
+
* });
|
|
63
|
+
* const result = model.runSync([resized]);
|
|
64
|
+
* // Process result...
|
|
65
|
+
* }, [model]);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function getFrameProcessorInstructions(): string;
|
|
69
|
+
/**
|
|
70
|
+
* Convert Float32Array from HWC to NHWC format (add batch dimension)
|
|
71
|
+
*/
|
|
72
|
+
export declare function addBatchDimension(data: Float32Array): Float32Array;
|
|
73
|
+
/**
|
|
74
|
+
* Check if Skia is available for image preprocessing
|
|
75
|
+
*/
|
|
76
|
+
export declare function isSkiaAvailable(): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Initialize Skia module (call before using Skia-dependent functions)
|
|
79
|
+
* @returns true if Skia was loaded successfully
|
|
80
|
+
*/
|
|
81
|
+
export declare function initSkia(): Promise<boolean>;
|
|
82
|
+
/**
|
|
83
|
+
* Check if resize plugin is available for frame processing
|
|
84
|
+
*/
|
|
85
|
+
export declare function isResizePluginAvailable(): Promise<boolean>;
|