Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

oneocr-modelex

Extracts the ONNX sub-models and vocabularies out of Windows 11's oneocr.onemodel, in pure Java.

Windows only. Run it once. It is the bootstrap step for oneocr/onnx, which then runs OCR anywhere with no Microsoft binaries at all.

What it produces

From your own licensed Windows installation, into ~/oneocr/models/:

detector/text_detector.onnx           11.5 MB   FPN text detector
classifier/script_classifier.onnx      3.5 MB   script, orientation, print-vs-handwriting
recognizers/recognizer_<script>.onnx     9 files  CTC recognizers, 1.7-13.4 MB each
vocab/vocab_<script>.txt                 9 files  index to character, recovered per script
aux/                                     3 files  see "the three we cannot use"

Nine scripts: CJK, Cyrillic, Latin, Arabic, Devanagari, Greek, Thai, Hebrew, Tamil.

How it works

oneocr.dll links against Microsoft's own build of ONNX Runtime and reaches it through one public entry point, OrtGetApiBase(), which returns a table of roughly 200 function pointers. Slot 8 is CreateSessionFromArray, and the DLL has to hand that function fully decrypted model bytes in order to load anything at all.

So: load onnxruntime.dll first, make the table page writable with VirtualProtect, overwrite slots 8, 9 and 151 with Java FFM upcall stubs, then ask oneocr.dll to build its pipeline with model delay-load turned off. Each stub forwards to the original so the DLL keeps working, and captures the plaintext ONNX on the way past.

Vocabularies need a second trick, because the recognizers emit indices rather than characters. Slot 9 is Run, so the classifier's script_id_score output can be forced to select one chosen script and the recognizer's logsoftmax output forced to spell out a known run of consecutive vocabulary indices — then you read back the text the DLL's own decoder produces and record which character each index gave. Repeat until the vocabulary is covered, for each script.

This is userland API interception inside our own process, using documented Windows calls. No disassembler, no debugger, no driver, no patched files on disk.

Use

java --enable-native-access=ALL-UNNAMED -jar oneocr-modelex.jar
java --enable-native-access=ALL-UNNAMED -jar oneocr-modelex.jar --natives ~/oneocr --out ~/oneocr/models --no-vocab

Needs oneocr.dll, oneocr.onemodel and onnxruntime.dll in the natives folder (~/oneocr by default). JDK 22 or later. Takes about two minutes.

Two things worth knowing

The vocabulary sweep is self-checking. The obvious implementation forces a fixed block of 200 indices per pass and assumes the decoded text lines up one-for-one. It doesn't always: an index that decodes to nothing shifts everything after it, silently corrupting the rest of the vocabulary. So when the decoded length doesn't match the number of timesteps forced, this halves the range and retries, isolating the blank index instead of shifting past it. That is why the vocabularies here need no post-hoc "cleaning" pass — index i in the output file really is model index i.

The three we cannot use. Extraction also yields three small models that will not load in stock ONNX Runtime: they need com.microsoft.oneocr:OneOCRFeatureExtract, a custom operator that exists only inside oneocr.dll. They are parked in aux/ and are not part of the OCR path. What they unlock is an open question — most plausibly per-line typography, since OneOCR exports a GetOcrLineStyle function nobody has used. Tracked as PRP 20.

Corrections to prior work

The script naming in circulation is wrong on three entries, and this was established by reading the characters that actually came out rather than by trusting the vocabulary size:

  • V=179 is Tamil, not Greek — ஂ ஃ அ ஆ இ ஈ உ ஊ
  • V=244 is Greek, not Hebrew — the U+0370 block
  • V=201 is Hebrew, not Bengali — the U+0591 block

So this build of OneOCR ships no Bengali recognizer, and it does ship a Tamil one that prior work did not know existed.

The classifier index to script mapping was also measured directly rather than inferred: forcing script_id_score to index N and observing which recognizer the DLL then selects gives 0 → nothing, then CJK, Cyrillic, Latin, Arabic, Devanagari, Greek, Thai, Hebrew, Tamil.

Both are properties of one OneOCR build. A future Windows build could reorder them, and the failure would be silent — OCR would still run, in the wrong alphabet. Naming scripts from the recovered characters instead of from a size table is tracked as PRP 24.

Legal and practical

The models are Microsoft intellectual property. This tool decrypts them on the machine that owns the licence, for use on that machine. Nothing proprietary is contained in or distributed by this repository, and the extracted models must not be committed or redistributed — treat them as a build artefact with a provenance note.

The technique itself is not novel here and was published before this existed; see the credits.

Credits

About

Extracts the ONNX sub-models and vocabularies out of Windows 11 oneocr.onemodel, in pure Java. Windows only, run once. Bootstrap for oneocr/onnx.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages