Instructions to use litert-community/PP-OCRv6-Small-LiteRT with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use litert-community/PP-OCRv6-Small-LiteRT with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
PP-OCRv6 Small LiteRT runtime examples
Use these four unchanged FP32 files with LiteRT 2.2.0. The Android wrapper explicitly requests GPU FP32. That setting matters: the default GPU configuration failed numerical parity, while explicit FP32 passed all 37 tensor cases and all six complete image-pipeline cases on the tested Samsung S26 SM8850, Android 16. Those are small synthetic fixture gates, not a broad accuracy benchmark or a guarantee for another GPU.
| File | Input float32 NCHW | Output float32 probabilities |
|---|---|---|
ppocrv6_small_det_640_fp32.tflite |
[1,3,640,640] |
[1,1,640,640] |
ppocrv6_small_rec_320_fp32.tflite |
[1,3,48,320] |
[1,40,18710] |
ppocrv6_small_rec_640_fp32.tflite |
[1,3,48,640] |
[1,80,18710] |
ppocrv6_small_rec_960_fp32.tflite |
[1,3,48,960] |
[1,120,18710] |
Every model uses signature serving_default, input args_0, output output_0. Both examples verify the model SHA-256 and query actual buffer or tensor types/shapes. Model hashes are pinned in the source. characters.json contains all 18,710 tokens, including blank at index 0 and the final space token. Do not append, delete or reorder tokens; its exact SHA-256 is 9c89db8aa95ad30c83ee305d53d366c6bba3f85ff2eab0375ef345fd50b0674a.
Android Kotlin
Add the Google Maven repository and the versioned dependency to your own application. The tested app used Kotlin 2.2.10, Java/JVM target 17, minSdk 26, compileSdk 35 and arm64-v8a. This example needs no vendor SDK, NPU plugin, APK or precompiled cache.
// Dependency repository: google()
dependencies {
implementation("com.google.ai.edge.litert:litert:2.2.0")
}
Copy examples/android/PpocrV6Gpu.kt, examples/android/OcrPreprocessing.kt and examples/android/TorchUint8Resize.kt into your app. They use package com.ppocrv6.litert. Place the four models and unchanged dictionary in application-private files and pass those paths explicitly. If downloading or copying from assets, complete that operation before constructing the runtime.
import com.ppocrv6.litert.*
import java.io.File
// Run this entire lifetime on one dedicated worker thread, off the UI thread.
val modelDir = File(context.filesDir, "ppocrv6")
val vocabulary = PpocrV6Gpu.loadVocabulary(File(modelDir, "characters.json"))
PpocrV6Gpu(modelDir).use { runtime ->
val creationMs = runtime.prepare(OcrGraph.DET_640)
// For a prepared, finite FloatArray in the exact [1,3,640,640] NCHW order:
val det = runtime.infer(OcrGraph.DET_640, detectorNchw)
val map = det.probabilities // 640*640 values, fully read back to the CPU.
// Or supply exactly 640x640 interleaved RGB uint8 pixels:
val detFromPixels = runtime.detect(squareRgb640)
// Supply an upright line crop from the DB/crop steps below:
val text = runtime.recognize(cropRgb, cropWidth, cropHeight, vocabulary)
println(text.text)
}
The variables detectorNchw, squareRgb640, cropRgb, cropWidth and cropHeight are caller-supplied data. ByteArray pixels are packed R,G,B; Kotlin's signed bytes are interpreted as unsigned 0–255. No Bitmap, camera orientation, color conversion, DB geometry or crop extraction is hidden in infer(). detect() adds only the provided exact DET preprocessing, and recognize() adds exact REC resize/normalization/padding and greedy CTC.
GPU selection is exactly:
CompiledModel.Options(setOf(Accelerator.GPU)).apply {
gpuOptions = CompiledModel.GpuOptions(
precision = CompiledModel.GpuOptions.Precision.FP32)
}
GPU backend selection stays automatic, as in the passing S26 run; program serialization is not enabled. The wrapper makes no CPU retry or NPU request. Creation/inference errors propagate. A successful creation alone does not prove accelerator placement or numerical correctness on a new device; compare its actual readback and review delegate logs. Do not switch to default/FP16 GPU precision while retaining the FP32 quality claim.
OcrInference.runAndReadbackMs spans run() and readFloat(). GPU run() may only enqueue work. Input transfer is reported separately; preprocessing, DB/cropping and CTC are outside this graph-only timing. prepare() reports first model creation plus buffer allocation in this runtime instance; caches have not been proven cold. Models stay loaded until close().
Image-to-text integration contract
The minimally packaged wrapper starts and ends at the model tensor boundary. To reproduce the tested complete pipeline, implement the following surrounding image steps exactly; this recipe does not claim that a new camera-image integration has already passed the six-page gate.
- Decode an opaque image into interleaved RGB uint8. The tested detector pages are exactly 640×640.
OcrPreprocessing.det()requires that size. There is no implicitly validated arbitrary-size resize/letterbox or rotation policy. If adapting arbitrary images, define that policy and coordinate inversion explicitly and gate it separately. - Normalize and change layout with
OcrPreprocessing.det(rgb). The exact official processor's incoming RGB means are[.406,.456,.485], standard deviations[.225,.224,.229]. Compute each mean/std as float32 times 255, subtract/divide in float32, and write channels in reverse order to BGR NCHW. These are not replaceable by rounded decimal shortcuts such as57.12f. - Read the DET probability map, then apply DB postprocessing with bitmap threshold 0.2, box score threshold 0.45, unclip ratio 1.4, maximum candidates 3000, and minimum short side 3. Use the official analytic rectangle expansion, contour/min-area-box scoring and rounding. Do not replace it with an arbitrary polygon-offset library and assume equality.
- Sort boxes by top-left y/x, with the existing within-row correction when the y distance is below 10 pixels. For each accepted polygon, use the PaddleX min-area rectangle crop: order TL/TR/BR/BL, integer crop width/height from maximum opposite-edge lengths, OpenCV perspective transform to
(0,0),(w,0),(w,h),(0,h),INTER_CUBICandBORDER_REPLICATE. Rotate 90° counterclockwise whenheight/width >= 1.5. The validated implementation used OpenCV 5.0.0. This wrapper intentionally does not substitute axis-aligned boxes or a different image resampler. - Choose the smallest exported REC width covering
ceil(48*cropWidth/cropHeight): 320, 640 or 960. Preserve aspect ratio at height 48. Width above 960 is rejected, not compressed; the caller must handle it explicitly.OcrPreprocessing.rec()uses the provided two-pass fixed-point PyTorch uint8 bilinear port, then BGR NCHW normalization(value-127.5f)/127.5f, with normalized zero right padding. Ordinary OpenCV resize differed by one pixel value on tested crops and is not interchangeable for exact parity. - Run REC and decode all timesteps, including padding: argmax each probability vector; collapse adjacent repeated IDs; remove ID 0; concatenate dictionary entries. A blank separates repetitions. Keep spaces. Outputs are already softmax probabilities; do not softmax again. Confidence is the mean probability of emitted tokens, or
null(undefined) for an empty result.
The exact preprocessing helper algorithms were already checked on the JVM (38 byte-exact resize vectors and 39 bitwise float32 preprocessing cases), and their original application pipeline passed the real CPU/GPU image tests. This release changes their package name only. New runtime glue is compiled against the actual LiteRT 2.2.0 API; this minimal wrapper itself has not been installed and re-executed on a phone.
Python CompiledModel CPU
For the complete square-image pipeline, install the root requirements-lock.txt and run python examples/run_ocr.py fixtures/det/japanese.png from this repository. The exact preprocessing, DB polygons, perspective crops and CTC are implemented in examples/ocr.py. Both DET and REC use explicit LiteRT CompiledModel CPU inference. The public package also replays all three verification stages on the included fixtures; see conversion/README.md.
The smaller examples/run_cpu.py is a host CPU tensor runner. Install examples/requirements-cpu.txt into your own environment; this example was exercised with Python 3.12.12. Supply either a correctly shaped float32 .npy tensor or contiguous little-endian float32 .f32 bytes. Inputs must already follow the preprocessing contract above. Neither Python example claims GPU execution.
python examples/run_cpu.py \
--models /path/to/models \
--model-id rec_320 \
--input /path/to/prepared_rec_input.f32 \
--dictionary /path/to/characters.json \
--output /path/to/rec_output.npy
The example writes the output tensor and an adjacent JSON file with queried shapes, finite checks, hashes, decoded REC text, initialization and run/readback timing. DET accepts --model-id det_640 without a dictionary. Optional --reference /path/to/same_input_oracle.npy applies max absolute error ≤0.001 and relative L2 ≤0.0001 and exits nonzero on failure. That comparison requires the same input and matching output shape.
Local release verification executed REC320 on the previously saved LiteRT input and compared against its official CPU FP32 golden. The public verification summary is release_verification.json; detailed machine-local compiler and execution logs are retained separately. The CPU runtime may log discovery/registration of other installed accelerator libraries; the model execution request here is CPU-only.
Quality and source notices
Conversion parity does not remove source-model mistakes: on the six-page fixture set the official/CPU/FP32-GPU pipeline had 14 TP, 3 FP, 0 FN and region CER 5/181, including three nontext shape detections and two missing spaces. This release does not claim benchmark-scale accuracy. NPU and default-GPU quality failures do not qualify those configurations for this recipe.
The runtime wrapper and CPU example are Apache-2.0. OcrPreprocessing.kt preserves the official PaddlePaddle/Hugging Face Apache-2.0 notice. TorchUint8Resize.kt preserves its PyTorch BSD-3-Clause notice and source attribution. Retain those notices when copying the files. The official models are Apache-2.0; runtime third-party dependencies retain their own licenses. No vendor binaries are included in these examples.