Downloads · 30 days
218
41% of all-time downloads
lordtrilink/manga-text-detector-v0
manga-text-detector-v0 is a object detection model from lordtrilink. Use it when you need objects located in an image. It is set up for ultralytics. The card lists the license as cc-by-nc-sa-4.0.
A YOLO11s detector that draws one box per text region on a manga page — one box per speech bubble, caption, or free-floating line of dialogue — so each region can be cropped and handed to a text-extraction model.
Downloads · 30 days
218
41% of all-time downloads
All-time downloads
538
Public
Repo size
125 MB
Likes
1
Public
Click a slice to open those files.
.onnx57.3 MB · 46%
From the Hugging Face model README
A YOLO11s detector that draws one box per text region on a manga page — one box per speech bubble, caption, or free-floating line of dialogue — so each region can be cropped and handed to a text-extraction model.
It is the winner of a five-backend bake-off run on Manga109-s, and on 20 held-out books it reaches 95.6% extraction-ready regions, against a 99.7% ceiling. It beats comic-text-detector by +7.2 points (paired book-level bootstrap, 95% CI [4.8, 9.2], winning 16 of 20 books) and the shipped Google Cloud Vision + region-merge pipeline it was built to replace by +21.7 points — at 9.43M parameters and 19MB.
| Architecture | YOLO11s, 2 classes (text-region, sfx) |
| Input | one single page (not a double-page spread), 1024×1024 |
| Params / compute | 9.43M / 56.0 GFLOPs per page |
| Weights | 19.2MB (best.pt), 38.3MB TFLite fp32, 10.3MB TFLite int8 |
| On-device | 98.4 ms on a Pixel 10a, TFLite GPU delegate |
| Training | 60 epochs, 11,634 single-page images, |
The downstream job is cropping, not localization, so this model is not ranked on
IoU-based metrics. The ranking metric is ready: the fraction of ground-truth regions
whose crop is extraction-ready — the box contains the whole region and contains nothing
from any other region. A prediction fails in one of five ways: trunc (clips the region),
merge (swallows a neighbouring region), split (region covered by several boxes),
miss, or it is ready.
This distinction is not cosmetic. Dilating every predicted box by 10px lifts ready
from 0.1% to 78.8% while F1 falls from 0.927 to 0.268. Fat boxes are strictly better for
cropping and strictly worse by IoU, so any F1/mAP comparison of text-region detectors
ranks them on the wrong axis. For reference only, the Ultralytics validation numbers at
the final epoch (both classes, page-level val split) are mAP50 0.915, mAP50-95
0.739, precision 0.917, recall 0.864 — reported for comparability, not used for any
decision in this project.
The ceiling is 99.7%, not 100%: feeding ground truth back in as a prediction still leaves ~0.3% of regions unready, because some annotated regions genuinely overlap and contaminate each other's crops. Read every number below against 99.7%, not 100%.
20 held-out books, 80 spreads, 1,341 ground-truth regions. Each backend at its own best padding setting, since dilation is free downstream and comparing raw boxes just rewards whoever draws loosest. CIs are book-level bootstrap.
| detector | best pad | ready | 95% CI | trunc | merge | split | miss | trained on Manga109-s? |
|---|---|---|---|---|---|---|---|---|
| oracle (ceiling) | 0% | 99.7% | [99.2, 100.0] | 0.0% | 0.0% | 0.0% | 0.0% | — |
| this model (v0) | c30% | 95.6% | [93.4, 97.6] | 2.2% | 0.4% | 3.0% | 1.9% | no — book-disjoint |
| comic-text-detector | c75% | 88.4% | [85.2, 91.5] | 3.2% | 2.8% | 3.1% | 2.1% | yes, ~half the corpus |
| Google Cloud Vision + region-merge | c200% | 73.9% | [69.0, 78.7] | 9.2% | 4.9% | 6.4% | 5.9% | no |
| ML Kit + region-merge | c200% | 61.9% | [56.3, 67.4] | 15.8% | 7.5% | 4.7% | 11.9% | no |
| classical CV baseline (Otsu + CC) | — | 12.7% | — | — | — | — | — | no |
Two things about that table deserve emphasis, one in each direction:
split 3.0% + miss 1.9% + trunc 2.2%, and merge only 0.4% — seven times below
CTD's 2.8%. The failure shape inverts against every other backend tested: the incumbents
are truncation-dominated and CTD is merge-dominated, while this model's problem is purely
completeness. Instance separation is effectively solved, and generous NMS (IoU 0.7) on
region-level labels turned out to be enough for it — an NMS-free architecture is not what
this needs next.
The boxes are meant to be dilated before cropping, and how you dilate matters more than any inference-time knob.
Padding is measured in units of each box's own short side (≈ one character height for
vertical Japanese text), and the policy that wins for every backend tested is
contact: dilate each side up to a cap, but stop halfway to the nearest predicted
neighbour. An isolated bubble gets the full dilation; a bubble packed against three others
gets only the gap. Uniform padding has to trade truncation against merging with a single
cap for the whole page; contact-limiting decouples them, and is worth 9-18 points over
uniform for every backend.
Best setting for this model: contact padding at a 30-40% cap (95.6% ready, vs 92.0% at its best uniform setting). Unbounded contact padding loses — with nothing to collide with, a box grows into whatever the detector missed, and a missed region cannot block it.
Use conf 0.05, not a conventional 0.25-0.5. Performance is monotonic in the wrong direction from the usual instinct: 95.6% at conf 0.05 declining to 93.0% at 0.6. Under contact padding every prediction is also a blocker that stops its neighbours from over-expanding, so a spurious box costs one wasted crop but protects the boxes around it, while a missed box costs its own region and lets its neighbour grow into the gap. Instance recall outranks boundary precision here.
The observed optimum sits at the 0.05 floor used when dumping predictions, so the true optimum may be lower still — untested. NMS IoU was swept over {0.4 … 0.9} and is flat (95.8-96.1%); leave it at 0.7 and don't spend time on it.
from ultralytics import YOLO
from PIL import Image, ImageOps
model = YOLO("best.pt")
page = Image.open("page.jpg")
page = ImageOps.exif_transpose(page) # see "Honour EXIF" below — this line matters
r = model.predict(page, imgsz=1024, conf=0.05, iou=0.7, verbose=False)[0]
boxes = [b.xyxy[0].tolist() for b in r.boxes if int(b.cls) == 0] # class 0 = text-region
Then apply contact padding at a 30-40% cap over boxes before cropping.
Three input requirements, each of which cost accuracy when violated during evaluation:
TFLite and ONNX exports are included and load through the same ultralytics API
(YOLO("best-1024-fp32.tflite", task="detect")). All four exports were scored through the
identical ready harness as the .pt checkpoint and tie at 96.1% on the dev set at
conf 0.05 — neither export nor int8 quantization costs anything at this operating point.
Benchmarked with Google's official android_aarch64_benchmark_model.apk.
| config | inference | peak memory |
|---|---|---|
| fp32, GPU delegate | 98.4 ms | ~265 MB |
| int8, CPU, 4 threads | 1.62 s | ~255 MB |
| fp32, CPU, 4 threads (XNNPACK) | 3.19 s | ~313 MB |
| fp32, CPU, 8 threads (XNNPACK) | 5.57 s | ~322 MB |
| int8, GPU delegate | does not run | — |
Ship on the GPU delegate with fp32. That single choice is a bigger lever than quantization, a resolution cut, or distillation — none of which were needed. Notes:
TfLiteGpuDelegateOptionsV2.serialization_dir explicitly.| Base | yolo11s.pt (COCO-pretrained), not a comic-text-detector fine-tune |
| Data | Manga109-s, 67 books, 11,634 train + 76 val single-page images, 93,398 + 647 labels |
| Classes | 0: text-region (from <text> annotations), 1: sfx (from COO onomatopoeia) |
| Schedule | 60 epochs, batch 16, imgsz 1024, seed 0, deterministic, stock losses/augmentation |
| Hardware | one A10G, 3 h 51 m, ~$4 |
Everything about v0 is deliberately stock — the point was to establish the pipeline and find out which failure mode dominates, not to be clever.
Three decisions that shaped the result more than any hyperparameter:
<text> boxes are already at the granularity the metric scores. The two OCR-based
incumbents both need a separate fragment→region grouping algorithm on top, and that
grouping is worth ~20 points to them — but a detector trained directly on regions beats
the whole pipeline.Label quality was audited before training rather than assumed (94,661 regions across the 67 training books): 606 boxes dropped by the SFX overlap rule, 1,056 overlapping pairs of which 977 overlap by <25% of the smaller box (adjacent vertical columns grazing — harmless), leaving 10 truly nested regions in 94,055. 15 boxes under 12px on the short side, 0 degenerate. Label noise is not what stands between this model and the ceiling.
sfx (class 1) is untuned and unscored. It exists to keep the model from confusing
onomatopoeia with dialogue. Its accuracy has never been measured; do not rely on it.Trained on Manga109-s, the redistributable 87-book subset of Manga109, used under its academic-use terms. Manga109-s images are not redistributable and none are included here — only trained weights. The model is released CC BY-NC-SA 4.0 to stay consistent with the spirit of that corpus's terms; if you need a commercial licence for a manga text detector, train on data you have rights to.
Manga109 must be cited if you use this model in published work:
@article{mtap_matsui_2017,
author={Matsui, Yusuke and Ito, Kota and Aramaki, Yuji and Fujimoto, Azuma and Ogawa,
Toru and Yamasaki, Toshihiko and Aizawa, Kiyoharu},
title={Sketch-based Manga Retrieval using Manga109 Dataset},
journal={Multimedia Tools and Applications},
volume={76}, number={20}, pages={21811--21838}, year={2017}
}
@article{multimedia_aizawa_2020,
author={Aizawa, Kiyoharu and Fujimoto, Azuma and Otsubo, Atsushi and Ogawa, Toru and
Matsui, Yusuke and Tsubota, Koki and Ikuta, Hikaru},
title={Building a Manga Dataset ``Manga109'' with Annotations for Multimedia
Applications},
journal={IEEE MultiMedia}, volume={27}, number={2}, pages={8--18}, year={2020}
}
| file | size | notes |
|---|---|---|
best.pt | 19.2MB | PyTorch checkpoint — start here |
best-1024-fp32.tflite | 38.3MB | the deployment artefact — GPU delegate, 98.4 ms |
best-1024-int8.tflite | 10.3MB | CPU fallback / bundle size only; will not run on GPU delegate |
best-1024-fp32.onnx | 38.2MB | opset 17, static 1024×1024 input |
best-1024-fp16.onnx | 19.1MB | as above, fp16 |
results.csv | — | full 60-epoch training log |