Customizable restricted CTC beam-search decoding and OpenCV preprocessing variants for fixed-format captcha OCR.
Pipeline: multi-variant OpenCV preprocessing → OCR probability matrix → restricted CTC beam search → agreement voting across variants. It took a real crawler from 62% → 85% exact accuracy; this packages that core so you can apply it to your captcha by configuring charset and length.
from captchabeam import CaptchaBeam
cb = CaptchaBeam() # 18 variants + beam + agreement (best config)
print(cb.decode("captcha.png").text) # -> "XTRR3"See ARCHITECTURE.md for design and docs/benchmarks.md for the full methodology, GPU numbers, optimization journey, and datasets.
pip install captchabeam[all] # core + opencv + ddddocr (default backend)Extras: [cv] preprocessing · [ddddocr] default backend · [fast] fast
backend · [gpu] onnxruntime-gpu · [eval]/[all]. The core beam decoder only
needs numpy.
Pick a backend and pass it to CaptchaBeam(backend=...). All produce identical
results; they differ in speed. Latency is per image, 18-variants-beam, 300-image
holdout, Intel i7-12700 (see docs/benchmarks.md).
from captchabeam import CaptchaBeam
cb = CaptchaBeam() # default backend, 184 ms/img, 85.0% exactSame static model and char-for-char identical output, but takes arrays directly and uses a numpy-native decode. ~34% faster, no accuracy cost.
from captchabeam import CaptchaBeam
from captchabeam.backends import FastDdddOcrBackend
cb = CaptchaBeam(backend=FastDdddOcrBackend()) # 121 ms/img, 85.0% exactcb = CaptchaBeam(backend=DdddOcrBackend(use_gpu=True)) # needs onnxruntime-gpu + CUDA/cuDNNGPU is slower for this workload (tiny model, no batching): 347 ms/img. Run on CPU. Details in docs/benchmarks.md.
Any callable png_bytes -> {text, confidence, probabilities, charset} is a valid
backend (captchabeam.backends.OcrBackend) — a custom CRNN or PaddleOCR drops in
and the beam decoder still applies.
cb = CaptchaBeam(backend=MyCRNN())| Backend | ms/img | Exact |
|---|---|---|
FastDdddOcrBackend (CPU) |
121 | 85.0% |
DdddOcrBackend (CPU, default) |
184 | 85.0% |
DdddOcrBackend(use_gpu=True) |
347 | 85.0% |
CaptchaBeam(variants=1, decoder="native") # fastest, single Otsu (~72% exact)
CaptchaBeam(variants=6, decoder="native") # balanced (~76%)
CaptchaBeam(variants=18, decoder="beam") # most accurate, default (85%)from captchabeam import CaptchaBeam, DecodeConfig
cb = CaptchaBeam(decode_config=DecodeConfig(charset="0123456789", length=4, beam_size=16))from captchabeam.preprocess import VariantPipeline, resize, otsu, pad, CUBIC
cb = CaptchaBeam(variants=[
VariantPipeline("a", resize(3, CUBIC), otsu()),
VariantPipeline("b", resize(2, CUBIC), otsu(), pad(2)),
])captchabeam decode captcha.png --variants 18 --decoder beam
captchabeam eval --data data/captcha_holdout_100 --length 5
captchabeam ablation --data data/captcha_holdout_100 # leave-one-outpython -m venv .venv && source .venv/bin/activate
pip install -e .[dev]
pytest # ddddocr/opencv tests auto-skip if absent
python scripts/benchmark.py [--fast] [--gpu]See LICENSE.