{"version":3,"file":"index.cjs","names":[],"sources":["../src/constants.ts","../src/utils/image.ts","../src/processor/detection.ts","../src/processor/recognition.ts","../src/processor/paddle-ocr.ts"],"sourcesContent":["import type {\n    DetectionRuntimeOptions,\n    PaddleOptions,\n    ProcessRecognitionOptions,\n    RecognitionOrderingOptions,\n    RecognitionRuntimeOptions,\n} from \"./interface.ts\";\n\ntype DetectionDefaults = Required<DetectionRuntimeOptions>;\ntype RecognitionDefaults = Required<RecognitionRuntimeOptions>;\ntype RecognitionOrderingDefaults = Required<RecognitionOrderingOptions>;\ntype ProcessRecognitionDefaults = Required<ProcessRecognitionOptions>;\n\nexport const DEFAULT_DETECTION_OPTIONS: DetectionDefaults = {\n    padding: 0,\n    mean: [0.485 * 255, 0.456 * 255, 0.406 * 255],\n    stdDeviation: [1 / 0.229 / 255, 1 / 0.224 / 255, 1 / 0.255 / 255],\n    maxSideLength: 960,\n    textPixelThreshold: 0.5,\n    minimumAreaThreshold: 20,\n    paddingBoxVertical: 0.4,\n    paddingBoxHorizontal: 0.6,\n    dilationKernelSize: 1,\n};\n\nexport const DEFAULT_RECOGNITION_OPTIONS: RecognitionDefaults = {\n    mean: [127.5, 127.5, 127.5],\n    stdDeviation: [1.0 / 127.5, 1.0 / 127.5, 1.0 / 127.5],\n    imageHeight: 48,\n    charactersDictionary: [],\n};\n\nexport const DEFAULT_RECOGNITION_ORDERING_OPTIONS: RecognitionOrderingDefaults = {\n    sortByReadingOrder: true,\n    sameLineThresholdRatio: 0.25,\n};\n\nexport const DEFAULT_PROCESS_RECOGNITION_OPTIONS: ProcessRecognitionDefaults = {\n    lineMergeThresholdRatio: 0.5,\n};\n\nexport const DEFAULT_PADDLE_OPTIONS: Partial<PaddleOptions> = {\n    detection: DEFAULT_DETECTION_OPTIONS,\n    recognition: DEFAULT_RECOGNITION_OPTIONS,\n};\n","import type { Box } from \"../interface.ts\";\n\ninterface CropOptions {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n}\n\ninterface ResizeOptions {\n    width?: number;\n    height?: number;\n    filter?: \"triangle\";\n}\n\ninterface PaddingOptions {\n    padding?: number;\n    vertical?: number;\n    horizontal?: number;\n    top?: number;\n    bottom?: number;\n    left?: number;\n    right?: number;\n    color?: number[];\n}\n\ninterface TensorOptions {\n    mean_values: [number, number, number];\n    norm_values: [number, number, number];\n}\n\ninterface DilateOptions {\n    norm?: \"LInf\";\n    k?: number;\n}\n\ninterface ThresholdOptions {\n    threshold?: number; // 阈值，默认128\n}\n\ninterface ContoursOptions {\n    minArea?: number;\n}\n\ninterface RectOptions {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n    lineWidth?: number;\n    color?: number[];\n}\n\nexport class Image {\n    width: number;\n    height: number;\n    data: Uint8Array;\n    depth: 8;\n    channels: number;\n\n    /**\n     * 创建一个新的 Image 实例。\n     * @param width 图像的宽度\n     * @param height 图像的高度\n     * @param data 图像数据，Uint8Array\n     */\n    constructor(width: number, height: number, channels: number, data: Uint8Array) {\n        this.width = width;\n        this.height = height;\n        this.channels = channels;\n        this.depth = 8;\n        if (data) {\n            this.data = data;\n        } else {\n            const length = width * height * 4;\n            this.data = new Uint8Array(length); // Default to RGBA\n        }\n    }\n\n    /**\n     * 裁剪\n     */\n    crop(options: CropOptions) {\n        const { x, y, width, height } = options;\n        if (x < 0 || y < 0 || x + width > this.width || y + height > this.height) {\n            throw new Error(\"Crop area is out of bounds\");\n        }\n        const croppedData = new Uint8Array(width * height * this.channels);\n        for (let j = 0; j < height; j++) {\n            for (let i = 0; i < width; i++) {\n                const srcIndex = ((y + j) * this.width + (x + i)) * this.channels;\n                const dstIndex = (j * width + i) * this.channels;\n                croppedData.set(this.data.subarray(srcIndex, srcIndex + this.channels), dstIndex);\n            }\n        }\n        return new Image(width, height, this.channels, croppedData);\n    }\n\n    /**\n     * 将图片缩放到指定的尺寸w\n     * @param options\n     */\n    resize(options: ResizeOptions) {\n        let { width, height } = options;\n        if (width === undefined && height === undefined) {\n            throw new Error(\"At least one of width or height must be specified\");\n        }\n        if (width === undefined) {\n            width = Math.round(this.width * ((height ?? this.height) / this.height));\n        }\n        if (height === undefined) {\n            height = Math.round(this.height * (width / this.width));\n        }\n\n        const srcW = this.width;\n        const srcH = this.height;\n        const dstW = width;\n        const dstH = height;\n        const channels = this.channels;\n        const srcData = this.data;\n\n        function triangle_kernel(x: number) {\n            x = Math.abs(x);\n            return x < 1 ? 1 - x : 0;\n        }\n\n        function clamp(v: number, min: number, max: number): number {\n            return Math.max(min, Math.min(max, v));\n        }\n\n        // 1. 纵向采样\n        const tmpData = new Float32Array(srcW * dstH * channels);\n        const ratioY = srcH / dstH;\n        const sratioY = ratioY < 1 ? 1 : ratioY;\n        const supportY = 1.0 * sratioY;\n\n        for (let outy = 0; outy < dstH; outy++) {\n            const inputy = (outy + 0.5) * ratioY - 0.5;\n            const left = Math.max(0, Math.floor(inputy - supportY));\n            const right = Math.min(srcH, Math.ceil(inputy + supportY));\n\n            const ws: number[] = [];\n            let sum = 0;\n            for (let i = left; i < right; i++) {\n                const w = triangle_kernel((i - inputy) / sratioY);\n                ws.push(w);\n                sum += w;\n            }\n            for (let i = 0; i < ws.length; i++) ws[i] /= sum;\n\n            for (let x = 0; x < srcW; x++) {\n                for (let c = 0; c < channels; c++) {\n                    let t = 0;\n                    for (let i = 0; i < ws.length; i++) {\n                        const srcIdx = ((left + i) * srcW + x) * channels + c;\n                        t += srcData[srcIdx] * ws[i];\n                    }\n                    tmpData[(outy * srcW + x) * channels + c] = t;\n                }\n            }\n        }\n\n        // 2. 横向采样\n        const dstData = new Uint8Array(dstW * dstH * channels);\n        const ratioX = srcW / dstW;\n        const sratioX = ratioX < 1 ? 1 : ratioX;\n        const supportX = 1.0 * sratioX;\n\n        for (let outx = 0; outx < dstW; outx++) {\n            const inputx = (outx + 0.5) * ratioX - 0.5;\n            const left = Math.max(0, Math.floor(inputx - supportX));\n            const right = Math.min(srcW, Math.ceil(inputx + supportX));\n\n            const ws: number[] = [];\n            let sum = 0;\n            for (let i = left; i < right; i++) {\n                const w = triangle_kernel((i - inputx) / sratioX);\n                ws.push(w);\n                sum += w;\n            }\n            for (let i = 0; i < ws.length; i++) ws[i] /= sum;\n\n            for (let y = 0; y < dstH; y++) {\n                for (let c = 0; c < channels; c++) {\n                    let t = 0;\n                    for (let i = 0; i < ws.length; i++) {\n                        const srcIdx = (y * srcW + (left + i)) * channels + c;\n                        t += tmpData[srcIdx] * ws[i];\n                    }\n                    dstData[(y * dstW + outx) * channels + c] = Math.round(clamp(t, 0, 255));\n                }\n            }\n        }\n\n        return new Image(dstW, dstH, channels, dstData);\n    }\n\n    /**\n     * 为图片添加指定颜色的边距，默认为透明的\n     * @param options\n     */\n    padding(options: PaddingOptions) {\n        // 解析边距\n        let { padding, vertical, horizontal, top, bottom, left, right, color } = options;\n        // 优先级：padding > vertical/horizontal > top/bottom/left/right\n        if (typeof padding === \"number\") {\n            top = bottom = left = right = padding;\n        } else {\n            if (typeof vertical === \"number\") {\n                top = bottom = vertical;\n            }\n            if (typeof horizontal === \"number\") {\n                left = right = horizontal;\n            }\n        }\n        top = top ?? 0;\n        bottom = bottom ?? 0;\n        left = left ?? 0;\n        right = right ?? 0;\n        color = color ?? [0, 0, 0, 0];\n        const newW = this.width + left + right;\n        const newH = this.height + top + bottom;\n        const newData = new Uint8Array(newW * newH * 4);\n        // 填充背景色\n        for (let y = 0; y < newH; y++) {\n            for (let x = 0; x < newW; x++) {\n                const idx = (y * newW + x) * 4;\n                newData[idx] = color[0];\n                newData[idx + 1] = color[1];\n                newData[idx + 2] = color[2];\n                newData[idx + 3] = color[3];\n            }\n        }\n        // 拷贝原图\n        for (let y = 0; y < this.height; y++) {\n            for (let x = 0; x < this.width; x++) {\n                const srcIdx = (y * this.width + x) * 4;\n                const dstIdx = ((y + top) * newW + (x + left)) * 4;\n                newData.set(this.data.subarray(srcIdx, srcIdx + 4), dstIdx);\n            }\n        }\n        return new Image(newW, newH, this.channels, newData);\n    }\n\n    /**\n     * 将当前图像转换为张量格式，以便输入到onnx模型\n     * @param options\n     */\n    tensor(options: TensorOptions): Float32Array {\n        const mean = options.mean_values;\n        const norm = options.norm_values;\n        const width = this.width;\n        const height = this.height;\n        const numChannels = 3;\n        const rgbaData = this.data;\n        const tensor = new Float32Array(width * height * numChannels);\n        for (let h = 0; h < height; h++) {\n            for (let w = 0; w < width; w++) {\n                const pixelIndex = (h * width + w) * this.channels;\n                const tensorIndex = h * width + w;\n                for (let c = 0; c < numChannels; c++) {\n                    const pixelValue = rgbaData[pixelIndex + c];\n                    const normalizedValue = pixelValue * norm[c] - mean[c] * norm[c];\n                    tensor[c * height * width + tensorIndex] = normalizedValue;\n                }\n            }\n        }\n        return tensor;\n    }\n\n    /**\n     * 灰度图阈值方法，大于阈值的像素点设为255，小于等于阈值的设为0\n     * @param options\n     */\n    threshold(options: ThresholdOptions) {\n        const threshold = options.threshold ?? 128;\n        const width = this.width;\n        const height = this.height;\n        // 创建二值化图像\n        const binData = new Uint8Array(width * height);\n        for (let i = 0; i < width * height; i++) {\n            binData[i] = this.data[i * this.channels] > threshold ? 255 : 0;\n        }\n        return new Image(width, height, 1, binData);\n    }\n\n    /**\n     * 膨胀操作，使用指定的范数和核大小\n     * 进行处理的图片像素是0和255，膨胀255的像素点\n     * 返回一个新的图片\n     * @param options\n     */\n    dilate(options: DilateOptions = {}): Image {\n        const { norm = \"LInf\", k = 1 } = options;\n        if (norm !== \"LInf\") {\n            throw new Error(\"Only LInf norm is supported\");\n        }\n        if (this.channels !== 1) {\n            throw new Error(\"Dilate only supports single channel (grayscale) images\");\n        }\n        const width = this.width;\n        const height = this.height;\n        const src = this.data;\n        // 1. 计算每个像素到最近前景像素(255)的LInf距离\n        // 初始化距离图，前景为0，背景为无穷大\n        const INF = 999999;\n        const dist = new Uint16Array(width * height);\n        for (let i = 0; i < width * height; i++) {\n            dist[i] = src[i] > 0 ? 0 : INF;\n        }\n        // 两次扫描，先左上到右下，再右下到左上\n        // LInf: 只需看8邻域的最小距离+1\n        // 正向\n        for (let y = 0; y < height; y++) {\n            for (let x = 0; x < width; x++) {\n                const idx = y * width + x;\n                if (dist[idx] === 0) continue;\n                let minDist = INF;\n                for (let dy = -1; dy <= 0; dy++) {\n                    for (let dx = -1; dx <= 1; dx++) {\n                        if (dx === 0 && dy === 0) continue;\n                        const nx = x + dx,\n                            ny = y + dy;\n                        if (nx >= 0 && nx < width && ny >= 0 && ny < height) {\n                            const nidx = ny * width + nx;\n                            minDist = Math.min(minDist, dist[nidx] + 1);\n                        }\n                    }\n                }\n                dist[idx] = Math.min(dist[idx], minDist);\n            }\n        }\n        // 反向\n        for (let y = height - 1; y >= 0; y--) {\n            for (let x = width - 1; x >= 0; x--) {\n                const idx = y * width + x;\n                if (dist[idx] === 0) continue;\n                let minDist = INF;\n                for (let dy = 0; dy <= 1; dy++) {\n                    for (let dx = -1; dx <= 1; dx++) {\n                        if (dx === 0 && dy === 0) continue;\n                        const nx = x + dx,\n                            ny = y + dy;\n                        if (nx >= 0 && nx < width && ny >= 0 && ny < height) {\n                            const nidx = ny * width + nx;\n                            minDist = Math.min(minDist, dist[nidx] + 1);\n                        }\n                    }\n                }\n                dist[idx] = Math.min(dist[idx], minDist);\n            }\n        }\n        // 2. 距离小于等于k的像素设为255，否则为0\n        const out = new Uint8Array(width * height);\n        for (let i = 0; i < width * height; i++) {\n            out[i] = dist[i] <= k ? 255 : 0;\n        }\n        return new Image(width, height, 1, out);\n    }\n\n    /**\n     * 获取图像中的轮廓\n     * @returns\n     */\n    contours(options: ContoursOptions = {}): Box[] {\n        // Suzuki/Abe 边界跟踪算法，输入为灰度图，输出 Box[]\n        const minArea = options.minArea ?? 1;\n        const width = this.width;\n        const height = this.height;\n        // 二值化\n        const bin = new Uint8Array(width * height);\n        for (let i = 0; i < width * height; i++) {\n            bin[i] = this.data[i] > 0 ? 1 : 0;\n        }\n        // 轮廓提取\n        const visited = new Uint8Array(width * height);\n        const boxes: Box[] = [];\n        const at = (x: number, y: number) => y * width + x;\n        for (let y = 0; y < height; y++) {\n            for (let x = 0; x < width; x++) {\n                if (bin[at(x, y)] && !visited[at(x, y)]) {\n                    // BFS 寻找连通域\n                    let minX = x,\n                        minY = y,\n                        maxX = x,\n                        maxY = y,\n                        area = 0;\n                    const queue = [[x, y]];\n                    visited[at(x, y)] = 1;\n                    while (queue.length) {\n                        const current = queue.shift();\n                        if (!current) {\n                            break;\n                        }\n                        const [cx, cy] = current;\n                        area++;\n                        minX = Math.min(minX, cx);\n                        minY = Math.min(minY, cy);\n                        maxX = Math.max(maxX, cx);\n                        maxY = Math.max(maxY, cy);\n                        for (const [dx, dy] of [\n                            [-1, 0],\n                            [1, 0],\n                            [0, -1],\n                            [0, 1],\n                            [-1, -1],\n                            [1, -1],\n                            [-1, 1],\n                            [1, 1],\n                        ]) {\n                            const nx = cx + dx,\n                                ny = cy + dy;\n                            if (\n                                nx >= 0 &&\n                                nx < width &&\n                                ny >= 0 &&\n                                ny < height &&\n                                bin[at(nx, ny)] &&\n                                !visited[at(nx, ny)]\n                            ) {\n                                visited[at(nx, ny)] = 1;\n                                queue.push([nx, ny]);\n                            }\n                        }\n                    }\n                    if (area >= minArea) {\n                        boxes.push({\n                            x: minX,\n                            y: minY,\n                            width: maxX - minX + 1,\n                            height: maxY - minY + 1,\n                        });\n                    }\n                }\n            }\n        }\n        return boxes;\n    }\n\n    /**\n     * 在图像上绘制矩形，支持线宽\n     * @param x 左上角x\n     * @param y 左上角y\n     * @param width 矩形宽度\n     * @param height 矩形高度\n     * @param color 颜色 [r,g,b,a]\n     * @param lineWidth 线宽\n     */\n    rect(options: RectOptions) {\n        const { x, y, width, height, color = [], lineWidth = 1 } = options;\n        if (!color.length) {\n            color.push(...Array(this.channels).fill(255));\n        }\n        if (this.channels !== color.length) {\n            throw new Error(\n                `Color length ${color.length} does not match image channels ${this.channels}`\n            );\n        }\n        // 上下边\n        for (let dy = 0; dy < lineWidth; dy++) {\n            for (let i = 0; i < width; i++) {\n                // 上边\n                const yy = y + dy;\n                const xx = x + i;\n                if (yy >= 0 && yy < this.height && xx >= 0 && xx < this.width) {\n                    const idx = (yy * this.width + xx) * this.channels;\n                    this.data.set(color, idx);\n                }\n                // 下边\n                const by = y + height - 1 - dy;\n                if (by >= 0 && by < this.height && xx >= 0 && xx < this.width) {\n                    const idx = (by * this.width + xx) * this.channels;\n                    this.data.set(color, idx);\n                }\n            }\n        }\n        // 左右边\n        for (let dx = 0; dx < lineWidth; dx++) {\n            for (let j = 0; j < height; j++) {\n                // 左边\n                const xx = x + dx;\n                const yy = y + j;\n                if (xx >= 0 && xx < this.width && yy >= 0 && yy < this.height) {\n                    const idx = (yy * this.width + xx) * this.channels;\n                    this.data.set(color, idx);\n                }\n                // 右边\n                const rx = x + width - 1 - dx;\n                if (rx >= 0 && rx < this.width && yy >= 0 && yy < this.height) {\n                    const idx = (yy * this.width + rx) * this.channels;\n                    this.data.set(color, idx);\n                }\n            }\n        }\n    }\n\n    /**\n     * 以png格式输出到指定位置\n     * @param path 输出路径\n     */\n    // async saveAsPng(path: string) {\n    //     try {\n    //         const { encode } = await import(\"fast-png\");\n    //         const pngData = encode({\n    //             width: this.width,\n    //             height: this.height,\n    //             depth: this.depth,\n    //             channels: this.channels,\n    //             data: this.data,\n    //         });\n    //         const { writeFile } = await import(\"fs/promises\");\n    //         await writeFile(path, pngData);\n    //     } catch (e) {\n    //         console.error(`Failed to save image as PNG: ${e}`);\n    //         throw e;\n    //     }\n    // }\n}\n","import { DEFAULT_DETECTION_OPTIONS } from \"../constants.ts\";\nimport type {\n    Box,\n    DetectionRuntimeOptions,\n    OcrProgress,\n    OrtInferenceSession,\n    OrtModule,\n    PaddleOcrProgressEvent,\n} from \"../interface.ts\";\nimport { Image } from \"../utils/image.ts\";\n\nexport interface ResizeParams {\n    srcWidth: number;\n    srcHeight: number;\n    dstWidth: number;\n    dstHeight: number;\n    scaleWidth: number;\n    scaleHeight: number;\n}\n\n/**\n * Result of preprocessing an image for text detection\n */\nexport interface PreprocessDetectionResult {\n    tensor: Float32Array;\n    resizeParams: ResizeParams;\n}\n\nexport interface DetectionRunOptions extends Partial<DetectionRuntimeOptions> {\n    onProgress?: (event: PaddleOcrProgressEvent) => void;\n}\n\n/**\n * Service for detecting text regions in images\n */\nexport class DetectionService {\n    private static readonly TOTAL_PROGRESS_STEPS = 3;\n    private readonly options: DetectionRuntimeOptions;\n    private readonly session: OrtInferenceSession;\n    private readonly ortModule: OrtModule;\n\n    constructor(\n        ortModule: OrtModule,\n        session: OrtInferenceSession,\n        options: Partial<DetectionRuntimeOptions> = {}\n    ) {\n        this.session = session;\n        this.ortModule = ortModule;\n\n        this.options = {\n            ...DEFAULT_DETECTION_OPTIONS,\n            ...options,\n        };\n    }\n\n    /**\n     * Main method to run text detection on an image\n     * @param image ArrayBuffer of the image or Canvas\n     */\n    async run(image: Image, options: DetectionRunOptions = {}): Promise<Box[]> {\n        const { onProgress, ...runtimeOverrides } = options;\n        const runtimeOptions = this.resolveRuntimeOptions(runtimeOverrides);\n        const input = await this.preprocessDetection(image, runtimeOptions);\n        onProgress?.({\n            type: \"det\",\n            stage: \"preprocess\",\n            progress: this.createProgress(1),\n        });\n\n        const detection = await this.runInference(input.tensor, input.resizeParams);\n        onProgress?.({\n            type: \"det\",\n            stage: \"infer\",\n            progress: this.createProgress(2),\n        });\n\n        const detectedBoxes = detection\n            ? this.postprocessDetection(detection, input, runtimeOptions)\n            : [];\n        onProgress?.({\n            type: \"det\",\n            stage: \"postprocess\",\n            progress: this.createProgress(3),\n            detectedCount: detectedBoxes.length,\n        });\n\n        return detectedBoxes;\n    }\n\n    private resolveRuntimeOptions(\n        options: Partial<DetectionRuntimeOptions> = {}\n    ): DetectionRuntimeOptions {\n        return {\n            ...this.options,\n            ...options,\n        };\n    }\n\n    private createProgress(current: number): OcrProgress {\n        return {\n            current,\n            remain: DetectionService.TOTAL_PROGRESS_STEPS - current,\n            total: DetectionService.TOTAL_PROGRESS_STEPS,\n        };\n    }\n\n    /**\n     * Preprocess an image for text detection\n     */\n    private async preprocessDetection(\n        image: Image,\n        runtimeOptions: DetectionRuntimeOptions\n    ): Promise<PreprocessDetectionResult> {\n        const resizeParams = this.calculateResizeDimensions(image, runtimeOptions);\n\n        const resizedImage = image.resize({\n            width: resizeParams.dstWidth,\n            height: resizeParams.dstHeight,\n        });\n        const tensor = resizedImage.tensor({\n            mean_values: runtimeOptions.mean,\n            norm_values: runtimeOptions.stdDeviation,\n        });\n\n        return {\n            tensor,\n            resizeParams,\n        };\n    }\n\n    /**\n     * Calculate dimensions for resizing the image\n     */\n    private calculateResizeDimensions(image: Image, runtimeOptions: DetectionRuntimeOptions) {\n        const MAX_SIDE_LEN = runtimeOptions.maxSideLength;\n        const { width: srcWidth, height: srcHeight } = image;\n        const ratio = srcWidth > srcHeight ? MAX_SIDE_LEN / srcWidth : MAX_SIDE_LEN / srcHeight;\n        let dstWidth = Math.floor(srcWidth * ratio);\n        let dstHeight = Math.floor(srcHeight * ratio);\n        // Ensure dimensions are multiples of 32 for model compatibility\n        if (dstWidth % 32 !== 0) dstWidth = Math.max(Math.floor(dstWidth / 32) * 32, 32);\n        if (dstHeight % 32 !== 0) dstHeight = Math.max(Math.floor(dstHeight / 32) * 32, 32);\n        const scaleWidth = dstWidth / srcWidth;\n        const scaleHeight = dstHeight / srcHeight;\n\n        return {\n            srcHeight,\n            srcWidth,\n            dstHeight,\n            dstWidth,\n            scaleWidth,\n            scaleHeight,\n        };\n    }\n\n    /**\n     * Run the detection model inference\n     */\n    private async runInference(\n        tensor: Float32Array,\n        resizeParams: ResizeParams\n    ): Promise<Float32Array | null> {\n        const inputTensor = new this.ortModule.Tensor(\"float32\", tensor, [\n            1,\n            3,\n            resizeParams.dstHeight,\n            resizeParams.dstWidth,\n        ]);\n\n        const feeds = { x: inputTensor };\n        const results = await this.session.run(feeds);\n        const outputTensor = results[this.session.outputNames[0] || \"fetch_name_0\"];\n        if (!outputTensor) {\n            return null;\n        }\n\n        return outputTensor.data as Float32Array;\n    }\n\n    /**\n     * Process detection results to extract bounding boxes\n     */\n    private postprocessDetection(\n        detection: Float32Array,\n        input: PreprocessDetectionResult,\n        runtimeOptions: DetectionRuntimeOptions\n    ): Box[] {\n        const { dstWidth, dstHeight } = input.resizeParams;\n        const greyImage = new Image(\n            dstWidth,\n            dstHeight,\n            1,\n            new Uint8Array(detection.map((v) => Math.round(v * 255)))\n        );\n        const thresholdedImage = greyImage.threshold({\n            threshold: 255 * runtimeOptions.textPixelThreshold,\n        });\n        const dilateImage = thresholdedImage.dilate({\n            norm: \"LInf\",\n            k: runtimeOptions.dilationKernelSize,\n        });\n        const boxes = dilateImage.contours({\n            minArea: runtimeOptions.minimumAreaThreshold,\n        });\n        const finalBoxes = boxes.map((box) => {\n            const paddedBox = this.applyPaddingToRect(box, dstWidth, dstHeight, runtimeOptions);\n            const finalBox = this.convertToOriginalCoordinates(paddedBox, input.resizeParams);\n            return finalBox;\n        });\n        return finalBoxes;\n    }\n\n    /**\n     * Apply padding to a rectangle\n     */\n    private applyPaddingToRect(\n        rect: { x: number; y: number; width: number; height: number },\n        maxWidth: number,\n        maxHeight: number,\n        runtimeOptions: DetectionRuntimeOptions\n    ) {\n        const paddingVertical = runtimeOptions.paddingBoxVertical;\n        const paddingHorizontal = runtimeOptions.paddingBoxHorizontal;\n        const verticalPadding = Math.round(rect.height * paddingVertical);\n        const horizontalPadding = Math.round(rect.height * paddingHorizontal);\n\n        let x = rect.x - horizontalPadding;\n        let y = rect.y - verticalPadding;\n        let width = rect.width + 2 * horizontalPadding;\n        let height = rect.height + 2 * verticalPadding;\n\n        x = Math.max(0, x);\n        y = Math.max(0, y);\n\n        const rightEdge = Math.min(maxWidth, rect.x + rect.width + horizontalPadding);\n        const bottomEdge = Math.min(maxHeight, rect.y + rect.height + verticalPadding);\n        width = rightEdge - x;\n        height = bottomEdge - y;\n\n        return { x, y, width, height };\n    }\n\n    /**\n     * Convert coordinates from resized image back to original image\n     */\n    private convertToOriginalCoordinates(\n        rect: { x: number; y: number; width: number; height: number },\n        resizeParams: ResizeParams\n    ): Box {\n        const scaledX = rect.x / resizeParams.scaleWidth;\n        const scaledY = rect.y / resizeParams.scaleHeight;\n        const scaledWidth = rect.width / resizeParams.scaleWidth;\n        const scaledHeight = rect.height / resizeParams.scaleHeight;\n\n        const x = Math.max(0, Math.round(scaledX));\n        const y = Math.max(0, Math.round(scaledY));\n        const width = Math.min(resizeParams.srcWidth - x, Math.round(scaledWidth));\n        const height = Math.min(resizeParams.srcHeight - y, Math.round(scaledHeight));\n\n        return { x, y, width, height };\n    }\n}\n","import { DEFAULT_RECOGNITION_OPTIONS, DEFAULT_RECOGNITION_ORDERING_OPTIONS } from \"../constants.ts\";\nimport type {\n    Box,\n    OcrProgress,\n    OrtInferenceSession,\n    OrtModule,\n    OrtTensor,\n    RecognitionOptions,\n    RecognitionOrderingOptions,\n    RecognitionRuntimeOptions,\n} from \"../interface.ts\";\nimport type { Image } from \"../utils/image.ts\";\n\nexport interface RecognitionResult {\n    text: string;\n    box: Box;\n    confidence: number;\n}\n\nexport interface SingleRecognitionTask {\n    index: number;\n    image: Image;\n    box: Box;\n    charWhiteSet?: Set<string>;\n}\n\n/**\n * Service for detecting and recognizing text in images\n */\nexport class RecognitionService {\n    private readonly options: RecognitionRuntimeOptions;\n    private readonly session: OrtInferenceSession;\n    private readonly ortModule: OrtModule;\n\n    constructor(\n        ortModule: OrtModule,\n        session: OrtInferenceSession,\n        options: Partial<RecognitionRuntimeOptions> = {}\n    ) {\n        this.session = session;\n        this.ortModule = ortModule;\n\n        this.options = {\n            ...DEFAULT_RECOGNITION_OPTIONS,\n            ...options,\n        };\n    }\n\n    /**\n     * Main method to run text recognition on an image with detected regions\n     * @param image The original image buffer or image in Canvas\n     * @param detection Array of bounding boxes from text detection\n     * @returns Array of recognition results with text and bounding box, sorted in reading order\n     */\n    async run(\n        image: Image,\n        detection: Box[],\n        options?: RecognitionOptions\n    ): Promise<RecognitionResult[]> {\n        const recognitionOptions = this.resolveRuntimeOptions(options?.recognition);\n        const orderingOptions = this.resolveOrderingOptions(options?.ordering);\n        const validBoxes = this.sortBoxesByReadingOrder(\n            detection.filter((box) => box.width > 0 && box.height > 0),\n            orderingOptions\n        );\n        const results: RecognitionResult[] = [];\n        const charWhiteListSet = options?.charWhiteList?.length\n            ? new Set(options.charWhiteList)\n            : undefined;\n        const total = validBoxes.length;\n        const onProgress = options?.onProgress;\n\n        onProgress?.({\n            type: \"rec\",\n            stage: \"start\",\n            progress: this.createProgress(0, total),\n        });\n\n        for (const [i, box] of validBoxes.entries()) {\n            const result = await this.processBox(\n                {\n                    image: image,\n                    index: i,\n                    box: box,\n                    charWhiteSet: charWhiteListSet,\n                },\n                recognitionOptions\n            );\n            if (result) {\n                results.push(result);\n            }\n            onProgress?.({\n                type: \"rec\",\n                stage: \"item\",\n                progress: this.createProgress(i + 1, total),\n                index: i,\n                box,\n                result: result ?? undefined,\n            });\n        }\n\n        onProgress?.({\n            type: \"rec\",\n            stage: \"complete\",\n            progress: this.createProgress(total, total),\n        });\n\n        return results;\n    }\n\n    private resolveRuntimeOptions(\n        options: Partial<RecognitionRuntimeOptions> = {}\n    ): RecognitionRuntimeOptions {\n        return {\n            ...this.options,\n            ...options,\n        };\n    }\n\n    private resolveOrderingOptions(\n        options: Partial<RecognitionOrderingOptions> = {}\n    ): RecognitionOrderingOptions {\n        return {\n            ...DEFAULT_RECOGNITION_ORDERING_OPTIONS,\n            ...options,\n        };\n    }\n\n    /**\n     * Process a single text box\n     */\n    private async processBox(\n        task: SingleRecognitionTask,\n        runtimeOptions: RecognitionRuntimeOptions\n    ): Promise<RecognitionResult | null> {\n        const { image, box } = task;\n\n        const crop = image.crop(box);\n        const resizedCrop = crop.resize({\n            height: runtimeOptions.imageHeight,\n        });\n        const tensor = resizedCrop.tensor({\n            mean_values: runtimeOptions.mean,\n            norm_values: runtimeOptions.stdDeviation,\n        });\n\n        const inputTensor = new this.ortModule.Tensor(\"float32\", tensor, [\n            1,\n            3,\n            resizedCrop.height,\n            resizedCrop.width,\n        ]);\n        const { data: outputData, dims: shape } = await this.runInference(inputTensor);\n\n        const [, sequenceLength, numClasses] = shape;\n        const { text: recognizedText, confidence } = this.ctcLabelDecode(\n            outputData as Float32Array,\n            sequenceLength,\n            numClasses,\n            runtimeOptions,\n            task.charWhiteSet\n        );\n\n        return { text: recognizedText, box, confidence };\n    }\n\n    /**\n     * Sort recognition results by reading order (top to bottom, left to right)\n     */\n    private sortBoxesByReadingOrder(\n        boxes: Box[],\n        orderingOptions: RecognitionOrderingOptions\n    ): Box[] {\n        if (!orderingOptions.sortByReadingOrder) {\n            return [...boxes];\n        }\n\n        return [...boxes].sort((boxA, boxB) => {\n            if (\n                Math.abs(boxA.y - boxB.y) <\n                (boxA.height + boxB.height) * orderingOptions.sameLineThresholdRatio\n            ) {\n                return boxA.x - boxB.x;\n            }\n            return boxA.y - boxB.y;\n        });\n    }\n\n    private createProgress(current: number, total: number): OcrProgress {\n        return {\n            current,\n            remain: total - current,\n            total,\n        };\n    }\n\n    /**\n     * Runs the ONNX inference session with the prepared tensor\n     */\n    private async runInference(inputTensor: OrtTensor): Promise<OrtTensor> {\n        const feeds = { x: inputTensor };\n        const results = await this.session.run(feeds);\n\n        const outputNodeName = Object.keys(results)[0];\n        const outputTensor = results[outputNodeName];\n\n        if (!outputTensor) {\n            throw new Error(\n                `Recognition output tensor '${outputNodeName}' not found. Available keys: ${Object.keys(results)}`\n            );\n        }\n\n        return outputTensor;\n    }\n\n    private ctcLabelDecode(\n        logits: Float32Array,\n        sequenceLength: number,\n        numClasses: number,\n        runtimeOptions: RecognitionRuntimeOptions,\n        charWhiteSet?: Set<string>\n    ): { text: string; confidence: number } {\n        const dict = runtimeOptions.charactersDictionary;\n        let text = \"\";\n        const scores: number[] = [];\n\n        let lastIndex = -1;\n\n        for (let t = 0; t < sequenceLength; t++) {\n            let maxScore = 0;\n            let maxScoreIndex = 0;\n\n            const offset = t * numClasses;\n            for (let i = 0; i < numClasses; i++) {\n                const val = logits[offset + i];\n                if (val > maxScore) {\n                    maxScore = val;\n                    maxScoreIndex = i;\n                }\n            }\n\n            if (maxScoreIndex === lastIndex) {\n                continue;\n            }\n\n            lastIndex = maxScoreIndex;\n\n            if (maxScoreIndex === 0) {\n                continue;\n            }\n\n            const char = dict[maxScoreIndex] || \"\";\n\n            if (charWhiteSet && !charWhiteSet.has(char) && char !== \" \") {\n                continue;\n            }\n\n            text += char;\n            scores.push(maxScore);\n        }\n\n        return {\n            text,\n            confidence:\n                scores.length > 0\n                    ? scores.reduce((sum, score) => sum + score, 0) / scores.length\n                    : 0,\n        };\n    }\n}\n","import {\n    DEFAULT_DETECTION_OPTIONS,\n    DEFAULT_PADDLE_OPTIONS,\n    DEFAULT_PROCESS_RECOGNITION_OPTIONS,\n    DEFAULT_RECOGNITION_OPTIONS,\n    DEFAULT_RECOGNITION_ORDERING_OPTIONS,\n} from \"../constants.ts\";\nimport type {\n    DetectionRuntimeOptions,\n    ImageInput,\n    OrtInferenceSession,\n    PaddleOptions,\n    ProcessRecognitionOptions,\n    RecognitionOptions,\n    RecognitionOrderingOptions,\n    RecognitionRuntimeOptions,\n} from \"../interface.ts\";\nimport { Image } from \"../utils/image.ts\";\nimport { DetectionService } from \"./detection.ts\";\nimport { type RecognitionResult, RecognitionService } from \"./recognition.ts\";\n\nexport interface PaddleOcrResult {\n    text: string;\n    lines: RecognitionResult[][];\n    confidence: number;\n}\n\nexport interface FlattenedPaddleOcrResult {\n    text: string;\n    results: RecognitionResult[];\n    confidence: number;\n}\n\n/**\n * PaddleOcrService - Provides OCR functionality using PaddleOCR models\n *\n * This service can be used either as a singleton or as separate instances\n * depending on your application needs.\n */\nexport class PaddleOcrService {\n    options: PaddleOptions;\n\n    detectionSession: OrtInferenceSession | null = null;\n    detectionService: DetectionService | null = null;\n\n    recognitionSession: OrtInferenceSession | null = null;\n    recognitionService: RecognitionService | null = null;\n\n    /**\n     * Create a new PaddleOcrService instance\n     * @param options Optional configuration options\n     */\n    constructor(options?: Partial<PaddleOptions>) {\n        if (!options?.ort) {\n            throw new Error(\n                \"PaddleOcrService requires the 'ort' option to be set with onnxruntime-node or onnxruntime-wen.\"\n            );\n        }\n        this.options = {\n            ...DEFAULT_PADDLE_OPTIONS,\n            ...(options || {}),\n        };\n    }\n\n    /**\n     * Initialize the OCR service by loading models\n     */\n    public async initialize(): Promise<void> {\n        const ort = this.options.ort;\n        if (!ort) {\n            throw new Error(\n                \"PaddleOcrService requires the 'ort' option to be set with onnxruntime-node or onnxruntime-wen.\"\n            );\n        }\n\n        // Init detection service\n        const detectionModelBuffer = this.options.detection?.modelBuffer;\n        if (!detectionModelBuffer) {\n            throw new Error(\n                \"Detection model buffer is required. Please provide a valid ONNX model.\"\n            );\n        }\n        this.detectionSession = await ort.InferenceSession.create(detectionModelBuffer);\n        const { modelBuffer: _detectionModelBuffer, ...detectionOptions } =\n            this.options.detection ?? {};\n        this.detectionService = new DetectionService(ort, this.detectionSession, detectionOptions);\n\n        // Init recognition service\n        const recognitionModelBuffer = this.options.recognition?.modelBuffer;\n        if (!recognitionModelBuffer) {\n            throw new Error(\n                \"Recognition model buffer is required. Please provide a valid ONNX model.\"\n            );\n        }\n        this.recognitionSession = await ort.InferenceSession.create(recognitionModelBuffer);\n        const { modelBuffer: _recognitionModelBuffer, ...recognitionOptions } =\n            this.options.recognition ?? {};\n        this.recognitionService = new RecognitionService(\n            ort,\n            this.recognitionSession,\n            recognitionOptions\n        );\n    }\n\n    /**\n     * Check if the service is initialized with models loaded\n     */\n    public isInitialized(): boolean {\n        return this.detectionSession !== null && this.recognitionSession !== null;\n    }\n\n    /**\n     * Create a new instance instead of using the singleton\n     * This is useful when you need multiple instances with different models\n     * @param options Configuration options for this specific instance\n     */\n    public static async createInstance(options?: PaddleOptions): Promise<PaddleOcrService> {\n        const instance = new PaddleOcrService(options);\n        await instance.initialize();\n\n        return instance;\n    }\n\n    private resolveDetectionRuntimeOptions(\n        options: Partial<DetectionRuntimeOptions> = {}\n    ): DetectionRuntimeOptions {\n        const { modelBuffer: _modelBuffer, ...instanceOptions } = this.options.detection ?? {};\n\n        return {\n            ...DEFAULT_DETECTION_OPTIONS,\n            ...instanceOptions,\n            ...options,\n        };\n    }\n\n    private resolveRecognitionRuntimeOptions(\n        options: Partial<RecognitionRuntimeOptions> = {}\n    ): RecognitionRuntimeOptions {\n        const { modelBuffer: _modelBuffer, ...instanceOptions } = this.options.recognition ?? {};\n\n        return {\n            ...DEFAULT_RECOGNITION_OPTIONS,\n            ...instanceOptions,\n            ...options,\n        };\n    }\n\n    private resolveRecognitionOrderingOptions(\n        options: Partial<RecognitionOrderingOptions> = {}\n    ): RecognitionOrderingOptions {\n        return {\n            ...DEFAULT_RECOGNITION_ORDERING_OPTIONS,\n            ...options,\n        };\n    }\n\n    /**\n     * Runs object detection on the provided image input, then performs\n     * recognition on the detected regions.\n     *\n     * @param image - The raw image data as an ArrayBuffer or Canvas.\n     * @param options - Optional configuration for the recognition output, e.g., `{ flatten: true }`.\n     * @return A promise that resolves to the OCR result, either grouped by lines or as a flat list.\n     */\n    public async recognize(\n        input: ImageInput,\n        options?: RecognitionOptions\n    ): Promise<RecognitionResult[]> {\n        if (!this.detectionService || !this.recognitionService) {\n            throw new Error(\"PaddleOcrService is not initialized. Please call initialize() first.\");\n        }\n        const channels = input.data.length / (input.width * input.height);\n        if (!Number.isInteger(channels) || channels < 1 || channels > 4) {\n            throw new Error(\n                `Invalid input data: ${input.data} for image size ${input.width}x${input.height}. Expected 1, 3, or 4 channels.`\n            );\n        }\n        const detectionRuntimeOptions = this.resolveDetectionRuntimeOptions(options?.detection);\n        const recognitionRuntimeOptions = this.resolveRecognitionRuntimeOptions(\n            options?.recognition\n        );\n        const orderingOptions = this.resolveRecognitionOrderingOptions(options?.ordering);\n        if (!recognitionRuntimeOptions.charactersDictionary?.length) {\n            throw new Error(\n                \"Recognition charactersDictionary is required. Provide it in createInstance({ recognition }) or recognize(_, { recognition }).\"\n            );\n        }\n        let image = new Image(input.width, input.height, channels, input.data);\n\n        const padding = detectionRuntimeOptions.padding;\n        if (padding) {\n            image = image.padding({\n                padding,\n                color: [255, 255, 255, 255],\n            });\n        }\n        const detection = await this.detectionService.run(image, {\n            ...detectionRuntimeOptions,\n            onProgress: options?.onProgress,\n        });\n        const recognition = await this.recognitionService.run(image, detection, {\n            ...options,\n            detection: detectionRuntimeOptions,\n            recognition: recognitionRuntimeOptions,\n            ordering: orderingOptions,\n        });\n\n        return recognition;\n    }\n\n    /**\n     * Processes raw recognition results to generate the final text,\n     * grouped lines, and overall confidence.\n     */\n    processRecognition(\n        recognition: RecognitionResult[],\n        options?: ProcessRecognitionOptions\n    ): PaddleOcrResult {\n        const result: PaddleOcrResult = {\n            text: \"\",\n            lines: [],\n            confidence: 0,\n        };\n\n        if (!recognition.length) {\n            return result;\n        }\n\n        // Calculate overall confidence as the average of all individual confidences\n        const totalConfidence = recognition.reduce((sum, r) => sum + r.confidence, 0);\n        result.confidence = totalConfidence / recognition.length;\n        const processOptions = {\n            ...DEFAULT_PROCESS_RECOGNITION_OPTIONS,\n            ...options,\n        };\n\n        let currentLine: RecognitionResult[] = [recognition[0]];\n        let fullText = recognition[0].text;\n        let avgHeight = recognition[0].box.height;\n\n        for (let i = 1; i < recognition.length; i++) {\n            const current = recognition[i];\n            const previous = recognition[i - 1];\n\n            const verticalGap = Math.abs(current.box.y - previous.box.y);\n            const threshold = avgHeight * processOptions.lineMergeThresholdRatio;\n\n            if (verticalGap <= threshold) {\n                currentLine.push(current);\n                fullText += ` ${current.text}`;\n\n                avgHeight =\n                    currentLine.reduce((sum, r) => sum + r.box.height, 0) / currentLine.length;\n            } else {\n                result.lines.push([...currentLine]);\n\n                fullText += `\\n${current.text}`;\n\n                currentLine = [current];\n                avgHeight = current.box.height;\n            }\n        }\n\n        if (currentLine.length > 0) {\n            result.lines.push([...currentLine]);\n        }\n\n        result.text = fullText;\n        return result;\n    }\n\n    /**\n     * Releases the onnx runtime session for both\n     * detection and recognition model.\n     */\n    public async destroy(): Promise<void> {\n        await this.detectionSession?.release();\n        await this.recognitionSession?.release();\n    }\n}\n\nexport default PaddleOcrService;\n"],"mappings":"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"}