Views
No views yet
pdf-strikethrough-detect
uses to resolve pixel-ambiguous strikethrough cases on scanned document pages. A thin strike
over an ascender-less word is pixel-identical to an ordinary glyph chain; geometry alone cannot
separate them, so a learned model casts the deciding vote. On born-digital PDFs the package reads
vector strokes and annotations directly and never invokes this model.32×160 (ink-positive,
height-normalized). Produced by pdf_strikethrough.cnn.std_crop; the exact geometry is recorded
in strike_verdict_cnn.meta.json and enforced at load time (cnn._check_geometry) so training
and inference preprocessing cannot drift.p_hi = 0.85, p_lo = 0.15. A word scoring ≥ p_hi is
struck, ≤ p_lo is clean, and the [p_lo, p_hi) band is "unsure" and deferred to geometry. The
training script sets these from data: p_hi as a split-conformal threshold on held-out
struck-word probabilities (distribution-free recall floor of 1 − alpha), p_lo mirrored on the
clean class. Override per-call with ScanConfig.recall_first(cnn_p_hi=…) /
precision_first(cnn_p_lo=…).lines.py) → StrikeNet adjudicates the
auto/review tier crops → struck words, char-level partial resolution, struck-aware markdown.
Full architecture: the project README.sha256-pinned). Reproduce with benchmarks/scanned_recovery.py.| Metric | Value | Source |
|---|---|---|
| Scanned-path strike recovery (RapidOCR) | 97% | scanned_recovery.py, 3 docs / 24 pages / 2,170 known strikes |
| Scanned-path strike recovery (Azure DI) | 95% | same harness, Azure Document Intelligence words |
| Native vector detections independently confirmed by the flag signal | 99.8% | confirmation_rate.py (context; native path, not this model) |
1import pdf_strikethrough as st
2
3st.ensure_model(
4 "https://huggingface.co/niles-liu/strikenet/resolve/main/strike_verdict_cnn.onnx",
5 "fac2c51baaa75ee782196bdfe7452638cb48c7deddb21163b1ac6a0a72ae4457",
6 meta_url="https://huggingface.co/niles-liu/strikenet/resolve/main/strike_verdict_cnn.meta.json",
7)
8assert "p_hi" in st.get_model_meta() # thresholds + crop geometry now loaded
9result = st.detect_pdf("scanned-redline.pdf", ocr=st.rapidocr_backend())1pdf-strikethrough detect scan.pdf --ocr rapidocr --dump-crops crops_out/ # export scored crops
2# label crops_out/crops.jsonl: set each row's "label" to "struck" or "clean"
3python training/train_strikenet.py crops_out/ -o model_out/ --epochs 40 # train + calibrate + ONNXtraining/README.md.