docTR DB-MobileNetV3-Large β ExecuTorch
Text detection: where the words are. The other half of the pair is CRNN-MobileNetV3-Small, which reads them.
- Source: mindee/doctr
db_mobilenet_v3_large, 4.2M parameters - License: Apache-2.0
- Input:
[1, 3, 1024, 1024], normalised with docTR's own mean (0.798, 0.785, 0.772) and std (0.264, 0.2749, 0.287) β not ImageNet's - Output:
[1, 1, 1024, 1024], one probability per pixel of belonging to a word
Differentiable Binarization returns a shrunk region per word; turning the map into boxes
is docTR's postprocessor, which unshrinks the polygons. That stays on the caller, the way
the shelf's other detectors leave NMS outside.
Verification (Mac arm64, 2026-08-23)
| build | size | latency | worst corr |
|---|---|---|---|
| XNNPACK fp32 | 16.1 MB | 46.9 ms | 1.000000 |
| Core ML fp32 | 8.6 MB | 13.1 ms | 0.999714 |
Eager fp32 for the same input is 309 ms. Delegation is 100% (224/224 ops, one subgraph).
Read end to end, both .pte files through docTR's own post-processing, on a London
street photograph (convert/check_doctr.py):
boxes: 10
read: TIUZABXPRESS | Chrisiophers | Place | STREE! | LAG | BAR!
The signs in that photograph say PIZZA EXPRESS and Christopher's Place. Approximate, and that is the point of quoting it: correlation against eager says the tensors match, and says nothing about whether the map thresholds to any boxes at all.
Not shipped, and why
- int8: worst corr 0.627. It is 4.3 MB against 16.1, which is the trade this shelf would normally take, but not at that number.
- fp16: corr 0.999879 and it passes, but the file is the same 16.1 MB β the weights are convolutions XNNPACK already runs in fp32, so there is nothing to buy.
The mistake worth repeating back
The harness gates on correlation against eager for random input. This file scored 1.000000 there and then produced a map that thresholded to zero boxes on a real photograph. The cause was not the export:
corr pte max pixels > 0.3
as built 0.024711 0.2385 0
.contiguous() 1.000000 0.5639 1816
np.transpose leaves the array in HWC order with permuted strides, and ExecuTorch reads a
tensor in memory order rather than by its strides. Random and all-zero inputs are
contiguous, so the gate never saw it. Anything built with transpose needs
np.ascontiguousarray before it reaches a .pte.
Conversion
python convert/export_doctr.py detect
python convert/check_doctr.py <image>
docTR's forward runs its post-processing in numpy whether or not it was asked to, which
torch.export refuses (.numpy() is not supported for tensor subclasses). The model
carries an exportable flag that skips it and returns raw logits; the wrapper sets that and
applies the sigmoid itself.
(conversion scripts: executorch-models)
- Downloads last month
- 8