@sudobility/sudojo_ocr
v1.1.46
Published
OCR library for extracting Sudoku puzzles from images (Node.js; recognition via paddle_ocr)
Maintainers
Readme
@sudobility/sudojo_ocr
Node.js library for extracting Sudoku puzzles, and optionally pencilmarks, from images.
Board detection, squaring and cropping happen in-process; digit recognition is a single HTTP call to
the paddle_ocr service. Every frontend goes through sudojo_api rather than importing this
directly. ESM-only.
The split matters: PaddleOCR emits one text block per digit on a board that fills the frame, but it has no board detector. Cropping first is what makes the geometry mapping exact -- on an uncropped photo the digits land in the wrong rows and any surrounding page text arrives as blocks.
Installation
bun add @sudobility/sudojo_ocr @sudobility/sudojo_types
bun add @napi-rs/canvas # required by the Node adapter@sudobility/sudojo_types is a peer dependency. There is no OCR engine to bundle and no language
data to download.
Usage
import { extractSudokuFromImage } from '@sudobility/sudojo_ocr';
import { createNodeAdapter } from '@sudobility/sudojo_ocr/node';
const adapter = await createNodeAdapter(); // async
const result = await extractSudokuFromImage(
adapter,
imageBuffer, // Buffer or file path
{ url: 'http://ocr.sudobility.com', timeoutMs: 30000 },
{ recognizePencilmarks: true } // optional, default false
);
console.log(result.board.original); // "004002008100400000..." ('0' = empty)
console.log(result.board.pencilmark.numbers); // 81 comma-separated entries
console.log(result.confidence); // 100
console.log(result.digitCount); // 40Accuracy
Measured against the three committed fixtures and their ground truth, cropped then recognized:
243/243 cells correct, 0.5-1.6s per board. The recognizePencilmarks flag only decides whether
autopencil is set and the legal candidates are computed -- the marks themselves are derived from
the givens by constraint propagation, never read off the image.
result.board is a SolverBoard from @sudobility/sudojo_types.
API
extractSudokuFromImage()-- Full pipeline: image -> board detection -> crop -> paddle_ocr -> block-to-cell mapping -> board assemblydetectAndCropBoard()-- Detect and crop board, returns data URLextractCellImages()-- Extract 81 cell images as data URLsrecognizeBoard()/mapBlocksToBoard()-- The paddle client and its geometry mapping, usable on their own- Platform adapter:
createNodeAdapter() - Low-level image-processing and board-detection algorithms are also exported (see
src/index.ts)
Development
bun run build # Build ESM to dist/ (no CJS)
bun run test # Run Vitest (offline; fakes the paddle response)
PADDLE_OCR_URL=http://ocr.sudobility.com bun run test # also run the live 81/81 checks
bun run typecheck # TypeScript check
bun run lint # ESLint (includes Prettier rules)
bun run verify # Typecheck + lint + test + buildSee CLAUDE.md for the architecture and gotchas, and docs/ for OCR tuning notes.
Related Packages
sudojo_api-- Backend/ocrroute (Node adapter). Dispatches by image source: camera captures come here, library images prefersudojo_ocr_mland fall back herepaddle_ocr-- The PaddleOCR service this library calls for recognitionsudojo_app,sudojo_app_rn,sudojo_extension,sudojo_bot-- Frontends; they callsudojo_api, not this librarysudojo_ocr_ml-- Python ONNX whole-board OCR service; the preferred backend for library images@sudobility/sudojo_types-- Peer dependency; definesSolverBoard, the result'sboardfield
License
BUSL-1.1
