@exige/web-scanner-sdk 0.2.9
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 +330 -0
- package/dist/assets/document-worker.js +2 -0
- package/dist/assets/document-worker.js.map +1 -0
- package/dist/assets/ort-wasm-simd-threaded.jsep.mjs +108 -0
- package/dist/assets/ort-wasm-simd-threaded.jsep.wasm +0 -0
- package/dist/assets/ort.min.js +2937 -0
- package/dist/assets/ort.min.js.map +1 -0
- package/dist/assets/tesseract/eng.traineddata.LICENSE +201 -0
- package/dist/assets/tesseract/eng.traineddata.NOTICE +9 -0
- package/dist/assets/tesseract/eng.traineddata.gz +0 -0
- package/dist/assets/tesseract/tesseract-core-lstm.wasm.js +191 -0
- package/dist/assets/tesseract/tesseract-core-relaxedsimd-lstm.wasm.js +191 -0
- package/dist/assets/tesseract/tesseract-core-simd-lstm.wasm.js +191 -0
- package/dist/assets/tesseract/tesseract.js-core.LICENSE +202 -0
- package/dist/assets/tesseract/tesseract.js.LICENSE +201 -0
- package/dist/assets/tesseract/worker.min.js +3 -0
- package/dist/assets/tesseract/worker.min.js.LICENSE.txt +12 -0
- package/dist/assets-manifest.json +11 -0
- package/dist/components/ModelDownloadRing.d.ts +4 -0
- package/dist/components/scanner-camera-overlay.css +2 -0
- package/dist/finder-DFueuWuS.js +1225 -0
- package/dist/finder-DFueuWuS.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/live-overlay-geometry.d.ts +11 -0
- package/dist/react/context.d.ts +2 -0
- package/dist/react/hooks.d.ts +3 -0
- package/dist/react/parts.d.ts +16 -0
- package/dist/react/scanner-context.d.ts +5 -0
- package/dist/react/types.d.ts +113 -0
- package/dist/react.d.ts +4 -0
- package/dist/react.js +594 -0
- package/dist/react.js.map +1 -0
- package/dist/scanner-sdk.js +1001 -0
- package/dist/scanner-sdk.js.map +1 -0
- package/dist/sdk/camera.d.ts +150 -0
- package/dist/sdk/display-quad.d.ts +23 -0
- package/dist/sdk/errors.d.ts +14 -0
- package/dist/sdk/face-model.d.ts +22 -0
- package/dist/sdk/field-model.d.ts +29 -0
- package/dist/sdk/finder-simulator.d.ts +17 -0
- package/dist/sdk/finder.d.ts +174 -0
- package/dist/sdk/frame-geometry.d.ts +6 -0
- package/dist/sdk/image.d.ts +18 -0
- package/dist/sdk/license-codec.d.ts +2 -0
- package/dist/sdk/license-public-key.d.ts +9 -0
- package/dist/sdk/license-runtime.d.ts +2 -0
- package/dist/sdk/license.d.ts +84 -0
- package/dist/sdk/lighting.d.ts +22 -0
- package/dist/sdk/model-download.d.ts +25 -0
- package/dist/sdk/ocr-runtime.d.ts +27 -0
- package/dist/sdk/ocr.d.ts +104 -0
- package/dist/sdk/ort-runtime.d.ts +23 -0
- package/dist/sdk/programmatic-redaction.d.ts +151 -0
- package/dist/sdk/redact.d.ts +17 -0
- package/dist/sdk/scan.d.ts +61 -0
- package/dist/sdk/types.d.ts +80 -0
- package/package.json +93 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { type ScanOptions } from './scan';
|
|
2
|
+
import type { DocumentDetectionResult, DocumentModelStatus, DocumentQuad } from './types';
|
|
3
|
+
export type AutoCaptureMode = 'defaultOn' | 'defaultOff' | 'alwaysOn' | 'alwaysOff' | 'only';
|
|
4
|
+
export type FinderSource = HTMLVideoElement | MediaStream | HTMLCanvasElement;
|
|
5
|
+
export type FinderState = 'seeking' | 'detecting' | 'unstable' | 'ready' | 'captured';
|
|
6
|
+
export type FinderGuidanceReason = 'place-document' | 'move-closer' | 'move-farther-away' | 'straighten-camera' | 'hold-still' | 'ready';
|
|
7
|
+
export interface QuadFill {
|
|
8
|
+
/** Raw quad bounds width divided by the analysis frame width. */
|
|
9
|
+
widthFill: number;
|
|
10
|
+
/** Raw quad bounds height divided by the analysis frame height. */
|
|
11
|
+
heightFill: number;
|
|
12
|
+
/** Fill on the limiting axis: `max(widthFill, heightFill)`. */
|
|
13
|
+
limitingFill: number;
|
|
14
|
+
/** Shoelace polygon area divided by the analysis frame area. Diagnostic only. */
|
|
15
|
+
areaFill: number;
|
|
16
|
+
/** Long side divided by short side of the raw quad. */
|
|
17
|
+
aspectRatio: number;
|
|
18
|
+
}
|
|
19
|
+
export interface FinderGuidance {
|
|
20
|
+
hint: string;
|
|
21
|
+
reason: FinderGuidanceReason;
|
|
22
|
+
/**
|
|
23
|
+
* Fill on the limiting axis of the raw quad: the larger of its width and
|
|
24
|
+
* height fill. A tall receipt that fills the frame height is fully framed
|
|
25
|
+
* even though its bounding box covers little frame area.
|
|
26
|
+
*/
|
|
27
|
+
fillRatio: number;
|
|
28
|
+
/** Component fills, polygon area fill, and aspect ratio behind `fillRatio`. */
|
|
29
|
+
fill: QuadFill;
|
|
30
|
+
readyForAutoCapture: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface FinderLighting {
|
|
33
|
+
castShadow: boolean;
|
|
34
|
+
strength: number;
|
|
35
|
+
hint?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function selectFinderHint(guidance: FinderGuidance, lighting: FinderLighting): string;
|
|
38
|
+
export interface AutoCaptureControl {
|
|
39
|
+
visible: boolean;
|
|
40
|
+
checked: boolean;
|
|
41
|
+
mutable: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface FinderStatus {
|
|
44
|
+
state: FinderState;
|
|
45
|
+
confidence: number;
|
|
46
|
+
quad?: DocumentQuad;
|
|
47
|
+
guidance: FinderGuidance;
|
|
48
|
+
lighting: FinderLighting;
|
|
49
|
+
stableFrames: number;
|
|
50
|
+
requiredStableFrames: number;
|
|
51
|
+
autoCapture: AutoCaptureControl;
|
|
52
|
+
sourceWidth?: number;
|
|
53
|
+
sourceHeight?: number;
|
|
54
|
+
detector?: DocumentDetectionResult['detector'];
|
|
55
|
+
modelStatus?: DocumentModelStatus;
|
|
56
|
+
modelProvider?: DocumentDetectionResult['modelProvider'];
|
|
57
|
+
modelError?: string;
|
|
58
|
+
inferenceMs?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface FinderCapture {
|
|
61
|
+
frame: HTMLCanvasElement;
|
|
62
|
+
detection?: DocumentDetectionResult;
|
|
63
|
+
reason: 'auto' | 'manual';
|
|
64
|
+
}
|
|
65
|
+
export interface FinderOptions {
|
|
66
|
+
source: FinderSource;
|
|
67
|
+
autoCapture: AutoCaptureMode;
|
|
68
|
+
/** Supplies the final full-resolution frame while finder analysis stays bounded. */
|
|
69
|
+
captureFrame?: () => HTMLCanvasElement | Promise<HTMLCanvasElement>;
|
|
70
|
+
onStatus?: (status: FinderStatus) => void;
|
|
71
|
+
onCapture?: (capture: FinderCapture) => void | Promise<void>;
|
|
72
|
+
/** Reports capture failures, including automatic captures, instead of swallowing them. */
|
|
73
|
+
onCaptureError?: (error: Error) => void;
|
|
74
|
+
/** Consecutive stable raw detections required. Defaults to 4. */
|
|
75
|
+
stableFrames?: number;
|
|
76
|
+
/** Minimum detector confidence on the normalized 0–1 scale. Defaults to 0.72. */
|
|
77
|
+
confidenceThreshold?: number;
|
|
78
|
+
/** Maximum normalized corner movement while entering ready. Defaults to 0.024. */
|
|
79
|
+
cornerTolerance?: number;
|
|
80
|
+
/** Movement allowed after ready before dropping out. Defaults to 0.036. */
|
|
81
|
+
exitCornerTolerance?: number;
|
|
82
|
+
intervalMs?: number;
|
|
83
|
+
maxFrameDimension?: number;
|
|
84
|
+
guidance?: FinderGuidanceOptions;
|
|
85
|
+
detection?: ScanOptions;
|
|
86
|
+
playShutterSound?: boolean;
|
|
87
|
+
}
|
|
88
|
+
export interface FinderSession {
|
|
89
|
+
stop: () => void;
|
|
90
|
+
capture: () => Promise<FinderCapture>;
|
|
91
|
+
setAutoCapture: (enabled: boolean) => boolean;
|
|
92
|
+
getStatus: () => FinderStatus;
|
|
93
|
+
}
|
|
94
|
+
export declare function snapshotBeforeCaptureFeedback<T>(snapshot: () => T | Promise<T>, feedback: () => void): Promise<T>;
|
|
95
|
+
export declare function autoCaptureControl(mode: AutoCaptureMode): AutoCaptureControl;
|
|
96
|
+
export interface StabilityOptions {
|
|
97
|
+
stableFrames: number;
|
|
98
|
+
confidenceThreshold: number;
|
|
99
|
+
cornerTolerance: number;
|
|
100
|
+
exitCornerTolerance?: number;
|
|
101
|
+
}
|
|
102
|
+
export interface FinderGuidanceOptions {
|
|
103
|
+
confidenceThreshold?: number;
|
|
104
|
+
/** Limiting-axis fill required to enter ready. Defaults to 0.72. */
|
|
105
|
+
minFillRatio?: number;
|
|
106
|
+
/** Limiting-axis fill allowed after ready before exiting. Defaults to 0.64. */
|
|
107
|
+
exitFillRatio?: number;
|
|
108
|
+
/** Long-to-short side ratio that makes a document high-aspect. Defaults to 2.2. */
|
|
109
|
+
highAspectRatio?: number;
|
|
110
|
+
/** Long-side fill required to enter ready on a high-aspect document. Defaults to 0.8. */
|
|
111
|
+
highAspectFillRatio?: number;
|
|
112
|
+
/** Long-side fill allowed after ready on a high-aspect document. Defaults to 0.72. */
|
|
113
|
+
highAspectExitFillRatio?: number;
|
|
114
|
+
/** Edge clearance required to enter ready. Defaults to 0.015. */
|
|
115
|
+
edgeMarginRatio?: number;
|
|
116
|
+
/** Edge clearance allowed after ready. Defaults to 0.005. */
|
|
117
|
+
exitEdgeMarginRatio?: number;
|
|
118
|
+
/** Opposite-edge ratio required to enter ready. Defaults to 0.48. */
|
|
119
|
+
minPerspectiveRatio?: number;
|
|
120
|
+
/** Opposite-edge ratio allowed after ready. Defaults to 0.4. */
|
|
121
|
+
exitMinPerspectiveRatio?: number;
|
|
122
|
+
}
|
|
123
|
+
export declare const DEFAULT_FINDER_STABLE_FRAMES = 4;
|
|
124
|
+
export declare const DEFAULT_FINDER_CONFIDENCE_THRESHOLD = 0.72;
|
|
125
|
+
export declare const DEFAULT_FINDER_CORNER_TOLERANCE = 0.024;
|
|
126
|
+
export declare const DEFAULT_FINDER_EXIT_CORNER_TOLERANCE = 0.036;
|
|
127
|
+
export declare const DEFAULT_FINDER_MIN_FILL_RATIO = 0.72;
|
|
128
|
+
export declare const DEFAULT_FINDER_EXIT_FILL_RATIO = 0.64;
|
|
129
|
+
export declare const DEFAULT_FINDER_HIGH_ASPECT_RATIO = 2.2;
|
|
130
|
+
/** Extra long-side fill asked of a high-aspect document, above the base target. */
|
|
131
|
+
export declare const DEFAULT_FINDER_HIGH_ASPECT_FILL_MARGIN = 0.08;
|
|
132
|
+
export declare const DEFAULT_FINDER_EDGE_MARGIN_RATIO = 0.015;
|
|
133
|
+
export declare const DEFAULT_FINDER_EXIT_EDGE_MARGIN_RATIO = 0.005;
|
|
134
|
+
export declare const DEFAULT_FINDER_MIN_PERSPECTIVE_RATIO = 0.48;
|
|
135
|
+
export declare const DEFAULT_FINDER_EXIT_MIN_PERSPECTIVE_RATIO = 0.4;
|
|
136
|
+
/**
|
|
137
|
+
* Measures how much of each frame axis the raw quad occupies. A document can
|
|
138
|
+
* only grow until its limiting axis reaches a frame edge, so the larger of the
|
|
139
|
+
* two axis fills — not the bounding-box area — describes how well it is framed.
|
|
140
|
+
*/
|
|
141
|
+
export declare function measureQuadFill(quad: DocumentQuad, frameWidth: number, frameHeight: number): QuadFill;
|
|
142
|
+
/**
|
|
143
|
+
* Fill the limiting axis must reach. High-aspect documents are asked for a
|
|
144
|
+
* little more of the long side, because their short side can never fill and
|
|
145
|
+
* the long side is the only axis carrying resolution. The target never exceeds
|
|
146
|
+
* what the edge margin physically allows.
|
|
147
|
+
*/
|
|
148
|
+
export declare function limitingFillTarget(fill: QuadFill, previouslyReady: boolean, edgeMarginRatio: number, options?: FinderGuidanceOptions): number;
|
|
149
|
+
export declare function selectFinderGuidance(detection: DocumentDetectionResult, stability: {
|
|
150
|
+
ready: boolean;
|
|
151
|
+
previouslyReady?: boolean;
|
|
152
|
+
}, options?: FinderGuidanceOptions): FinderGuidance;
|
|
153
|
+
export declare class QuadStabilityTracker {
|
|
154
|
+
private previous?;
|
|
155
|
+
private count;
|
|
156
|
+
private ready;
|
|
157
|
+
private readonly options;
|
|
158
|
+
constructor(options: StabilityOptions);
|
|
159
|
+
reset(): void;
|
|
160
|
+
update(detection: DocumentDetectionResult): {
|
|
161
|
+
stableFrames: number;
|
|
162
|
+
ready: boolean;
|
|
163
|
+
movement: number;
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Watches a camera or canvas for a stable document.
|
|
168
|
+
* Detection quality is reported on `FinderStatus`, not thrown.
|
|
169
|
+
* Worker startup and DocAligner HTTP failures are caught on each tick and
|
|
170
|
+
* reported as `modelStatus: 'failed'` with `modelError`. The camera stays up.
|
|
171
|
+
*
|
|
172
|
+
* @throws {LicenseError} LicenseError when the scan feature is not licensed. The finder does not start.
|
|
173
|
+
*/
|
|
174
|
+
export declare function startFinder(options: FinderOptions): Promise<FinderSession>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ImageSource } from './types';
|
|
2
|
+
export interface CanvasSourceOptions {
|
|
3
|
+
cloneCanvas?: boolean;
|
|
4
|
+
maxDimension?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function sourceToCanvas(source: ImageSource, options?: CanvasSourceOptions): Promise<HTMLCanvasElement>;
|
|
7
|
+
export declare function canvasToBlob(canvas: HTMLCanvasElement, type?: string, quality?: number): Promise<Blob>;
|
|
8
|
+
export declare function clampBox(box: {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}, width: number, height: number): {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw Ed25519 public key: 32 bytes, base64url, no padding.
|
|
3
|
+
*
|
|
4
|
+
* The license portal signs with `LICENSE_SIGNING_PRIVATE_KEY`.
|
|
5
|
+
* Generate a pair with `npm run generate-keypair --prefix license-portal`,
|
|
6
|
+
* then replace this constant with the printed public key and rebuild the
|
|
7
|
+
* library. Never commit the private key.
|
|
8
|
+
*/
|
|
9
|
+
export declare const LICENSE_PUBLIC_KEY_BASE64 = "uFpA_UXGk-1AjjG31cFP6cqXOQX0w2TnuR7Bl-msZ6I";
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hosts that may use the SDK before a paid license exists.
|
|
3
|
+
* Add a production hostname here when it should run without a signed key.
|
|
4
|
+
*
|
|
5
|
+
* An entry is either an exact hostname or a single `*.suffix` pattern.
|
|
6
|
+
* `*.exige.io` matches `exige.io` and any host that ends with `.exige.io`.
|
|
7
|
+
* It does not match `exige.io.evil.com`. Other entries are exact:
|
|
8
|
+
* `exige-park-app.ngrok.io` does not allow the rest of ngrok, and nothing
|
|
9
|
+
* here allows `*.vercel.app`. Paid license `domains` stay exact hostnames.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEV_LICENSE_HOSTS: readonly ["localhost", "127.0.0.1", "exige-scanner-sdk.vercel.app", "exige-park-app.ngrok.io", "*.exige.io"];
|
|
12
|
+
export declare const LICENSE_FEATURES: readonly ["scan", "ocr", "redaction", "vehicles", "torch"];
|
|
13
|
+
export type LicenseFeature = (typeof LICENSE_FEATURES)[number];
|
|
14
|
+
export type LicenseErrorCode = 'missing' | 'malformed' | 'invalid-signature' | 'expired' | 'domain' | 'feature';
|
|
15
|
+
export interface LicenseFeatures {
|
|
16
|
+
scan: boolean;
|
|
17
|
+
ocr: boolean;
|
|
18
|
+
redaction: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Kept so existing signed keys still verify.
|
|
21
|
+
* No camera, finder, scan, OCR, or redaction entry point asserts this flag.
|
|
22
|
+
*/
|
|
23
|
+
vehicles: boolean;
|
|
24
|
+
torch: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface LicenseClaims {
|
|
27
|
+
customerId: string;
|
|
28
|
+
/** Exact hostnames. `localhost` and `127.0.0.1` are included only when listed. */
|
|
29
|
+
domains: string[];
|
|
30
|
+
/** Unix expiry in seconds. The key is valid while `now < exp`. */
|
|
31
|
+
exp: number;
|
|
32
|
+
features: LicenseFeatures;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Compact signed payload: `base64url(json).base64url(ed25519 signature)`.
|
|
36
|
+
* The signature covers the raw JSON bytes. Public APIs do not accept a
|
|
37
|
+
* caller-supplied public key or hostname.
|
|
38
|
+
*/
|
|
39
|
+
export interface LicenseVerification {
|
|
40
|
+
publicKey: Uint8Array;
|
|
41
|
+
/** Injected only for Node tests. Browsers use `location.hostname`. */
|
|
42
|
+
hostname: string;
|
|
43
|
+
/** Unix time in seconds. */
|
|
44
|
+
now: number;
|
|
45
|
+
}
|
|
46
|
+
export declare class LicenseError extends Error {
|
|
47
|
+
readonly code: LicenseErrorCode;
|
|
48
|
+
constructor(code: LicenseErrorCode, message: string);
|
|
49
|
+
}
|
|
50
|
+
export declare function normalizeHostname(value: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Canonical JSON signed by the license portal. Key order is part of the
|
|
53
|
+
* signature bytes. Keep this in lockstep with `license-portal/lib/license-token.ts`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function canonicalLicensePayload(claims: LicenseClaims): string;
|
|
56
|
+
/**
|
|
57
|
+
* Verifies a compact license. Hostname and public key are explicit so Node
|
|
58
|
+
* tests can inject them. Published entry points call `assertLicense`, which
|
|
59
|
+
* always uses the embedded public key and `location.hostname`.
|
|
60
|
+
*/
|
|
61
|
+
export declare function verifyLicenseToken(licenseKey: string, verification: LicenseVerification): Promise<LicenseClaims>;
|
|
62
|
+
/**
|
|
63
|
+
* Verifies `licenseKey` for the current page and keeps it for later calls.
|
|
64
|
+
*
|
|
65
|
+
* @throws {LicenseError} LicenseError when the key is missing, malformed, badly signed,
|
|
66
|
+
* expired, or not issued for `location.hostname`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function setLicenseKey(licenseKey: string): Promise<LicenseClaims>;
|
|
69
|
+
/**
|
|
70
|
+
* Feature flags from the key most recently accepted by `setLicenseKey`.
|
|
71
|
+
* Returns null when no key is loaded, the key is expired, or this hostname
|
|
72
|
+
* is not on the key. Enforcement still re-checks the signature in `assertLicense`.
|
|
73
|
+
*/
|
|
74
|
+
export declare function getLicense(): LicenseClaims | null;
|
|
75
|
+
/**
|
|
76
|
+
* Fail-closed gate used by the public camera, finder, scan, OCR, and
|
|
77
|
+
* redaction entry points.
|
|
78
|
+
*
|
|
79
|
+
* @throws {LicenseError} LicenseError before those APIs do any work, when the key is
|
|
80
|
+
* missing, invalid, or missing `feature`.
|
|
81
|
+
*/
|
|
82
|
+
export declare function assertLicense(feature: LicenseFeature): Promise<LicenseClaims>;
|
|
83
|
+
/** Drops the in-memory key. Not part of the published package entry. */
|
|
84
|
+
export declare function clearLicenseForTests(): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DocumentQuad } from './types';
|
|
2
|
+
export interface CastShadowRegion {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
export interface CastShadowAnalysis {
|
|
9
|
+
strong: boolean;
|
|
10
|
+
strength: number;
|
|
11
|
+
darkness: number;
|
|
12
|
+
areaRatio: number;
|
|
13
|
+
region?: CastShadowRegion;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Finds a connected, page-sized dark blob in any direction. A component must
|
|
17
|
+
* cover meaningful area and contain local contrast, distinguishing cast
|
|
18
|
+
* shadows over printed paper from a dark border or isolated illustration.
|
|
19
|
+
*/
|
|
20
|
+
export declare function analyzeCastShadowLuminance(luminance: Uint8Array, width: number, height: number, gridSize?: number): CastShadowAnalysis;
|
|
21
|
+
export declare function flattenIlluminationLuminance(luminance: Uint8Array, width: number, height: number, radius?: number): Uint8Array<ArrayBuffer>;
|
|
22
|
+
export declare function analyzeCanvasCastShadow(canvas: HTMLCanvasElement, quad: DocumentQuad): CastShadowAnalysis;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ModelDownloadProgress {
|
|
2
|
+
loaded: number;
|
|
3
|
+
/** Byte length from Content-Length. Null when that header is absent. */
|
|
4
|
+
total: number | null;
|
|
5
|
+
done?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ModelDownloadSnapshot {
|
|
8
|
+
downloading: boolean;
|
|
9
|
+
loaded: number;
|
|
10
|
+
/** Sum of Content-Length values when every active transfer has one. */
|
|
11
|
+
total: number | null;
|
|
12
|
+
}
|
|
13
|
+
export declare function modelDownloadSnapshot(): ModelDownloadSnapshot;
|
|
14
|
+
/** Subscribing does not fetch. Downloads start only from `downloadModelBytes`. */
|
|
15
|
+
export declare function subscribeModelDownloads(listener: (snapshot: ModelDownloadSnapshot) => void): () => void;
|
|
16
|
+
/** Progress reported from another realm, such as the document worker. */
|
|
17
|
+
export declare function reportModelDownload(url: string, progress: ModelDownloadProgress): void;
|
|
18
|
+
export declare function readResponseBytes(response: Response, onProgress?: (progress: ModelDownloadProgress) => void): Promise<ArrayBuffer>;
|
|
19
|
+
/**
|
|
20
|
+
* Fetch a model file and report loaded/total while the body transfers.
|
|
21
|
+
* A second call for the same URL reuses the cached bytes and does not fetch.
|
|
22
|
+
*/
|
|
23
|
+
export declare function downloadModelBytes(url: string, init?: {
|
|
24
|
+
cache?: RequestCache;
|
|
25
|
+
}): Promise<ArrayBuffer>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser files copied from tesseract.js 7, tesseract.js-core 7.0.0 LSTM builds,
|
|
3
|
+
* and @tesseract.js-data/eng 4.0.0_best_int. Literal `new URL` keeps them visible
|
|
4
|
+
* to Webpack and Turbopack.
|
|
5
|
+
*/
|
|
6
|
+
export declare const tesseractWorkerUrl: URL;
|
|
7
|
+
export declare const tesseractCoreLstmUrl: URL;
|
|
8
|
+
export declare const tesseractCoreSimdLstmUrl: URL;
|
|
9
|
+
export declare const tesseractCoreRelaxedSimdLstmUrl: URL;
|
|
10
|
+
export declare const bundledEnglishTraineddataUrl: URL;
|
|
11
|
+
export interface LstmCoreSupport {
|
|
12
|
+
relaxedSimd: boolean;
|
|
13
|
+
simd: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** Same relaxed-SIMD then SIMD order as tesseract.js `getCore` for an LSTM core. */
|
|
16
|
+
export declare function detectLstmCoreSupport(): LstmCoreSupport;
|
|
17
|
+
export declare function selectLstmCoreUrl(support: LstmCoreSupport): URL;
|
|
18
|
+
export type OcrLanguagePlan = {
|
|
19
|
+
kind: 'bundled-eng';
|
|
20
|
+
language: 'eng';
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'lang-path';
|
|
23
|
+
language: string;
|
|
24
|
+
langPath: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function resolveOcrLanguage(language?: string, langPath?: string): OcrLanguagePlan;
|
|
27
|
+
export declare function loadBundledEnglishTraineddata(): Promise<Uint8Array<ArrayBuffer>>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { type CastShadowAnalysis } from './lighting';
|
|
2
|
+
import type { ImageSource, OcrBox, OcrResult } from './types';
|
|
3
|
+
export interface OcrOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Tesseract language code. Defaults to `eng`, which loads the packaged
|
|
6
|
+
* English LSTM traineddata. Any other code needs `langPath`.
|
|
7
|
+
*/
|
|
8
|
+
language?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Directory URL that contains `${language}.traineddata.gz`.
|
|
11
|
+
* Required when `language` is not `eng`. For `eng`, set this only to
|
|
12
|
+
* replace the packaged English model.
|
|
13
|
+
*/
|
|
14
|
+
langPath?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Minimum normalized confidence accepted for OCR tokens, from 0 to 1.
|
|
17
|
+
* Defaults to 0.5. Words and characters are filtered independently.
|
|
18
|
+
* A value outside 0–1 throws `RangeError`.
|
|
19
|
+
*/
|
|
20
|
+
minConfidence?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Re-reads one low-yield phone/hand cast-shadow tile after local
|
|
23
|
+
* illumination normalization. Defaults to true.
|
|
24
|
+
*/
|
|
25
|
+
shadowPass?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Include word boxes on the result. Defaults to false.
|
|
28
|
+
* Redaction that matches words needs `true`.
|
|
29
|
+
*/
|
|
30
|
+
includeWords?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Include character boxes on the result. Defaults to false.
|
|
33
|
+
*/
|
|
34
|
+
includeCharacters?: boolean;
|
|
35
|
+
onProgress?: (progress: number, status: string) => void;
|
|
36
|
+
}
|
|
37
|
+
interface TesseractBbox {
|
|
38
|
+
x0: number;
|
|
39
|
+
y0: number;
|
|
40
|
+
x1: number;
|
|
41
|
+
y1: number;
|
|
42
|
+
}
|
|
43
|
+
interface TesseractSymbol {
|
|
44
|
+
text: string;
|
|
45
|
+
confidence: number;
|
|
46
|
+
bbox: TesseractBbox;
|
|
47
|
+
}
|
|
48
|
+
interface TesseractWord {
|
|
49
|
+
text: string;
|
|
50
|
+
confidence: number;
|
|
51
|
+
bbox: TesseractBbox;
|
|
52
|
+
symbols: TesseractSymbol[];
|
|
53
|
+
}
|
|
54
|
+
interface TesseractBlock {
|
|
55
|
+
paragraphs: Array<{
|
|
56
|
+
lines: Array<{
|
|
57
|
+
words: TesseractWord[];
|
|
58
|
+
}>;
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
61
|
+
export interface OcrPass {
|
|
62
|
+
blocks: TesseractBlock[] | null;
|
|
63
|
+
/** Maps pass coordinates back into the original input image. */
|
|
64
|
+
scaleX?: number;
|
|
65
|
+
scaleY?: number;
|
|
66
|
+
offsetX?: number;
|
|
67
|
+
offsetY?: number;
|
|
68
|
+
}
|
|
69
|
+
export declare function mergeOcrPasses(passes: OcrPass[], options: Pick<OcrOptions, 'minConfidence' | 'includeWords' | 'includeCharacters'>, imageSize?: {
|
|
70
|
+
width: number;
|
|
71
|
+
height: number;
|
|
72
|
+
}, inkDensity?: (box: OcrBox['bbox']) => number): {
|
|
73
|
+
text: string;
|
|
74
|
+
confidence: number;
|
|
75
|
+
words: OcrBox[];
|
|
76
|
+
characters: OcrBox[];
|
|
77
|
+
};
|
|
78
|
+
export declare function extractOcrLayout(blocks: TesseractBlock[] | null, options: Pick<OcrOptions, 'minConfidence' | 'includeWords' | 'includeCharacters'>): {
|
|
79
|
+
text: string;
|
|
80
|
+
confidence: number;
|
|
81
|
+
words: OcrBox[];
|
|
82
|
+
characters: OcrBox[];
|
|
83
|
+
};
|
|
84
|
+
export declare function extractOcrBoxes(blocks: TesseractBlock[] | null, options: Pick<OcrOptions, 'minConfidence' | 'includeWords' | 'includeCharacters'>): {
|
|
85
|
+
words: OcrBox[];
|
|
86
|
+
characters: OcrBox[];
|
|
87
|
+
};
|
|
88
|
+
export declare function shadowRegionNeedsOcr(analysis: CastShadowAnalysis, words: OcrBox[], imageSize: {
|
|
89
|
+
width: number;
|
|
90
|
+
height: number;
|
|
91
|
+
}): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Reads text from a browser image. English uses the packaged traineddata.
|
|
94
|
+
* `includeWords` and `includeCharacters` default to false.
|
|
95
|
+
* `minConfidence` defaults to 0.5.
|
|
96
|
+
*
|
|
97
|
+
* @throws {LicenseError} LicenseError when the OCR feature is not licensed. Recognition does not start.
|
|
98
|
+
* @throws {RangeError} RangeError when `minConfidence` is outside 0–1.
|
|
99
|
+
* @throws {ScannerError} ScannerError `language` when `language` is not `eng` and `langPath` is omitted.
|
|
100
|
+
* `canvas` when canvas 2D is unavailable.
|
|
101
|
+
* `model-http` when the packaged English traineddata request fails.
|
|
102
|
+
*/
|
|
103
|
+
export declare function recognizeText(source: ImageSource, options?: OcrOptions): Promise<OcrResult>;
|
|
104
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ONNX Runtime Web 1.30 extern-wasm JSEP build (WebGPU, then WASM).
|
|
3
|
+
* Literal `new URL` calls are what Webpack and Turbopack copy.
|
|
4
|
+
*/
|
|
5
|
+
export declare const packagedOrtWasmFile: URL;
|
|
6
|
+
export declare const packagedOrtWasmGlue: URL;
|
|
7
|
+
export interface PackagedOrtWasmPaths {
|
|
8
|
+
wasm: string;
|
|
9
|
+
mjs: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Override for the packaged ONNX Runtime files.
|
|
13
|
+
* A string is a directory that contains `ort-wasm-simd-threaded.jsep.wasm`
|
|
14
|
+
* and `ort-wasm-simd-threaded.jsep.mjs`. An object sets each file URL.
|
|
15
|
+
* Omit the option to use the copies shipped with the SDK.
|
|
16
|
+
*/
|
|
17
|
+
export type OrtWasmPaths = string | {
|
|
18
|
+
wasm: string;
|
|
19
|
+
mjs: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function packagedOrtWasmPaths(): PackagedOrtWasmPaths;
|
|
22
|
+
/** Uses the packaged wasm pair when the override is missing or blank. */
|
|
23
|
+
export declare function resolveOrtWasmPaths(value?: OrtWasmPaths): OrtWasmPaths;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { type FaceDetection } from './face-model';
|
|
2
|
+
import { type FieldLayout } from './field-model';
|
|
3
|
+
import type { Box, ImageSource, OcrResult, RedactOptions } from './types';
|
|
4
|
+
export type StringMatchMode = 'exact' | 'case-insensitive' | 'regex';
|
|
5
|
+
export type LabelDirection = 'above' | 'below' | 'left' | 'right' | 'any';
|
|
6
|
+
export interface StringRedactionRule {
|
|
7
|
+
id: string;
|
|
8
|
+
strategy: 'string';
|
|
9
|
+
mode: StringMatchMode;
|
|
10
|
+
values?: string[];
|
|
11
|
+
pattern?: string;
|
|
12
|
+
flags?: string;
|
|
13
|
+
scope?: 'word' | 'line';
|
|
14
|
+
}
|
|
15
|
+
export interface LabelRedactionRule {
|
|
16
|
+
id: string;
|
|
17
|
+
strategy: 'label';
|
|
18
|
+
label: string;
|
|
19
|
+
direction: LabelDirection;
|
|
20
|
+
labelMode?: 'exact' | 'case-insensitive';
|
|
21
|
+
valuePattern?: string;
|
|
22
|
+
patternFlags?: string;
|
|
23
|
+
window?: {
|
|
24
|
+
distance?: number;
|
|
25
|
+
crossAxis?: number;
|
|
26
|
+
};
|
|
27
|
+
redactLabel?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export type SemanticField = 'person_name' | 'date_of_birth' | 'address' | 'document_number' | 'expiration_date' | 'postal_code' | 'state';
|
|
30
|
+
/** `logical` uses aliases, MRZ, and layout. `model` uses a field ONNX. */
|
|
31
|
+
export type SemanticFieldDetector = 'logical' | 'model';
|
|
32
|
+
export interface SemanticRedactionRule {
|
|
33
|
+
id: string;
|
|
34
|
+
strategy: 'semantic';
|
|
35
|
+
field: SemanticField;
|
|
36
|
+
/**
|
|
37
|
+
* Defaults to `logical`. A loaded field model does not replace logical rules.
|
|
38
|
+
* Set `model` on a separate rule to redact from `models.fields` or `semanticDetections`.
|
|
39
|
+
*/
|
|
40
|
+
detector?: SemanticFieldDetector;
|
|
41
|
+
}
|
|
42
|
+
export interface SemanticModelDetection {
|
|
43
|
+
field: SemanticField;
|
|
44
|
+
bbox: Box;
|
|
45
|
+
confidence: number;
|
|
46
|
+
}
|
|
47
|
+
export type ProgrammaticRedactionRule = StringRedactionRule | LabelRedactionRule | SemanticRedactionRule;
|
|
48
|
+
export interface NormalizedRect {
|
|
49
|
+
x: number;
|
|
50
|
+
y: number;
|
|
51
|
+
width: number;
|
|
52
|
+
height: number;
|
|
53
|
+
}
|
|
54
|
+
export interface TemplateRectField {
|
|
55
|
+
id: string;
|
|
56
|
+
strategy: 'rect';
|
|
57
|
+
rect: NormalizedRect;
|
|
58
|
+
}
|
|
59
|
+
export interface TemplateAnchorField extends Omit<LabelRedactionRule, 'id' | 'strategy'> {
|
|
60
|
+
id: string;
|
|
61
|
+
strategy: 'anchor';
|
|
62
|
+
}
|
|
63
|
+
export type RedactionTemplateField = TemplateRectField | TemplateAnchorField;
|
|
64
|
+
export interface RedactionTemplate {
|
|
65
|
+
id: string;
|
|
66
|
+
fields: RedactionTemplateField[];
|
|
67
|
+
}
|
|
68
|
+
export interface MatchRedactionOptions {
|
|
69
|
+
rules: ProgrammaticRedactionRule[];
|
|
70
|
+
template?: RedactionTemplate;
|
|
71
|
+
imageWidth?: number;
|
|
72
|
+
imageHeight?: number;
|
|
73
|
+
semanticDetections?: SemanticModelDetection[];
|
|
74
|
+
/**
|
|
75
|
+
* When true, rules with `detector: 'model'` use `semanticDetections`.
|
|
76
|
+
* Logical rules ignore this flag.
|
|
77
|
+
*/
|
|
78
|
+
modelRequested?: boolean;
|
|
79
|
+
}
|
|
80
|
+
export interface RedactionMatch {
|
|
81
|
+
ruleId: string;
|
|
82
|
+
strategy: 'string' | 'label' | 'template-rect' | 'template-anchor' | 'semantic';
|
|
83
|
+
source?: 'string' | 'label' | 'template' | 'alias' | 'mrz' | 'layout' | 'model';
|
|
84
|
+
bbox: Box;
|
|
85
|
+
text?: string;
|
|
86
|
+
confidence: number;
|
|
87
|
+
}
|
|
88
|
+
export interface RedactionMatchResult {
|
|
89
|
+
matches: RedactionMatch[];
|
|
90
|
+
unmatchedRuleIds: string[];
|
|
91
|
+
complete: boolean;
|
|
92
|
+
confidence: number;
|
|
93
|
+
}
|
|
94
|
+
export interface ProgrammaticRedactionOptions extends MatchRedactionOptions {
|
|
95
|
+
/**
|
|
96
|
+
* Prior OCR. Omit it to run OCR with word boxes.
|
|
97
|
+
* An object without `words` is used as-is. OCR does not re-run, and
|
|
98
|
+
* word, label, and semantic rules then match nothing.
|
|
99
|
+
*/
|
|
100
|
+
ocr?: OcrResult;
|
|
101
|
+
style?: RedactOptions;
|
|
102
|
+
requireAll?: boolean;
|
|
103
|
+
models?: {
|
|
104
|
+
fields?: string;
|
|
105
|
+
fieldClasses?: SemanticField[];
|
|
106
|
+
/**
|
|
107
|
+
* ONNX output layout. Defaults to `yolov8` (`[1, classes+4, anchors]`).
|
|
108
|
+
* `yolox` is decoded YOLOX-Nano `[1, anchors, 5+classes]`
|
|
109
|
+
* (`cx, cy, w, h, objectness`, then class scores). A tensor of that shape
|
|
110
|
+
* is read as YOLOX even when this is omitted.
|
|
111
|
+
*/
|
|
112
|
+
fieldLayout?: FieldLayout;
|
|
113
|
+
confidence?: number;
|
|
114
|
+
/**
|
|
115
|
+
* When the field model fails to load, model-detector rules use logical finding.
|
|
116
|
+
* Defaults to true. Logical rules are unchanged either way.
|
|
117
|
+
*/
|
|
118
|
+
allowHeuristicFallback?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* One-class YOLOX-Nano face ONNX. Boxes are painted on the image.
|
|
121
|
+
* They do not select OCR words. Omitted means no face model is fetched.
|
|
122
|
+
*/
|
|
123
|
+
face?: string;
|
|
124
|
+
faceConfidence?: number;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export interface ProgrammaticRedactionResult extends RedactionMatchResult {
|
|
128
|
+
status: 'success' | 'partial' | 'unmatched';
|
|
129
|
+
ocr?: OcrResult;
|
|
130
|
+
canvas?: HTMLCanvasElement;
|
|
131
|
+
blob?: Blob;
|
|
132
|
+
modelStatus: 'not-requested' | 'loaded' | 'fallback' | 'failed';
|
|
133
|
+
modelError?: string;
|
|
134
|
+
faces: FaceDetection[];
|
|
135
|
+
faceStatus: 'not-requested' | 'loaded' | 'failed';
|
|
136
|
+
faceError?: string;
|
|
137
|
+
}
|
|
138
|
+
export declare function matchRedactionRules(ocr: OcrResult | undefined, options: MatchRedactionOptions): RedactionMatchResult;
|
|
139
|
+
export declare function redactionStatus(summary: RedactionMatchResult, requireAll?: boolean): ProgrammaticRedactionResult['status'];
|
|
140
|
+
/**
|
|
141
|
+
* Matches rules and paints a new canvas.
|
|
142
|
+
* Returns `success`, `partial`, or `unmatched`. An unmatched rule does not throw.
|
|
143
|
+
*
|
|
144
|
+
* Omit `ocr` to run OCR with `includeWords: true`. An `ocr` object without
|
|
145
|
+
* `words` is used as-is, and OCR does not re-run.
|
|
146
|
+
* Face blackout is `models.face` on this call.
|
|
147
|
+
*
|
|
148
|
+
* @throws {LicenseError} LicenseError when the redaction feature is not licensed. Matching does not start.
|
|
149
|
+
* @throws {ScannerError} ScannerError `canvas` when canvas 2D is unavailable.
|
|
150
|
+
*/
|
|
151
|
+
export declare function redactProgrammatically(image: ImageSource, options: ProgrammaticRedactionOptions): Promise<ProgrammaticRedactionResult>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ImageSource, RedactionRegion, RedactOptions } from './types';
|
|
2
|
+
export interface RedactResult {
|
|
3
|
+
canvas: HTMLCanvasElement;
|
|
4
|
+
blob: Blob;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Paints trusted redaction regions onto a copy of an image and encodes it.
|
|
8
|
+
* Use this when the rectangles are already known. `redactProgrammatically`
|
|
9
|
+
* calls it after matching rules.
|
|
10
|
+
*
|
|
11
|
+
* The source is not mutated. Regions use source-image pixel coordinates and
|
|
12
|
+
* are clipped to the image bounds.
|
|
13
|
+
*
|
|
14
|
+
* @throws {LicenseError} LicenseError when the redaction feature is not licensed.
|
|
15
|
+
* @throws {ScannerError} ScannerError `canvas` when canvas 2D is unavailable.
|
|
16
|
+
*/
|
|
17
|
+
export declare function applyRedactions(source: ImageSource, regions: RedactionRegion[], options?: RedactOptions): Promise<RedactResult>;
|