Downloads · 30 days
15
11% of all-time downloads
Hansda/minicpm-v4_6-captcha-lora
minicpm-v4_6-captcha-lora is a image-text-to-text model from Hansda. Use it for the image-text-to-text task on the model card, and read the license before you ship it in a product. It is set up for peft. The card lists the license as apache-2.0.
QLoRA adapter fine-tuning openbmb/MiniCPM-V-4.6 to read distorted alphanumeric text from synthetic CAPTCHA images and output the exact character sequence.
Downloads · 30 days
15
11% of all-time downloads
All-time downloads
142
Public
Repo size
96 MB
Likes
1
Public
Click a slice to open those files.
.safetensors38 MB · 66%
From the Hugging Face model README
QLoRA adapter fine-tuning openbmb/MiniCPM-V-4.6 to read distorted alphanumeric
text from synthetic CAPTCHA images and output the exact character sequence.
This release is the noise-robust checkpoint: it was trained from scratch on data with on-the-fly noise augmentation (salt & pepper, Gaussian, speckle, blur, JPEG artifacts, and variable-scale pixelation), which improves accuracy on corrupted / low-quality inputs while matching the clean-image baseline.
Greedy decoding, 500-sample held-out validation split.
| Metric | Clean images | Noisy images |
|---|---|---|
| Exact match (case-sensitive) | 54.2% | 45.6% |
| Exact match (case-insensitive) | 84.8% | 73.6% |
For comparison, the previous (non-augmented) adapter scored 41.8% / 69.6% on the same noisy set — this checkpoint is +3.8 pts case-sensitive and +4.0 pts case-insensitive more robust to noise.
Note on the case-sensitive vs case-insensitive gap. The ~30-point gap is almost entirely case ambiguity: for glyphs like
c/C,o/O,s/S,u/U,v/V,w/W,x/X,z/Zthe upper- and lower-case forms are visually identical apart from size, so case is inherently hard to recover from a single distorted glyph. Reading the characters themselves is ~85% reliable.
[a-zA-Z0-9] minus ambiguous I O 0 1 l),
10k train / 2k test; multi-font, warping, lines, background noise.
See the companion dataset: Hansda/captcha-dataset.Single-turn, one image + instruction:
What is the text shown in this CAPTCHA image? Reply with only the exact characters, nothing else.
import torch
from transformers import AutoProcessor, BitsAndBytesConfig
from transformers.models.minicpmv4_6.modeling_minicpmv4_6 import MiniCPMV4_6ForConditionalGeneration
from peft import PeftModel
from PIL import Image
model_id = "openbmb/MiniCPM-V-4.6"
adapter = "Hansda/minicpm-v4_6-captcha-lora"
bnb = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16, bnb_4bit_use_double_quant=True)
base = MiniCPMV4_6ForConditionalGeneration.from_pretrained(
model_id, quantization_config=bnb, dtype=torch.bfloat16,
device_map="auto", attn_implementation="eager")
model = PeftModel.from_pretrained(base, adapter).eval()
proc = AutoProcessor.from_pretrained(model_id, trust_remote_code=True)
img = Image.open("captcha.png").convert("RGB")
instr = "What is the text shown in this CAPTCHA image? Reply with only the exact characters, nothing else."
text = proc.apply_chat_template(
[{"role": "user", "content": [{"type": "image"}, {"type": "text", "text": instr}]}],
tokenize=False, add_generation_prompt=True)
inp = proc(images=[img], text=[text], return_tensors="pt").to(model.device)
if "pixel_values" in inp: inp["pixel_values"] = inp["pixel_values"].to(torch.bfloat16)
out = model.generate(**inp, max_new_tokens=32, do_sample=False,
pad_token_id=proc.tokenizer.pad_token_id)
print(proc.tokenizer.decode(out[0][inp["input_ids"].shape[1]:], skip_special_tokens=True).strip())