Fullerene 3M: four small networks that read Latin-script pages, for Carbon-OCR

Fullerene 3M is the Latin model set of Carbon-OCR, an OCR engine in C++ and CUDA by Carbon Research: four small networks, 2,774,014 parameters in all, trained from scratch, that read scans, photos of documents and PDFs into text, HTML, markdown and JSON with boxes, in reading order with labeled blocks and table cells. On all 2,937 pages of OmniParseBench it scores a headline of 44.4 where Tesseract 5.5 scores 5.9, passes 27.3 of the text tests to Tesseract's 17.8, and on one CPU core reads 5.4 times as many pages a second. On a laptop's GPU (an RTX 4060, TensorRT) it reads all of them at 101.5 pages a second. On olmOCR-Bench it scores 45.1 to Tesseract's 34.2, by its tables, its multi-column pages and its leaving out running headers and footers; on OmniDocBench's English pages Tesseract reads plain text better (an edit distance of 0.129 to fullerene-3M's 0.165), and fullerene-3M reads their tables (29.1 TEDS to none).

Fullerene 3M at a glance

The set

Model Job Parameters Input Output
orient Page orientation, before detection 338,669 512 ร— 512 grayscale thumbnail, ink map 13 class scores: 12 angle bins of 30ยฐ, plus vertical CJK
det Line detection and pictures 442,564 The page in grayscale, long side 1024, H and W multiples of 32 4 maps at stride 2: core-band logit, top distance, bottom distance, picture logit
rec-latin Read Latin, Cyrillic and Greek lines 1,511,104 32 ร— W line crop, W a multiple of 8, ink map 800 CTC class scores per 4 px; class 0 is the blank
order Reading order, block labels, table structure 481,677 16 features per line (geometry and text cues) Successor, same-block, table row, column and cell scores, 13 block labels

Every line goes to rec-latin: this set has no script router. Block labels: Text, Section-Header, Page-Header, Page-Footer, List-Group, Table, Caption, Footnote, Table-Of-Contents, Form, Picture, Formula, Other.

Run it with Carbon-OCR, which loads all four models: orientation and deskew, detection with a second pass for tiny text, recognition, and the order model's reading order, blocks and table cells (the XY-cut where the order model is unsure). Lines that are not text (rules, slivers, unsure pieces read out of pictures) are dropped, the blocks are put in order by their geometry, columns first, and tables take their spanning cells.

carbon-ocr ocr page.png --set fullerene-3M --format html            # or text, markdown, json, hocr, alto, pdf
carbon-ocr ocr scan.pdf --set fullerene-3M --precision fp16         # the FP16 files on the CPU
carbon-ocr ocr scans/*.png --set fullerene-3M --device cuda         # the FP16 files on an NVIDIA GPU (TensorRT)
import carbon_ocr

engine = carbon_ocr.Engine("fullerene-3M")
page = engine.ocr([carbon_ocr.load_image("page.png")], html=True)[0]
print(page["html"])

The turn threshold. orient.onnx and orient.fp16.onnx carry their threshold for turning a page, 0.65, in their metadata (carbon.orient.turn_probability), which the engine reads; orient is evaluated at it (below).

Pages, read

Fullerene 3M on three invented pages, read by Carbon-OCR on a laptop's CPU (FP32 files, ONNX Runtime). Every picture is drawn from the engine's own output for the page, and the pages' text is known word for word. The full report has every number, every fault with where it comes from, and the scripts that make it all again.

A report page in two columns: every line found, 253 of its 255 words right (the two misses are one footnote mark, read into the word before it), 18 blocks labelled and in reading order, and HTML, in 152 ms on one core and 60 ms on six.

A report page with every line boxed in its block's colour and every block numbered in reading order, beside the HTML the engine wrote for it

A page of two tables: both found as tables, and all 73 cells in their row and column, 59 of them character for character; most of the rest carry the column rule beside them as a |.

A page of two tables with every cell boxed in its column's colour, beside the HTML tables the engine wrote

A rough photo of the report page, upside down and 2.5ยฐ off, under uneven light, noisy and JPEG-compressed: turned 180ยฐ by orient, levelled by 2.45ยฐ with no model, and read as well as the clean page.

The photo, upside down and tilted, and the page as the engine read it: turned, levelled, every line found

What det sees: its line-core map over the page, and the 47 line boxes the engine's decoder makes of it.

The detector's line-core map over the report page, and the line boxes made of it

What it gets wrong is the pages' structure more than their words: a heading joined to the paragraph under it, the table placed after the footers, a caption written as a table's last row. The report lists all eleven faults it found, and which the engine can fix and which need training.

Benchmarks, against Tesseract

OmniParseBench

All 2,937 pages of OmniParseBench, graded by the benchmark's own grader (omni-parse-bench 1.2.0, its unit_tests scorer). Fullerene 3M through Carbon-OCR, which gives the grader its HTML (headings, paragraphs, lists, tables from their cells) and its layout blocks; Tesseract 5.5.0 (-l eng --psm 3, its defaults) as the baseline, its lines as paragraphs. The same pages, rendered once at 200 dpi. Scores out of 100.

OmniParseBench by family: fullerene-3M against Tesseract 5.5
fullerene-3M fullerene-3M, FP16 on the CPU fullerene-3M, FP16 on the GPU Tesseract 5.5
Headline (the three families' mean) 44.4 44.5 44.3 5.9
Text (8,499 tests) 27.3 27.3 27.1 17.8
Tables (5,386 tests) 23.6 23.8 23.4 0.0
Layout (2,403 tests) 82.4 82.4 82.3 0.0
Pages read (failed); coverage 2,937 (0); 1.0000 2,937 (0); 1.0000 2,937 (0); 1.0000 2,937 (0); 1.0000

Tesseract writes text alone, so its tables and layout score 0, as a line engine's do; read as a line engine too (its lines as paragraphs), fullerene-3M scores 27.5 on text. In FP16 on the CPU it passes 34.2 of all tests to FP32's 34.2: the FP16 files read as the FP32 ones do. On the GPU (TensorRT, the FP16 files and the fused CTC head) the pages read as on the CPU, within 0.2 of each score.

Each kind of OmniParseBench test passed: fullerene-3M against Tesseract 5.5 OmniParseBench text tests passed by suite: fullerene-3M against Tesseract 5.5

Where it reads better. document photos 67.1 against 17.3; rotated and skewed pages 58.0 against 17.3; real document pages 60.3 against 25.8; multilingual pages 49.3 against 20.0; ParseBench documents 70.8 against 48.6; federal forms 62.0 against 41.0; multilingual PDFs 18.5 against 2.4; tables 63.0 against 47.8; synthetic copies 31.5 against 19.9; multi-column pages 67.0 against 55.7; filled forms 68.8 against 62.3; real PDFs 54.5 against 48.7. Document by document, over the 1,791 documents with text tests, fullerene-3M scores higher on 461, the same on 1,194 and lower on 136.

Where it reads worse. large-format sheets 47.8 against 56.5; old scans 1.3 against 6.3.

Why text tests fail. Of the 8,499 text tests, 3,205 want LaTeX math and 584 a script with no recognizer in this set. Of the 4,710 left, the largest causes are reading order (790 tests: order tests, and text whose words are all there out of sequence), text that is not there at all (727, most on handwritten and degraded pages), and near misses (582, most often a space read inside a word).

Every OmniParseBench test passed by suite, text, tables and layout: fullerene-3M against Tesseract 5.5
Every suite, test type and script
Suite Text tests fullerene-3M Tesseract 5.5
arXiv math 2,830 1.7 0.8
synthetic copies 1,500 31.5 19.9
multilingual PDFs 465 18.5 2.4
old scans with math 438 3.2 4.8
real document pages 383 60.3 25.8
tiny plans 351 85.2 83.2
old scans 319 1.3 6.3
rotated and skewed pages 312 58.0 17.3
handwriting 280 0.7 1.1
document photos 237 67.1 17.3
multi-column pages 230 67.0 55.7
real PDFs 224 54.5 48.7
ParseBench documents 212 70.8 48.6
tables 184 63.0 47.8
long tiny text 167 46.7 43.1
federal forms 100 62.0 41.0
filled forms 77 68.8 62.3
multilingual pages 75 49.3 20.0
large-format sheets 46 47.8 56.5
French handwriting 41 7.3 2.4
forms 28 82.1 78.6
Test type Tests fullerene-3M Tesseract 5.5
present 7,275 25.0 16.5
table_cell 5,386 23.6 0.0
layout_kind 2,403 82.4 0.0
order 1,189 40.6 25.3
repeat 35 42.9 40.0
Script tag Text tests fullerene-3M Tesseract 5.5
Latn 4,160 45.9 29.7
(none) 3,669 10.4 7.7
Hani 135 0.0 0.0
Cyrl 74 25.7 0.0
Grek 62 35.5 3.2
Armn 60 0.0 0.0
Laoo 52 0.0 0.0
Knda 48 0.0 0.0
Ethi 43 0.0 0.0
Beng 40 0.0 0.0
Mlym 40 0.0 0.0
Thai 39 0.0 0.0
Khmr 34 0.0 0.0
Telu 33 0.0 0.0
Guru 31 0.0 0.0
Hebr 30 0.0 0.0
Taml 25 0.0 0.0
Hang 24 0.0 0.0
Deva 20 0.0 0.0

olmOCR-Bench

All 1,403 PDFs of olmOCR-Bench (7,010 pass-fail tests), rendered at 200 dpi and read as images by both engines (no text layer), graded by its own scorer (olmocr.bench.benchmark); fullerene-3M through Carbon-OCR's markdown, Tesseract 5.5 (-l eng --psm 3) by its own text. The headline is the mean of its test files' scores, with a 95% interval.

Test file Tests fullerene-3M Tesseract 5.5
Headline 7,010 45.1 ยฑ 1.0 34.2 ยฑ 1.0
Tables 1,022 40.8 0.5
Headers and footers left out 760 75.0 40.1
Long tiny text 442 61.1 60.6
Multi-column pages 884 68.8 52.3
Old scans 526 15.4 20.7
arXiv math 2,927 0.0 0.0
Old scans, math 458 0.0 0.0
Baseline (output neither empty nor junk) 1,394 99.9 99.0

fullerene-3M leads on tables, on multi-column pages, on leaving out running headers and footers, and narrowly on long pages of tiny text; Tesseract reads more of the old scans. Neither writes LaTeX, so both score 0 on mathematics, a quarter of the headline.

OmniDocBench, its English pages

The 755 English pages of OmniDocBench v1.6 (the rest are Chinese, which neither engine reads), end to end, graded by its own grader. Its formula metric CDM needs TeX Live on Linux and is not computed, so neither is its Overall; the parts are below.

Metric fullerene-3M Tesseract 5.5
Text: edit distance (lower is better) 0.165 0.129
Tables: TEDS 29.1 0.0
Tables: TEDS, structure only 51.4 0.0
Reading order: edit distance (lower is better) 0.269 0.253
Display formulas: edit distance 0.901 0.877

Tesseract reads the text of these pages better and puts it in a slightly better order; fullerene-3M reads their tables, and the text of their slides (0.081 against 0.086). Its text is furthest behind on newspapers (0.298 against 0.097); closer on magazines (0.133 against 0.107), exam papers (0.130 against 0.109) and two-column pages (0.078 against 0.069).

Where it still loses. On newspapers, and on old print, which it finds but misreads (e for o, c for e, a for u). Speed on olmOCR-Bench's pages, six processes on the laptop's CPU: 12.6 pages a second against Tesseract's 3.0.

Speed and throughput

On a laptop: Intel Core i7-13620H (6 performance and 4 efficiency cores) and an NVIDIA RTX 4060 Laptop GPU (8 GB), Windows 11, on mains power in its Turbo mode. Model loading and one warm-up page per worker are left out.

One page at a time, one core (the speed set: 300 of OmniParseBench's pages, every suite in turn):

fullerene-3M fullerene-3M, FP16 on the CPU Tesseract 5.5
Pages a second 4.06 3.31 0.756
Median page, p90 208 ms, 399 ms 256 ms, 496 ms 976 ms, 2419 ms

Throughput (the speed set's first 60 pages, worker processes of one thread, the median of three runs):

Processes fullerene-3M, pages/s Tesseract 5.5, pages/s ratio
1 4.07 0.79 5.1ร—
2 7.32 1.41 5.2ร—
4 11.49 2.34 4.9ร—
6 13.54 2.97 4.6ร—
Pages a second by worker count: fullerene-3M against Tesseract 5.5

Carbon-OCR's own workers in one process, pinned one to a core: one page at a time spread over them, or a stream of pages in flight, each started as soon as a worker is free (Engine.submit and next). On all 2,937 pages, one process of 10 workers with 20 in flight reads 14.99 pages a second, against 13.59 in six processes of one worker:

Process ร— workers pages/s median page, ms
1 ร— 6, pinned, one page at a time 10.37 79
1 ร— 10, pinned, one page at a time 10.33 80
1 ร— 6, pinned, 12 pages in flight 13.88 326
1 ร— 10, pinned, 20 pages in flight 15.38 349

On the GPU (the laptop's RTX 4060; TensorRT 11.4, CUDA 13.4): Carbon-OCR's batched pipeline, each model run on batches drawn from all the pages in flight, behind carbon-ocr serve --device cuda. All 2,937 pages sent by one client with 32 in flight, each page's file read, sent over HTTP and decoded on the way:

All 2,937 pages pages/s wall
fullerene-3M on the GPU (FP16 files, TensorRT) 101.5 28.9 s
fullerene-3M on the CPU, 1 process ร— 10 workers, 20 in flight 14.99 196.0 s
fullerene-3M on the CPU, 6 processes of one worker 13.59 216.1 s
Tesseract 5.5, 6 processes of one worker 3.16 930.0 s

Detection ran batches of up to 2 pages; the GPU stayed at 51 ยฐC and 42 W at most. A data-center GPU, with larger batches, is to come.

Where a page's time goes:

A page's time by stage

A speed-set page holds 136 lines, 198 px wide on average, 13.3 GMAC; recognition is most of its time and runs at the rate its compute predicts. In FP16 on this CPU a page takes 287 ms against FP32's 233: the CPU has no FP16 arithmetic, so the FP16 weights are widened and summed in FP32 on Carbon-OCR's own kernels, where the FP32 files run on ONNX Runtime. On CPUs with FP16 arithmetic (AVX-512 FP16, Armv8.2 FP16) the FP16 files compute in FP16; on NVIDIA GPUs TensorRT runs them.

Per-model scores

Each model on held-out pages and lines, at its export.

Each model alone on held-out pages and lines
Model Score
orient upright pages kept upright 1.0000; rotated pages turned right 0.9721; wrong turns 0; bin accuracy 0.9975 at a turn threshold of 0.65, 300 pages and 3,584 thumbnails (orient.eval.json)
det line F1 at IoU 0.5: 0.9936 (the exported checkpoint), 0.9926 at the end of training 8,000 held-out print pages, 600,718 lines
rec-latin character error rate on held-out print: 0.98% 800 classes, covering 99.991% of the characters sampled from the text corpora
order Kendall's tau 1.0 (the exported checkpoint), 0.9992 at the end of training; block F1 0.9916 and 0.9909

FP16 against FP32 (ONNX Runtime): det flips its core map on 494 of 274,432 pixels; rec-latin changes its best class on 2 of 2,796 frames; orient and order change no decision. Each *.meta.json holds its model's shapes, crop and decode rules, parameter count and parity.

Files

Each network as FP32 ONNX (opset 17: the CPU, ONNX Runtime) and FP16 ONNX (TensorRT, and the CPU with --precision fp16), with its record. The recognizer also ships its vocabulary and, for the GPU's fused CTC head, its trunk and head weights. config.json describes the set: its models, their files, inputs, outputs and parameter counts. Each network's FP32 weights are also in <model>.safetensors, as its ONNX file stores them (convolutions folded with their norms), for reading them without ONNX; model.safetensors.index.json maps every tensor to its file. The engine runs the ONNX files.

hf download CarbonResearchLabs/fullerene-3M --local-dir models/fullerene-3M
File SHA-256
orient.onnx 7998c668757d853897b4185876b93b9c635f29dfef28869d1f3d6b1392d76ee6
orient.fp16.onnx 1084fe345db946141ad7cb8f0954a97565be34d434931253f664e74ab1be9d01
orient.meta.json e8892c03abe2aaaee77d57dc573d3951e43e07fd0a762a8d5f935d165c367fb1
orient.eval.json 8fda34a4615ce8f04a3737b304fb79124a24797fa71de1f8358a9f4964a0e180
det.onnx 0b2d5bbae31c887d47513478e9546d6a35bdf2883c43e179f0f6807a2e25386e
det.fp16.onnx a39c5de990a14201f5332343266649ce21518c744d047e476888bec6152fe275
det.meta.json c37f3b56bdc82590e10f418e45587aec7f65fa386ed05f15394a2300e5689d88
rec-latin.onnx 9ffb3a1c2d000f5999c395a3bfaaf2e4fe5f1ee224465e4e20a12f21dbf3c6c3
rec-latin.fp16.onnx 75cba184d80d09eb10a7333a04800c00da5bb1125c1e77dd0c8be9fbb8c576ba
rec-latin.features.fp16.onnx 431946e774271f5143ad815b5188dc2863403513436d1d9f9da2e1835fa1f645
rec-latin.head.bin 67a862da116e6d19843dcd056d1203c594a4b0a5a85bcbc23add37898ca2864e
rec-latin.vocab.json a406f27ab49aad2b79c7af02cee49d44a7ad8f0aed6f1fe05adf48e2991ce986
rec.meta.json e69b93a36657a285e768b1603d270f023a41b2992347476e9f82047c6c7c603a
order.onnx 72f5c2f5754087d8bcdd5861e85e371dce6fd7666cd407639b2ff71c5d7ccee7
order.fp16.onnx aea6fd5b17f058aac4ecfaa60c7625fbbe022117d3a9eef6a1f28669a8351e04
order.meta.json 17528f22feb9cd4b8bff74c7b688e31b1ebf7e1ac56de9ace9b7cc5527efb0d2
config.json b4ee056f63e7d79e3d85e6609934b4d478dd9dc3ffa697ea256b3b6af3439e71
orient.safetensors b153cb3daa3770d311e187803da131355d8ca45d711028330e1a78b7284d3951
det.safetensors d1b3e36b34234d941444ae7e0b333876d42ce0a2fa61cd08a947a298d36866ef
rec-latin.safetensors 628337140c89bc0216a3d97e39e306863948c54c70900232047112b39e2c39af
order.safetensors 503c297976166fcbe53c3e89c20d41a44b1a9586724d4cab47e7bedcf0321c30
model.safetensors.index.json 0483261dde1d06253007c42436484f6a8d66c9ad4d8e65a00578c078ab0b8f6e

Training data

Each model was trained from scratch. The data is recorded source by source in the manifest at CarbonResearchLabs/fullerene-data, which holds manifests, profiles and the scripts that fetched them, not third-party data: each source keeps its own license and host.

  • orient and det: synthetic and born-digital pages (exact line boxes from their text layers), with DocLayNet, HierText and TextOCR for detection; upright pages turned to every bin, and real rotated scans, for orientation.
  • rec-latin: rendered lines (HarfBuzz and FreeType, 1,718 audited font families, 53 held out), born-digital lines from PDF text layers, real handwriting and pseudo-labelled real lines.
  • order: DocLayNet and PubLayNet, with synthetic and born-digital pages whose order is known.

Intended use and limitations

Latin-script document OCR through Carbon-OCR: scans and photos of documents and PDFs, read as text, HTML, markdown or JSON with boxes, on the CPU and on NVIDIA GPUs.

  • Weaker on old and degraded scans and handwriting (above). On newspaper pages Tesseract reads the text better (OmniDocBench, above).
  • Out of scope: scripts other than Latin, Cyrillic and Greek, and mathematics. With no script router, a mixed-script page goes to rec-latin.
  • Orientation turns a page only when orient is at least 0.65 sure of a quarter turn; below it a page is read as given.
  • FP16 differs from FP32 in the few decisions above; use FP32 where exact parity with the CPU matters.
  • No int8 files, Carbon-OCR's fastest CPU path, ship in this set.

License, links and citation

Weights: the Carbon-OCR OpenRAIL-AMS license (LICENSE-WEIGHTS.md): royalty-free use, modification and redistribution, hosted services included, under the use restrictions of its Attachment A, which every derivative and redistribution must carry with the license. Code: Apache 2.0 (Carbon-OCR's LICENSE).

Citation

@software{vora2026carbonocr,
  author       = {Karan Vora},
  title        = {Carbon-OCR and Fullerene: OCR in C++ and CUDA, with the Fullerene models},
  organization = {Carbon Research Labs},
  year         = {2026},
  url          = {https://github.com/karanvora2599/Carbon-OCR}
}

@misc{vora2026fullerene3m,
  author       = {Karan Vora},
  title        = {Fullerene 3M: the Latin model set of Carbon-OCR},
  organization = {Carbon Research Labs},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/CarbonResearchLabs/fullerene-3M}}
}

Credits. Carbon-OCR and Fullerene are built by Karan Vora at Carbon Research Labs (getcarbonresearch.com), with David Delaurier, lead MLOps, and Karthik Kumar Viswanathan, technical advisor.

Downloads last month
6
Safetensors
Model size
2.77M params
Tensor type
F32
ยท
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Dataset used to train CarbonResearchLabs/fullerene-3M

Evaluation results

  • Headline (mean of text, tables and layout) on OmniParseBench
    Carbon-OCR
    44.400
  • Text tests passed (%) on OmniParseBench
    Carbon-OCR
    27.300
  • Table tests passed (%) on OmniParseBench
    Carbon-OCR
    23.600
  • Layout tests passed (%) on OmniParseBench
    Carbon-OCR
    82.400
  • Headline (mean of its test files, %) on olmOCR-Bench
    Carbon-OCR
    45.100
  • Table tests passed (%) on olmOCR-Bench
    Carbon-OCR
    40.800
  • Headers and footers tests passed (%) on olmOCR-Bench
    Carbon-OCR
    75.000
  • Text edit distance (lower is better) on OmniDocBench v1.6 (English pages)
    Carbon-OCR
    0.165