[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-93319":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":17,"compositeScore":18,"rankGlobal":9,"rankLanguage":9,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":9,"pushedAt":9,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":15,"starSnapshotCount":15,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},93319,"light-ocr","arcships\u002Flight-ocr","arcships","C++17 PP-OCRv6 small OCR core with an asynchronous Node-API adapter",null,"C++",192,11,105,5,0,80,31,71.24,"Apache License 2.0",false,"main",true,[],"2026-07-22 04:02:08","# light-ocr\n\n[![Core CI](https:\u002F\u002Fgithub.com\u002Farcships\u002Flight-ocr\u002Factions\u002Fworkflows\u002Fcore.yml\u002Fbadge.svg?branch=main)](https:\u002F\u002Fgithub.com\u002Farcships\u002Flight-ocr\u002Factions\u002Fworkflows\u002Fcore.yml)\n[![License](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002Farcships\u002Flight-ocr)](LICENSE)\n[![C++17](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FC%2B%2B-17-00599C.svg)](https:\u002F\u002Fisocpp.org\u002F)\n[![Node--API v8](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FNode--API-v8-339933.svg)](bindings\u002Fnode\u002FREADME.md)\n[![npm](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002F%40arcships%2Flight-ocr?color=CB3837)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@arcships\u002Flight-ocr)\n\nEnglish | [简体中文](README.zh-CN.md)\n\n![light-ocr pixel-art banner](docs\u002Fassets\u002Flight-ocr-banner.png)\n\n**Offline OCR for native and Node.js applications, powered by PP-OCRv6 Small.**\n\n`light-ocr` turns images into ordered text lines, confidence scores, and quadrilateral boxes—inside your own process, without sending an image to a cloud service or running a Python sidecar. The native Core accepts decoded pixels; the Node.js adapter on `main` also accepts in-memory JPEG and PNG bytes.\n\nIt is made for products where OCR should feel like a local capability: quick to invoke, private by default, and straightforward to embed into an existing image pipeline.\n\n> **Available on npm:** `@arcships\u002Flight-ocr@0.2.0` includes the default PP-OCRv6 Small model, prebuilt native runtimes for all Tier 1 platforms, opt-in tiled detection, and direct in-memory JPEG\u002FPNG input for Node.js. See [Package support](#package-support).\n\n> **Apple acceleration on `main`:** the upcoming `0.2.1` source candidate adds an opt-in Direct Core ML path for macOS 15+. Across two locked workloads on the qualified Apple M4 Max, it delivered a **2.30×–2.85× warm end-to-end speedup** over the 12-thread CPU profile while reducing OCR process CPU time by **95.91%–97.67%**. This provider is not included in the published `0.2.0` npm packages yet.\n\n## Where light-ocr fits\n\n| Use case | What light-ocr provides |\n| --- | --- |\n| **Desktop and local-first apps** | Extract text from screenshots, selections, clipboard images, notes, and imported pages without uploading user content. |\n| **Private document workflows** | Read text from scanned forms, receipts, labels, and internal documents after your application renders or decodes them. |\n| **Image, camera, and media tools** | Add searchable text, copy-text actions, overlays, indexing, or accessibility features to an existing pixel pipeline. |\n| **On-premise and edge software** | Run a consistent OCR model in kiosks, terminals, appliances, or controlled networks where a cloud dependency is undesirable. |\n| **Native and Node.js services** | Embed OCR directly instead of deploying and supervising a separate Python process or OCR daemon. |\n\nThe current model is best suited to general text detection and recognition in CJK\u002FLatin mixed content. The Node.js adapter can decode in-memory JPEG and PNG inputs; the native core still accepts decoded pixels only. PDF rendering, other image formats, document layout analysis, tables, formulas, and translation remain the host application's responsibility.\n\n## Why this project exists\n\nCloud OCR is convenient, but it introduces uploads, network availability, recurring cost, and a new privacy boundary. Operating-system OCR APIs avoid the network, but their behavior and availability vary by platform. PaddleOCR offers excellent models, while its usual Python deployment is not always a natural fit for desktop software, native products, or a Node.js application.\n\n`light-ocr` closes that gap with one reusable native core built around official PP-OCRv6 Small models. Applications keep control of scheduling, storage, and user experience; the library focuses on turning images into structured OCR results while preserving a raw-pixel native boundary.\n\n## Why use light-ocr\n\n- **Local by default.** Recognition performs no runtime network access and does not start a child process.\n- **Ready for real application pipelines.** It accepts `GRAY8`, `RGB8`, `BGR8`, and `RGBA8` pixel buffers; the Node.js adapter can also decode JPEG and PNG bytes already held in memory.\n- **Two deliberate large-image modes.** Bounded\u002F960 remains the fast, memory-conscious default. Opt-in tiled detection preserves more detail for small text and dense 2048-pixel documents while processing one detection tile at a time.\n- **Native Apple acceleration when requested.** The `0.2.1` source candidate can route FP16 detection and recognition through Core ML without changing the default CPU behavior or the public OCR result contract.\n- **A pinned, reproducible model.** The approximately 31 MB PP-OCRv6 Small bundle is integrity-checked and designed to ship with the application instead of downloading on first use.\n- **Consistent across supported platforms.** The same model and result contract are used on macOS, Linux, and Windows.\n- **Built for asynchronous hosts.** The Node-API adapter keeps inference away from the JavaScript thread, with bounded queues, cancellation, and explicit lifecycle control.\n- **Open and inspectable.** The project is Apache-2.0 licensed and tests real model behavior, high-resolution memory use, lifecycle safety, and output parity in CI.\n\n## Why PP-OCRv6 Small\n\n![Official PP-OCRv6 model and VLM accuracy comparison](docs\u002Fassets\u002Fppocrv6-model-comparison.png)\n\nThe npm package uses **PP-OCRv6 Small**. On PaddleOCR's in-house multi-scenario benchmark it reports **84.1 detection Hmean** and **81.3 weighted recognition accuracy**, while keeping the model practical for local applications. This chart and these accuracy scores come from the [official PP-OCRv6 evaluation](https:\u002F\u002Fgithub.com\u002FPaddlePaddle\u002FPaddleOCR\u002Fblob\u002F211989f046cc1878460f9e65574690c00a127a1a\u002Fdocs\u002Fversion3.x\u002Falgorithm\u002FPP-OCRv6\u002FPP-OCRv6.en.md); they are upstream quality results, not latency measurements made by this repository.\n\n## What results look like\n\nFor each detected line, light-ocr returns the recognized text, a confidence score, and its position in the original image:\n\n```json\n{\n  \"lines\": [\n    {\n      \"text\": \"HELLO 123\",\n      \"confidence\": 0.99,\n      \"box\": [\n        {\"x\": 106, \"y\": 54},\n        {\"x\": 554, \"y\": 54},\n        {\"x\": 554, \"y\": 135},\n        {\"x\": 106, \"y\": 135}\n      ]\n    }\n  ]\n}\n```\n\nCoordinates are quadrilaterals rather than axis-aligned rectangles, so rotated and perspective text can be represented without discarding geometry.\n\n## Measured speed\n\n![The 800 by 180 HELLO 123 benchmark input](docs\u002Fassets\u002Fbenchmark-generated-hello-123.png)\n\n### CPU baseline\n\nFor the exact `800×180` BGR input above, light-ocr recognized `HELLO 123` with confidence `0.9893`. The native C++ Release benchmark was run on an Apple M4 Max (16-core CPU, 128 GB RAM), macOS 26.5.1, ONNX Runtime CPU with one intra-op and one inter-op thread, using the default bounded\u002F960 strategy and recognition batch size 1.\n\n| Measurement | Result |\n| --- | ---: |\n| Warm end-to-end median | **75.678 ms\u002Fimage** (~13.2 images\u002Fs) |\n| Warm end-to-end P95 | **79.788 ms\u002Fimage** |\n| Detection + recognition inference median | **74.125 ms\u002Fimage** |\n| Model bundle load, once | 167.906 ms |\n| Engine initialization, once | 30.511 ms |\n\nThe test uses 5 warm-up runs followed by 30 measured runs. It is a small, synthetic, single-line fixture; latency varies with hardware, input dimensions, text density, and line count. The benchmark contract and comparison with the pinned Python oracle are recorded in [Implementation status](docs\u002Fimplementation-status.md#本机最终验证快照).\n\n### Apple Core ML acceleration\n\nThe `0.2.1` provider gate compared the opt-in FP16 Core ML path with the `cpu_fast` profile on one Apple M4 Max (16-core CPU, 128 GB RAM) running macOS 26.5.1. The CPU profile used up to 12 intra-op threads; each workload used 5 warm-up runs and 3 independent sets of 30 measured runs. The CPU-time reduction describes host process usage, not energy consumption.\n\n| Locked workload | CPU warm P50 | Apple warm P50 | End-to-end speedup | OCR process CPU-time reduction |\n| --- | ---: | ---: | ---: | ---: |\n| Synthetic `HELLO 123`, 800×180 | 19.774 ms | **8.599 ms** | **2.300×** | **95.91%** |\n| Dense XFUND form, 113 text lines | 943.627 ms | **331.011 ms** | **2.851×** | **97.67%** |\n\nThe accelerated output also passed all 14 locked quality fixtures: 99.6484% character similarity to the CPU oracle, 100% detection recall, 99.5508% mean matched IoU, 0.004349 mean matched confidence difference, and zero critical failures. These are parity measurements against the CPU output, not independent ground-truth accuracy; FP16 output is not byte-for-byte identical.\n\nThe formal warm performance runs peaked at 692.14 MiB RSS and the self-contained Apple model payload added 25.42 MiB. The separate same-engine 100-dense-page lifecycle run peaked at 888.11 MiB and finished 27.47 MiB below its post-warm-up baseline, showing no sustained growth in that run. First use performs offline compilation and loads recognition functions on demand: the fixed `HELLO 123` startup canary took 7.219 s on a compiled-cache miss and 1.275\u002F1.278 s on hits; the 113-line form took 53.846 s on its first full-page miss and 12.677\u002F12.677 s on hits. No provider, compiler, or model is downloaded at runtime.\n\nOnly that single M4 Max runner has real-device performance data. The evidence contract classifies it under the `Apple M4` device family for `deviceValidated`; this does not represent separate measurements of every M4 SKU. The candidate's compatibility policy is intentionally open and experimental on other macOS 15+ hardware: M1–M3 and later Apple Silicon can try the same ANE\u002FGPU route, while Intel Macs use Core ML CPU+GPU. Hardware without reviewed evidence reports `deviceValidated: false`; no speedup is claimed until that family has its own data. See the [Apple acceleration design and evidence](docs\u002Fapple-device-acceleration.md) for methodology, model placement, quality thresholds, cache behavior, and lifecycle results.\n\n## Get started\n\n### Node.js\n\nNode.js 22 and 24 are supported on macOS arm64\u002Fx64, Linux x64 glibc, and Windows x64:\n\n```bash\nnpm install @arcships\u002Flight-ocr\n```\n\nThe package installs the matching native runtime and the pinned PP-OCRv6 Small model. It does not download a model at first run or compile native code during `postinstall`. Version 0.2.0 supports both `recognizeEncoded()` and raw-pixel `recognize()`.\n\n```ts\nimport { createEngine } from \"@arcships\u002Flight-ocr\";\nimport { readFile } from \"node:fs\u002Fpromises\";\n\nconst engine = await createEngine();\nconst result = await engine.recognizeEncoded(\n  await readFile(\"image.jpg\"),\n);\n\n\u002F\u002F Raw pixels remain available when the host already owns a decode pipeline.\nconst rawResult = await engine.recognize({\n  data: pixels,\n  width,\n  height,\n  stride,\n  pixelFormat: \"rgba8\",\n});\n\nconsole.log(result.lines);\nconsole.log(rawResult.lines);\nawait engine.close();\n```\n\nThe Apple provider remains opt-in. The following is a maintainer\u002Fsource-checkout preview, not an `npm install` path for `0.2.0`. It assumes the locked self-contained Apple bundle has already been derived by the local release tooling described in [Build and release](docs\u002Fbuild-and-release.md#8-ci). Request the provider explicitly and keep the whole-session CPU fallback visible:\n\n```ts\nconst engine = await createEngine({\n  \u002F\u002F Source candidate only; the planned npm 0.2.1 package will resolve it.\n  bundlePath: \"\u002Fabsolute\u002Fpath\u002Fto\u002Fppocrv6-small-apple-20260715.1\",\n  execution: {\n    provider: \"apple\",\n    precision: \"fp16\",\n    cpuPartition: \"allow\",\n    sessionFallback: \"cpu\",\n  },\n});\n\nconsole.log(engine.info.execution.sessions.detection.deviceValidated);\n```\n\n`cpuPartition: \"allow\"` works on both Apple Silicon and Intel Macs. The strict GPU-only profile is Apple-Silicon-only. Normal npm users should keep the default CPU provider until the Apple payload is published.\n\nSee the [Node.js guide](bindings\u002Fnode\u002FREADME.md) for the full API, cancellation, queue limits, and lifecycle behavior.\n\n### C++ core\n\nRequirements: Python 3 for bootstrap tooling, CMake, and a C++17 compiler. Dependencies and model inputs are pinned; the built runtime does not depend on Python.\n\n```bash\npython3 tools\u002Fbootstrap_dependencies.py --cache-dir .cache\u002Fdependencies\npython3 tools\u002Fbootstrap_models.py --cache-dir .cache\u002Fmodels\n\ncmake --preset release \\\n  -DLIGHT_OCR_DEPENDENCY_CACHE_DIR=\"$PWD\u002F.cache\u002Fdependencies\"\ncmake --build --preset release --parallel\nctest --preset release\n```\n\nSee [Build and release](docs\u002Fbuild-and-release.md) for platform prerequisites and [C++ API](docs\u002Fnative-api.md) for integration.\n\n## Package support\n\n| Distribution | Status | Platforms |\n| --- | --- | --- |\n| C++ core source | Available | macOS arm64\u002Fx64, Linux x64 glibc, Windows x64 |\n| Node-API adapter source | Available | Node.js 22 and 24 |\n| [`@arcships\u002Flight-ocr`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@arcships\u002Flight-ocr) | `0.2.0` published | Node.js 22\u002F24 on all Tier 1 platforms |\n| [`@arcships\u002Flight-ocr-model-ppocrv6-small`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@arcships\u002Flight-ocr-model-ppocrv6-small) | `0.2.0` published | Platform-independent required model dependency |\n| Platform native npm packages | `0.2.0` published | macOS arm64\u002Fx64, Linux x64 glibc, Windows x64 |\n\nThe npm distribution installs one facade, one required model package, and the native package matching the host platform. Package contents, versioning, and release gates are documented in [npm packaging](docs\u002Fnpm-packaging.md); immutable `0.2.0` hashes and validation evidence are recorded in the [release record](docs\u002Freleases\u002Fnpm-0.2.0.md).\n\nDirect Core ML acceleration is merged on `main` for the `0.2.1` candidate but is not part of the published `0.2.0` package set. Its release keeps the same six-package installation shape; no extra provider package or runtime download is planned.\n\n## Project status\n\n`light-ocr` is under active development. Version `0.2.0` publishes the deterministic `tiled-v1` high-resolution mode and bounded in-memory JPEG\u002FPNG decoding in the Node.js adapter without changing the raw-pixel C++ Core boundary. The current `0.2.1` source candidate adds opt-in Direct Core ML execution on macOS while preserving CPU as the default.\n\nAs a pre-1.0 project, public APIs and package layout may still evolve; the project does not currently promise a stable cross-release C++ ABI.\n\nThe Core CI builds and tests the project on:\n\n- macOS arm64\n- macOS x64\n- Linux x64 with glibc\n- Windows x64\n\nIt also runs sanitizers, fuzz smoke tests, offline-runtime checks, output parity, quality, and memory gates. Performance qualification is a separate, explicitly triggered workflow and is not part of ordinary CI or release preflight. See the [current implementation status](docs\u002Fimplementation-status.md) for verified results and known gaps.\n\n## Documentation\n\n- [Changelog](CHANGELOG.md)\n- [C++ API](docs\u002Fnative-api.md)\n- [Node.js adapter](bindings\u002Fnode\u002FREADME.md)\n- [Build and release](docs\u002Fbuild-and-release.md)\n- [Model bundle](docs\u002Fmodel-bundle.md)\n- [Accuracy and parity](docs\u002Fparity-testing.md)\n- [High-resolution memory behavior](docs\u002Fmemory-optimization.md)\n- [Architecture](docs\u002Farchitecture.md)\n- [Implementation status](docs\u002Fimplementation-status.md)\n\n## Community\n\nIssues and pull requests are welcome. If you are considering light-ocr for a product, feel free to [open an issue](https:\u002F\u002Fgithub.com\u002Farcships\u002Flight-ocr\u002Fissues) describing the platform, image source, language mix, and expected workload. Real application scenarios help shape package priorities and future model support.\n\nWhen reporting a bug, please include the platform, input dimensions and pixel format, the model bundle ID, and a minimal reproduction when possible. Do not attach private source images unless you are comfortable publishing them.\n\n## License\n\nlight-ocr is available under the [Apache License 2.0](LICENSE). Third-party dependencies and model notices are included with their corresponding release artifacts.\n","light-ocr 是一个轻量级离线OCR引擎，基于PP-OCRv6 Small模型，提供C++17原生核心与异步Node-API适配层。核心功能包括图像文本行检测、识别、置信度输出及四边形定位框，支持内存内JPEG\u002FPNG解码（Node.js）和原始像素输入（C++），具备低延迟、零网络依赖、隐私本地化处理能力。项目已预编译支持主流平台，并在macOS 15+上集成可选Core ML加速路径。适用于桌面应用、私有文档处理、图像\u002F摄像头工具、边缘设备及需嵌入OCR能力的Node.js或原生服务场景。",2,"2026-07-16 02:30:05","CREATED_QUERY"]