type ExecutionMode = 'best' | 'standard' | 'fallback'; type DetectorSource = 'cv' | 'ml'; type ProposalSource = 'contour' | 'hough' | 'ml' | 'coco'; type FallbackState = 'inactive' | 'armed' | 'active'; type DetectionRejectionReason = 'none' | 'low_confidence' | 'edge_touch' | 'aspect_invalid' | 'quality_fail'; interface Point { x: number; y: number; } interface Quad { topLeft: Point; topRight: Point; bottomRight: Point; bottomLeft: Point; } interface DetectionMetrics { areaFraction: number; aspectPlausibility: number; edgeContrast: number; interiorHomogeneity: number; cornerAngleCloseness: number; borderPenalty: number; } interface DetectionCandidate { quad: Quad; score: number; confidence: number; source?: ProposalSource; metrics: DetectionMetrics; area: number; perimeter: number; convexity: number; edgeStrength: number; } type DetectionStatus = 'found' | 'not_found'; interface DetectionDebugStageTimings { grayscaleMs: number; blurMs: number; edgesMs: number; candidateMs: number; scoringMs: number; totalMs: number; } interface DetectionDebugInfo { candidateCount: number; topScores: number[]; ambiguityMargin: number; bestScore: number; secondBestScore: number; proposalSources: ProposalSource[]; fallbackState?: FallbackState; edgeDensity?: number; stageMs: DetectionDebugStageTimings; } interface DetectionResult { status: DetectionStatus; source: DetectorSource; bestCandidate?: DetectionCandidate; candidates: DetectionCandidate[]; rejectionReason?: DetectionRejectionReason; debug?: DetectionDebugInfo; timings?: DetectionDebugStageTimings; } interface BrightnessResult { averageLuma: number; ok: boolean; } interface BlurResult { laplacianVariance: number; ok: boolean; } interface GlareResult { highlightRatio: number; ok: boolean; } interface AreaResult { areaFraction: number; ok: boolean; } interface QualityResult { brightness: BrightnessResult; blur: BlurResult; glare: GlareResult; area: AreaResult; ok: boolean; } type GuidanceCode = 'DOCUMENT_NOT_FOUND' | 'TOO_DARK_OR_BRIGHT' | 'REDUCE_GLARE' | 'TOO_BLURRY' | 'HOLD_STEADY' | 'MOVE_CLOSER' | 'READY'; interface StabilityResult { stable: boolean; stableMs: number; cornerMovement: number; confidenceAccumulation: number; smoothedQuad?: Quad; } interface FrameProcessResult { detection: DetectionResult; quality?: QualityResult; stability?: StabilityResult; guidance: GuidanceCode; } interface DetectionScoreWeights { areaFraction: number; aspectPlausibility: number; edgeContrast: number; interiorHomogeneity: number; cornerAngleCloseness: number; borderPenalty: number; } interface EngineConfig { detectionWidth: number; fallbackDetectionWidth: number; fallbackFps: number; stabilityWindowMs: number; emaAlpha: number; minAreaFraction: number; maxAreaFraction: number; minAspectRatio: number; maxAspectRatio: number; confidenceThreshold: number; movementThresholdPx: number; movementThresholdRatio: number; minStableConfidence: number; edgeLowThreshold: number; edgeHighThreshold: number; blurVarianceMin: number; brightnessMin: number; brightnessMax: number; glareRatioMax: number; contourLimit: number; candidateTopK: number; minRectangularity: number; edgeTouchMarginPx: number; ambiguityScoreMargin: number; identitySwitchThresholdPx: number; detectionFrameBudgetMs: number; workerHardCeilingMs: number; contourEnabled: boolean; houghSecondaryEnabled: boolean; houghEdgeDensityMin: number; houghEdgeDensityMax: number; houghMinLineLengthDiagRatio: number; houghMaxLineGapDiagRatio: number; houghOrthogonalityMinDeg: number; houghOrthogonalityMaxDeg: number; scoreWeights: DetectionScoreWeights; debug: boolean; } interface Capabilities { workerSupported: boolean; offscreenCanvasSupported: boolean; offscreenTransferSupported: boolean; webglMainSupported: boolean; webglWorkerSupported: boolean; requestVideoFrameCallbackSupported: boolean; crossOriginIsolated: boolean; selectedMode: ExecutionMode; } type WarpTierUsed = 'cpu' | 'raw'; type DetectorMode = 'cv' | 'hybrid' | 'ml'; type DebugOverlayLevel = 'off' | 'basic' | 'full'; type MlPipelineVersion = 'v1-heuristic' | 'v2-graph'; type WarpValidationLevel = 'standard' | 'strict'; type PostCaptureRefine = 'off' | 'safe'; /** * High-level detection strategy the SDK should use. * * - `'auto'` – Probes device capabilities and picks the best strategy. * - `'opencv'` – OpenCV only (Hough + optional contour), no ML models loaded. * - `'ml'` – ML-primary with a TF.js graph model; falls back to OpenCV. * - `'hybrid'` – OpenCV primary with ML fallback when OpenCV misses. */ type Detection = 'auto' | 'opencv' | 'ml' | 'hybrid'; /** * Output quality preset. * * - `'fast'` – Fastest capture, smaller output, JPEG. * - `'balanced'` – Good quality, sensible size, PNG. * - `'high'` – Maximum resolution & quality, PNG. */ type Quality = 'fast' | 'balanced' | 'high'; interface CaptureResult { blob: Blob; width: number; height: number; quad: Quad; sourceQuad?: Quad; refinedQuad?: Quad; postRefineApplied?: boolean; postRefineReason?: string; warpTierUsed: WarpTierUsed; warpRejected?: boolean; warpRejectionReason?: string; quality?: QualityResult; captureDecisionSource: 'auto' | 'manual'; detectorSourceAtCapture: DetectorSource; elapsedMs: number; } interface ScannerConfig extends Partial { /** * Detection strategy. * * - `'auto'` (default) – picks the best strategy for the current device. * - `'opencv'` – OpenCV only, no ML models. * - `'ml'` – ML-primary (TF.js graph model) with OpenCV fallback. * - `'hybrid'` – OpenCV primary, ML fallback when CV misses. */ detection?: Detection; /** * Output quality preset. * * - `'fast'` – smaller output, JPEG, fewer stable frames. * - `'balanced'` (default) – good quality, PNG. * - `'high'` – max resolution & quality, PNG. */ quality?: Quality; /** Enable ML fallback when OpenCV cannot find a document (hybrid / auto). Default: `true`. */ mlFallback?: boolean; /** Enable COCO-SSD "book" detector for faster, more robust document detection. Downloads model from CDN (~5 MB) on first use. Default: `true`. */ cocoSsd?: boolean; /** * @deprecated No longer used. CPU warp is always used for reliability. * Kept for backward compatibility — setting this has no effect. */ webglWarp?: boolean; /** Automatically capture when the document is stable. Default: `true`. */ autoCapture?: boolean; /** Refine corner positions after capture. Default: `false`. */ postCaptureRefine?: boolean; /** Debug logging to console. Default: `false`. */ debug?: boolean; /** Debug overlay drawn on detection canvas. Default: `'off'`. */ debugOverlay?: DebugOverlayLevel; /** Custom `MediaTrackConstraints` for camera access. */ videoConstraints?: MediaTrackConstraints; /** Attach an existing video element instead of creating one internally. */ videoElement?: HTMLVideoElement; /** Provide a custom worker factory. */ workerFactory?: () => Worker; /** MIME type for captured image blob. */ captureMimeType?: string; /** JPEG quality (0-1) when using `image/jpeg`. */ captureQuality?: number; /** Max output image width in px. */ outputMaxWidth?: number; /** Max output image height in px. */ outputMaxHeight?: number; /** How many consecutive stable frames before auto-capture fires. */ autoCaptureConsecutiveStableFrames?: number; /** Minimum document-area fraction for auto-capture to trigger. */ autoCaptureMinAreaFraction?: number; /** Cooldown in ms between auto-captures. */ autoCaptureCooldownMs?: number; /** * Maximum number of captures per session (both auto and manual). * When the limit is reached, a `'complete'` event fires and further * auto-captures are disabled. The scanner keeps running — call * `stop()` or `destroy()` in your `'complete'` handler if you want * to stop the camera. * * - `undefined` or `0` — unlimited (default, backward-compatible). * - `1` — single-capture mode (capture once, then emit complete). * - `n` — multi-page mode (capture n documents, then emit complete). */ maxCaptures?: number; /** Preferred execution mode. Normally auto-detected. */ preferredMode?: ExecutionMode; /** URL for the OpenCV.js script. */ opencvScriptUrl?: string; /** ML pipeline version. Default: `'v2-graph'`. */ mlPipelineVersion?: MlPipelineVersion; /** ML model identifier. Default: resolved from `mlPipelineVersion`. */ mlModelId?: string; /** Explicit ML model URL (overrides ID-based resolution). */ mlModelUrl?: string; /** Base URL for ML model assets. */ mlModelBaseUrl?: string; /** Base URL for TF.js WASM backend files. */ mlWasmBaseUrl?: string; /** Input tensor size for the ML model. */ mlInputSize?: number; /** Enable the TF.js graph-model provider in the worker. Default: `true`. */ graphMlEnabled?: boolean; /** COCO-SSD minimum detection score (0-1). Default: `0.45`. */ cocoMinScore?: number; /** Use COCO-SSD as the primary detector in ML mode. Default: `true`. */ cocoUseAsPrimaryInMlMode?: boolean; /** Enable OpenCV contour detection. Default: `false`. */ cvContourEnabled?: boolean; /** Enable ML rescue (re-run ML on CV fallback frames). Default: `true`. */ mlRescueEnabled?: boolean; /** ML rescue frame stride. Default: `2`. */ mlRescueFrameStride?: number; /** Warp validation strictness. Default: `'standard'`. */ warpValidationLevel?: WarpValidationLevel; /** ML fallback frame stride. Default: `5`. */ mlFallbackFrameStride?: number; /** Consecutive OpenCV misses before ML kicks in. Default: `8`. */ mlFallbackTriggerConsecutiveMisses?: number; /** Minimum OpenCV confidence to keep using CV in hybrid mode. Default: `0.35`. */ mlFallbackMinCvConfidence?: number; /** Consecutive CV recovery frames before exiting ML fallback. Default: `3`. */ mlFallbackExitConsecutiveCvRecoveries?: number; /** Cooldown frames before re-entering ML fallback. Default: `10`. */ mlFallbackReentryCooldownFrames?: number; /** @internal */ detectorMode?: DetectorMode; /** @internal */ debugOverlayLevel?: DebugOverlayLevel; /** @internal */ mlFallbackEnabled?: boolean; /** @internal */ cocoBookEnabled?: boolean; /** @internal */ postCaptureRefineMode?: PostCaptureRefine; } interface CaptureCompleteResult { /** Total captures performed in this session. */ totalCaptures: number; /** All capture results collected during the session. */ captures: CaptureResult[]; } interface ScannerEventMap { detection: DetectionResult; stability: StabilityResult; guidance: GuidanceCode; capture: CaptureResult; /** Fired when `maxCaptures` is reached. Auto-capture is disabled after this event. */ complete: CaptureCompleteResult; error: Error; warning: string; capabilities: Capabilities; frame: FrameProcessResult; } type ScannerEventName = keyof ScannerEventMap; interface ScannerSession { getCapabilities(): Capabilities; /** Number of captures performed in the current session. Resets on `start()`. */ readonly captureCount: number; start(): Promise; stop(): Promise; captureManual(): Promise; updateConfig(partial: Partial): void; on(event: K, handler: (payload: ScannerEventMap[K]) => void): () => void; destroy(): Promise; } declare function selectExecutionMode(capabilities: Omit): ExecutionMode; declare function detectCapabilities(): Promise; /** * Default English guidance messages for each guidance code. * Integrators can call `createGuidanceMessages()` with overrides for i18n. */ declare const defaultGuidanceMessages: Readonly>; type GuidanceMessages = Record; /** * Create a guidance message map, optionally overriding specific strings. * Use this for i18n — pass your translated strings as overrides. * * @example Spanish * ```ts * const messages = createGuidanceMessages({ * DOCUMENT_NOT_FOUND: 'Apunta la cámara al documento', * HOLD_STEADY: 'Mantén firme…', * READY: 'Capturando…', * }); * ``` */ declare function createGuidanceMessages(overrides?: Partial>): GuidanceMessages; /** * Resolve a guidance code to a human-readable message. * * @param code - The guidance code from the scanner * @param messages - Optional custom messages (defaults to English) * @returns Human-readable guidance string */ declare function getGuidanceMessage(code: GuidanceCode | undefined, messages?: GuidanceMessages): string; declare function announceGuidance(message: string, politeness?: 'polite' | 'assertive'): void; /** * Create a document-autocapture scanner session. * * @example Minimal (sensible defaults) * ```ts * const scanner = createScanner(); * ``` * * @example Custom * ```ts * const scanner = createScanner({ * detection: 'ml', * quality: 'high', * cocoSsd: false, * webglWarp: true, * autoCapture: true, * debug: true, * }); * ``` */ declare function createScanner(config?: Partial): ScannerSession; export { type Capabilities, type CaptureCompleteResult, type CaptureResult, type Detection, type GuidanceMessages, type Quality, type ScannerConfig, type ScannerEventMap, type ScannerEventName, type ScannerSession, type WarpTierUsed, announceGuidance, createGuidanceMessages, createScanner, defaultGuidanceMessages, detectCapabilities, getGuidanceMessage, selectExecutionMode };