Instructions to use Wall3/Yara_Captcha_Solver with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use Wall3/Yara_Captcha_Solver with Keras:
# Available backend options are: "jax", "torch", "tensorflow". import os os.environ["KERAS_BACKEND"] = "jax" import keras model = keras.saving.load_model("hf://Wall3/Yara_Captcha_Solver") - Notebooks
- Google Colab
- Kaggle
| license: mit | |
| language: | |
| - en | |
| tags: | |
| - captcha | |
| - ocr | |
| - crnn | |
| - ctc | |
| - image-to-text | |
| - tensorflow | |
| - keras | |
| task_categories: | |
| - image-to-text | |
| datasets: | |
| - ayoubkirouane/captcha | |
| - ThangaTharun/captchaimages | |
| - yuxi5/text-captcha-data-clean | |
| - AvinashRicky/CaptchaOCR-500K | |
| - cybertruck32489/captcha_90k | |
| - yusuf802/captcha_dataset | |
| - lumasik/captcha-25k | |
| # π CRNN-CTC Captcha Solver | |
| ### Convolutional Recurrent Neural Network Β· Real-Data Fine-Tuned | |
| [](https://opensource.org/licenses/MIT) | |
| [](https://www.python.org/) | |
| [](https://www.tensorflow.org/) | |
| Alphanumeric CAPTCHA recognition using a deep **CRNN + CTC** architecture trained on | |
| **275,000 real-world labeled CAPTCHAs** from 7 HuggingFace datasets, then refined over a | |
| full weekend of augmented training on an NVIDIA A100. Achieves **90.08% whole-CAPTCHA | |
| sequence accuracy** on the held-out real test set. | |
|  | |
| --- | |
| ## π Model Details | |
| | Property | Value | | |
| |---|---| | |
| | **Task** | Alphanumeric CAPTCHA Recognition (OCR) | | |
| | **Architecture** | CRNN β 6-block CNN + 2Γ Bidirectional LSTM + Dense | | |
| | **Input** | RGB image `(64 Γ 200 Γ 3)`, float32 `[0, 1]` | | |
| | **Output** | Character sequence, length 1β8 | | |
| | **Vocabulary** | `0-9`, `a-z`, `A-Z` β 62 characters + CTC blank | | |
| | **Loss** | Connectionist Temporal Classification (CTC) | | |
| | **Parameters** | 10,049,535 (~38.3 MB) | | |
| | **Framework** | TensorFlow 2.21 / Keras 3 | | |
| | **Training hardware** | NVIDIA A100 80 GB | | |
| --- | |
| ## π Performance | |
| ### Overall (held-out real test set, n = 5,502) | |
| | Metric | Score | | |
| |---|---| | |
| | **Sequence accuracy** (whole CAPTCHA correct) | **90.08 %** | | |
| | **Character accuracy** | **96.14 %** | | |
| | CTC loss | 1.10 | | |
| ### Per-dataset breakdown | |
| | Dataset | n (test) | Char acc | Seq acc | | |
| |---|---|---|---| | |
| | cybertruck32489/captcha_90k | 1,224 | 99.9 % | **99.7 %** | | |
| | ayoubkirouane/captcha | 192 | 99.9 % | **99.5 %** | | |
| | yuxi5/text-captcha-data-clean | 1,171 | 93.6 % | 90.9 % | | |
| | AvinashRicky/CaptchaOCR-500K | 1,215 | 97.8 % | 88.7 % | | |
| | lumasik/captcha-25k | 502 | 96.0 % | 86.5 % | | |
| | yusuf802/captcha_dataset | 1,196 | 92.5 % | 80.8 % | | |
| | ThangaTharun/captchaimages | 2 | 100.0 % | 100.0 % | | |
| **Total params: 10,049,535 β Model size: 38.3 MB** | |
| --- | |
| ## π¦ Training Datasets | |
| | Dataset | Label field | Images used | Notes | | |
| |---|---|---|---| | |
| | [ayoubkirouane/captcha](https://huggingface.co/datasets/ayoubkirouane/captcha) | `solution` | 10,000 | clean, parquet | | |
| | [ThangaTharun/captchaimages](https://huggingface.co/datasets/ThangaTharun/captchaimages) | `output` | 100 | small, noisy | | |
| | [yuxi5/text-captcha-data-clean](https://huggingface.co/datasets/yuxi5/text-captcha-data-clean) | `label` | 60,000 | capped at 60k | | |
| | [AvinashRicky/CaptchaOCR-500K](https://huggingface.co/datasets/AvinashRicky/CaptchaOCR-500K) | `text` | 60,000 | capped at 60k | | |
| | [cybertruck32489/captcha_90k](https://huggingface.co/datasets/cybertruck32489/captcha_90k) | `solve` | 60,000 | capped at 60k | | |
| | [yusuf802/captcha_dataset](https://huggingface.co/datasets/yusuf802/captcha_dataset) | `label` | 60,000 | capped at 60k | | |
| | [lumasik/captcha-25k](https://huggingface.co/datasets/lumasik/captcha-25k) | `label` | 25,000 | all images used | | |
| | **Synthetic (17 generator types)** | generated | mixed in at 30% | custom Python generators | | |
| **Total real images preprocessed:** 275,100 β 264,096 train / 5,502 val / 5,502 test | |
| All images were resized to **64 Γ 200** with aspect-preserving letterboxing (pad with | |
| median border color). | |
| --- | |
| ## βοΈ Training Details | |
| ### Two-stage process | |
| **Stage 1 β Synthetic pre-training** | |
| Training from scratch on 17 procedural CAPTCHA types (custom Python generators) covering | |
| different fonts, noise levels, distortions, and color palettes. | |
| **Stage 2 β Real-data fine-tuning + augmented weekend run** | |
| - Initialized from the synthetic checkpoint. | |
| - Fine-tuned on 264k real images for 40 epochs (LR 1e-3 β 1e-5 cosine). | |
| - Extended with a full weekend run (386 epochs, ~60h on A100) combining: | |
| - **30% synthetic** mixed into each batch for robustness. | |
| - **GPU augmentation:** `RandomRotation(Β±2Β°)`, `RandomTranslation`, `RandomZoom(6%)`, `RandomContrast(25%)`, brightness jitter Β±0.08, Gaussian noise Ο=0.03. | |
| - **Weak-source oversampling:** datasets below 90% test seq were oversampled up to Γ2 proportionally. | |
| ### Hyperparameters | |
| | Parameter | Value | | |
| |---|---| | |
| | Optimizer | Adam | | |
| | Peak LR | 5 Γ 10β»β΄ | | |
| | Min LR | 1 Γ 10β»βΆ | | |
| | LR schedule | Warmup + Cosine Decay | | |
| | Batch size | 128 | | |
| | Dropout | 0.25 | | |
| | Gradient clip norm | 5.0 | | |
| | Max sequence length | 8 characters | | |
| --- | |
| ## π Usage | |
| ### Install dependencies | |
| ```bash | |
| pip install tensorflow pillow numpy | |
| ``` | |
| ### Predict from an image | |
| ```python | |
| import numpy as np | |
| from PIL import Image | |
| import tensorflow as tf | |
| # ββ helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
| IDX_TO_CHAR = {i: c for i, c in enumerate(CHARS)} | |
| BLANK_IDX = 62 | |
| IMG_H, IMG_W = 64, 200 | |
| def preprocess(pil_img: Image.Image) -> np.ndarray: | |
| """Aspect-preserving resize to 64Γ200, pad with median border color.""" | |
| img = pil_img.convert("RGB") | |
| w, h = img.size | |
| new_w = int(round(w * IMG_H / h)) | |
| img = img.resize((new_w, IMG_H), Image.LANCZOS) | |
| if new_w >= IMG_W: | |
| img = img.resize((IMG_W, IMG_H), Image.LANCZOS) | |
| return np.array(img, dtype=np.float32) / 255.0 | |
| canvas = np.array(img, dtype=np.float32) | |
| border_color = np.median( | |
| np.concatenate([canvas[0], canvas[-1], | |
| canvas[:, 0], canvas[:, -1]], axis=0), axis=0 | |
| ) | |
| pad_l = (IMG_W - new_w) // 2 | |
| result = np.full((IMG_H, IMG_W, 3), border_color, dtype=np.float32) | |
| result[:, pad_l:pad_l + new_w] = canvas | |
| return result / 255.0 | |
| def decode_ctc(logits: np.ndarray) -> str: | |
| """Greedy CTC decode β collapse repeats, remove blanks.""" | |
| indices = np.argmax(logits, axis=-1) # (T,) | |
| chars, prev = [], -1 | |
| for idx in indices: | |
| if idx != prev and idx != BLANK_IDX: | |
| chars.append(IDX_TO_CHAR.get(int(idx), "")) | |
| prev = idx | |
| return "".join(chars) | |
| # ββ load model βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Clone the repo or download the weights file, then: | |
| from model import build_crnn_model # from this repository | |
| model = build_crnn_model() | |
| model.load_weights("weekend_best.weights.h5") | |
| # ββ run inference βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| img = Image.open("captcha.png") | |
| tensor = preprocess(img)[np.newaxis] # (1, 64, 200, 3) | |
| logits = model(tensor, training=False).numpy() # (1, 50, 63) | |
| print("Prediction:", decode_ctc(logits[0])) | |
| ``` | |
| ### Batch inference | |
| ```python | |
| images = [preprocess(Image.open(p)) for p in image_paths] | |
| batch = np.stack(images) # (N, 64, 200, 3) | |
| logits = model(batch, training=False).numpy() # (N, 50, 63) | |
| preds = [decode_ctc(l) for l in logits] | |
| ``` | |
| --- | |
| ## πΌοΈ Preprocessing | |
| Input images go through **aspect-preserving letterboxing**: | |
| 1. Resize height to 64 px, keeping aspect ratio. | |
| 2. If the resulting width β₯ 200 px, squeeze to 200 px. | |
| 3. Otherwise, pad left and right with the **median border color** of the image to reach 200 px. | |
| 4. Normalize to `float32 [0, 1]`. | |
| This ensures the character shapes are never stretched, which is critical for | |
| distinguishing similar characters (e.g. `O` / `0`, `l` / `1`). | |
| --- | |
| ## βοΈ License | |
| This model is released under the **MIT License**. You are free to use, copy, modify, | |
| and distribute it for any purpose, including commercial use, with attribution. | |
| --- | |
| ## π Citation | |
| If you use this model in your work, please cite: | |
| ``` | |
| CRNN-CTC Captcha Solver (2026) | |
| Trained on 275k real-world CAPTCHAs from 7 HuggingFace datasets. | |
| Architecture: 6-block CNN + 2Γ BiLSTM + CTC, 10M parameters, 38 MB. | |
| Sequence accuracy: 90.08% on held-out real test set. | |
| License: MIT | |
| ``` | |