| --- |
| license: mit |
| library_name: pytorch |
| pipeline_tag: image-to-text |
| tags: |
| - captcha |
| - image-classification |
| - pytorch |
| - safetensors |
| - onnx |
| language: |
| - en |
| - ja |
| --- |
| |
| # capsolve-sp |
|
|
| Model artifacts for a compact five-character CAPTCHA recognizer. |
|
|
| Training and inference code is maintained separately on GitHub: |
|
|
| - `https://github.com/nakasyou/capsolve-sp` |
|
|
| ## Quick start |
|
|
| Install the CPU inference dependencies: |
|
|
| ```bash |
| pip install huggingface-hub onnxruntime pillow numpy |
| ``` |
|
|
| Run the calibrated INT8 model on a 175x60 CAPTCHA image: |
|
|
| ```python |
| from huggingface_hub import hf_hub_download |
| from PIL import Image |
| import numpy as np |
| import onnxruntime as ort |
| |
| REPO_ID = "nakasyou/capsolve-sp" |
| CHARSET = "0123456789abcdefghijklmnopqrstuvwxyz" |
| |
| model_path = hf_hub_download(REPO_ID, "model.onnx") |
| session = ort.InferenceSession( |
| model_path, |
| providers=["CPUExecutionProvider"], |
| ) |
| |
| with Image.open("captcha.png") as source: |
| image = source.convert("L") |
| if image.size != (175, 60): |
| raise ValueError("captcha image must be 175x60 pixels") |
| pixels = np.asarray(image, dtype=np.float32) |
| |
| # The model expects white background as 0 and dark ink as 1. |
| input_tensor = ((255.0 - pixels) / 255.0)[None, None, :, :] |
| logits = session.run(["logits"], {"image": input_tensor})[0] |
| text = "".join(CHARSET[index] for index in logits[0].argmax(axis=-1)) |
| print(text) |
| ``` |
|
|
| To use the FP32 model instead, change `model.onnx` to `model-fp32.onnx`. |
|
|
| ## Files |
|
|
| - `model.onnx`: calibrated INT8 ONNX, recommended for fast CPU inference |
| - `model-fp32.onnx`: FP32 ONNX |
| - `model.safetensors`: PyTorch architecture weights |
| - `config.json`: architecture and preprocessing configuration |
| - `metadata.json`: training and evaluation metadata |
|
|
| ## Model |
|
|
| - Architecture: residual CNN with adaptive pooling into five character cells |
| - Parameters: 486,861 |
| - Input: grayscale 175x60 image |
| - Preprocessing: invert intensity so white is `0` and ink is `1` |
| - Character set: `0123456789abcdefghijklmnopqrstuvwxyz` |
| - Output: exactly five characters |
|
|
| The model was fine-tuned on 13,231 frames from 11,754 CAPTCHA groups. Validation used 3,355 frames from 2,938 disjoint groups. |
|
|
| | Validation metric | Result | |
| |---|---:| |
| | Character accuracy | 96.94% | |
| | Exact five-character accuracy | 87.00% | |
|
|
| Across all 14,332 valid labeled `0.png` images: |
|
|
| | Runtime model | Exact accuracy | |
| |---|---:| |
| | FP32 ONNX | 85.047% (12,189 / 14,332) | |
| | INT8 ONNX | 85.033% (12,187 / 14,332) | |
|
|
| FP32 and INT8 predictions agreed on 99.874% of images. On an AMD Ryzen AI 7 PRO 350, INT8 reached a median of approximately 1,573 images/second at batch size 8 and eight threads. |
|
|
| ## Limitations |
|
|
| - Supports only five-character images using the configured character set. |
| - Performance can be lower on CAPTCHA generators not represented in training. |
| - OCR-derived labels may contain residual annotation errors. |
| - Use only where automated image recognition is authorized. |
|
|
| ## License |
|
|
| The model artifacts are licensed under the MIT License. See `LICENSE`. |
|
|