Scarnox · Blog

Beeld- en tekstcaptcha met OCR: zo lees je vervormde captchas

Een beeldcaptcha toont een korte reeks letters of cijfers als afbeelding, soms met ruis, rotatie en golvende lijnen. Optische tekenherkenning (OCR) kan eenvoudige versies daarvan lezen met een open-sourcemotor zoals Tesseract. De nauwkeurigheid hangt af van hoe schoon het beeld is, dus het meeste werk zit in de voorbewerking. Deze gids laat een werkende Python-opzet zien, legt uit waar die faalt en maakt één ding duidelijk: de live API van Scarnox lost PopularCaptcha-widgettokens op, geen beeld-naar-tekstcaptchas. Plan OCR als je eigen code, niet als API-aanroep.

Wanneer OCR werkt en wanneer niet

OCR is een redelijke eerste poging als de tekst:

Het heeft moeite met gedraaide letters, letters die elkaar raken, achtergrondtexturen en lijnen die door de tekens lopen. Elk daarvan vraagt om een specifieke voorbewerkingsstap, en sommige vragen om een heel ander model. Wees erop voorbereid om de nauwkeurigheid te meten in plaats van ervan uit te gaan.

Installeer de tools

Je hebt Python nodig, het Tesseract-programma en twee Python-pakketten:

pip install pillow pytesseract

Tesseract is een aparte installatie. Gebruik op Windows het installatieprogramma van het Tesseract-project en zorg dat het uitvoerbare bestand in je PATH staat, of wijs pytesseract.pytesseract.tesseract_cmd ernaar.

Voorbewerken, dan lezen

Het grootste deel van de nauwkeurigheid komt van schone invoer. De onderstaande reeks zet het beeld om naar grijstinten, verhoogt het contrast, past een harde drempelwaarde toe, schaalt het beeld op en beperkt de uitvoer tot de tekens die de captcha gebruikt:

from PIL import Image, ImageOps
import pytesseract

# Tekens die de captcha kan gebruiken. Laat look-alikes zoals 0/O en 1/I weg als de
# captcha ze nooit gebruikt.
ALLOWED = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"

def read_text(path: str) -> str:
    img = Image.open(path)
    gray = ImageOps.grayscale(img)
    gray = ImageOps.autocontrast(gray)
    # Harde drempelwaarde: pixels die lichter zijn dan 140 worden wit, de rest zwart.
    bw = gray.point(lambda p: 255 if p > 140 else 0)
    # Tesseract werkt beter met grotere letters.
    bw = bw.resize((bw.width * 3, bw.height * 3))
    config = f"--psm 7 -c tessedit_char_whitelist={ALLOWED}"  # psm 7: een tekstregel
    return pytesseract.image_to_string(bw, config=config).strip()

if __name__ == "__main__":
    print(read_text("sample_captcha.png"))

De drempelwaarde van 140 is een startpunt. Druk het verwerkte beeld af, vergelijk het met het origineel en pas aan tot de letters vol zijn en de achtergrond schoon is.

Meet de nauwkeurigheid voordat je erop vertrouwt

Eén juiste lezing op één beeld bewijst niets. Sla een set captchas met bekende antwoorden op, draai de functie op alle beelden en tel de treffers:

def accuracy(samples: dict[str, str]) -> float:
    # samples koppelt een bestandspad aan de juiste tekst
    hits = sum(read_text(path) == truth for path, truth in samples.items())
    return hits / len(samples)

labelled = {
    "samples/0001.png": "K7PQ2",
    "samples/0002.png": "M3XN9",
}
print(f"accuracy: {accuracy(labelled):.0%}")

Houd dit getal bij telkens als je de voorbewerking wijzigt. Als de score laag blijft na meerdere wijzigingen, is OCR waarschijnlijk het verkeerde hulpmiddel voor die captchastijl, en moet je naar een andere aanpak kijken.

Waar het breekt

Een checklist voor voorbewerking

Wanneer een lezing mislukt, werk je deze punten in volgorde af. Verander één ding tegelijk, zodat je ziet welke stap hielp:

  1. Controleer de invoergrootte. Heel kleine captchas worden vaak beter gelezen na een opschaling van 3x.
  2. Zet om naar grijstinten en rek het contrast uit zodat de letters opvallen.
  3. Pas een drempelwaarde toe en probeer enkele waarden voordat je er één kiest.
  4. Verwijder korrelruis met een medianfilter en pas daarna de drempelwaarde opnieuw toe als dat nodig is.
  5. Snij het beeld bij tot het tekstgebied, zodat de achtergrond de motor niet in verwarring brengt.
  6. Beperk de tekenset tot de set die de captcha gebruikt.
  7. Probeer een andere paginasegmentatiemodus als de tekst verspreid of gestapeld staat.

Bewaar de volgorde en de instellingen in versiebeheer, naast je geëtiketteerde voorbeelden. Een voorbewerkingspijplijn is code, en moet als code worden beoordeeld.

OCR of een model dat je zelf draait

Klassieke OCR is snel en draait op een laptop, maar is broos wanneer een captcha van stijl verandert. Beeldmodellen die op je eigen geëtiketteerde set zijn getraind, kunnen meer variatie aan, maar kosten je tijd om data te verzamelen en om inferentie te draaien. Beide moet jij zelf bouwen en onderhouden. Geen van beide is vandaag een gehoste Scarnox-endpoint, dus plan de infrastructuur voordat je voor een van beide kiest.

Wat Scarnox hier wel en niet doet

De live API van Scarnox lost PopularCaptcha-widgettokens op. Het verzoek is POST https://api.scarnox.com/api/tasks/create met een PopularCaptcha-tasktype, een sitekey en een paginaurl, en het antwoord is een token voor het formulierveld. Dat is een andere taak dan het lezen van tekst in een afbeelding, en Scarnox biedt vandaag geen beeld-naar-tekst-endpoint. Heb je een beeldcaptcha, gebruik dan OCR of een model dat je zelf draait, en bekijk de andere gidsen voor wat Scarnox wel dekt. Je kunt een account aanmaken en beginnen met gratis proefkrediet, zonder creditcard, voor de PopularCaptcha-flows die het wel ondersteunt. Actuele prijzen staan op de prijspagina.

Legitiem gebruik

Gebruik OCR niet om een captcha te omzeilen op een site die geen geautomatiseerde toegang toestaat. Beeldcaptchas bestaan juist om precies dat tegen te gaan.

Volgende stappen