Scarnox · Blog

OCR captcha tekstowych i graficznych: jak odczytać zniekształcone captcha

Obraz captcha pokazuje krótki ciąg liter lub cyfr jako obrazek, czasem z szumem, obrotem i falistymi liniami. Optyczne rozpoznawanie znaków (OCR) potrafi odczytać proste wersje takich captcha przy użyciu silnika open source, np. Tesseract. Dokładność zależy od tego, jak czysty jest obraz, więc większość pracy to preprocessing. Ten przewodnik pokazuje działającą konfigurację w Pythonie, wyjaśnia, gdzie zawodzi, i podkreśla jedną rzecz: API Scarnox działające na żywo rozwiązuje tokeny widgetów PopularCaptcha, a nie captcha obrazkowe typu obraz-na-tekst. OCR trzeba zbudować jako własny kod, a nie jako wywołanie API.

Kiedy OCR działa, a kiedy nie

OCR to rozsądna pierwsza próba, gdy tekst jest:

Słabo radzi sobie z obróconymi literami, ze znakami, które się stykają, z teksturami tła i z liniami przeciągniętymi przez glify. Każdy z tych problemów wymaga konkretnego kroku preprocessingu, a niektóre wymagają zupełnie innego modelu. Bądź gotów zmierzyć dokładność zamiast ją zakładać.

Instalacja narzędzi

Potrzebujesz Pythona, pliku wykonywalnego Tesseract i dwóch pakietów Pythona:

pip install pillow pytesseract

Tesseract to osobna instalacja. Na Windows użyj instalatora z projektu Tesseract i upewnij się, że plik wykonywalny jest w PATH, albo wskaż go przez pytesseract.pytesseract.tesseract_cmd.

Preprocessing, a potem odczyt

Większość dokładności bierze się z czystego wejścia. Poniższa sekwencja konwertuje obraz do skali szarości, zwiększa kontrast, stosuje twardy próg, powiększa obraz i ogranicza wynik do znaków używanych przez captcha:

from PIL import Image, ImageOps
import pytesseract

# Znaki, których może używać captcha. Pomiń podobne do siebie, np. 0/O i 1/I,
# jeśli captcha ich nie używa.
ALLOWED = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"

def read_text(path: str) -> str:
    img = Image.open(path)
    gray = ImageOps.grayscale(img)
    gray = ImageOps.autocontrast(gray)
    # Twardy próg: piksele jaśniejsze niż 140 stają się białe, reszta czarna.
    bw = gray.point(lambda p: 255 if p > 140 else 0)
    # Tesseract lepiej radzi sobie z większymi glifami.
    bw = bw.resize((bw.width * 3, bw.height * 3))
    config = f"--psm 7 -c tessedit_char_whitelist={ALLOWED}"  # psm 7: jedna linia tekstu
    return pytesseract.image_to_string(bw, config=config).strip()

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

Wartość progu 140 to punkt wyjścia. Wypisz przetworzony obraz, porównaj go z oryginałem i dostrajaj, aż litery będą pełne, a tło czyste.

Zmierz dokładność przed użyciem

Jeden poprawny odczyt jednego obrazu nic nie dowodzi. Zapisz zestaw captcha o znanych odpowiedziach, uruchom funkcję na wszystkich i policz trafienia:

def accuracy(samples: dict[str, str]) -> float:
    # samples mapuje ścieżkę pliku na prawdziwy 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%}")

Śledź ten wynik za każdym razem, gdy zmieniasz preprocessing. Jeśli po kilku zmianach wskaźnik jest niski, OCR prawdopodobnie nie jest właściwym narzędziem dla tego stylu captcha i warto poszukać innego podejścia.

Gdzie to się psuje

Lista kontrolna preprocessingu

Gdy odczyt się nie udaje, przejdź przez te punkty po kolei. Zmieniaj jedną rzecz naraz, żeby widzieć, który krok pomógł:

  1. Sprawdź rozmiar wejścia. Bardzo małe captcha często lepiej się czytają po powiększeniu 3x.
  2. Konwertuj do skali szarości i rozciągnij kontrast, żeby litery wyróżniały się.
  3. Zastosuj próg i wypróbuj kilka wartości, zanim wybierzesz jedną.
  4. Usuń szum punktowy filtrem medianowym, a potem ewentualnie ponów progowanie.
  5. Przytnij obraz do obszaru tekstu, żeby tło nie zmylało silnika.
  6. Ogranicz zestaw znaków do tego, którego używa captcha.
  7. Wypróbuj inny tryb segmentacji strony, jeśli tekst jest rozrzucony lub ułożony w stos.

Trzymaj kolejność i ustawienia w systemie kontroli wersji obok oznaczonych próbek. Pipeline preprocessingu to kod i powinien przechodzić przegląd jak kod.

OCR czy model, który uruchamiasz sam

Klasyczny OCR jest szybki i działa na laptopie, ale jest kruchy, gdy captcha zmienia styl. Modele obrazu wytrenowane na twoim własnym oznaczonym zbiorze radzą sobie z większą zmiennością, kosztem zbierania danych i uruchamiania inferencji. Oba podejścia budujesz i utrzymujesz sam. Żadne nie jest dziś hostowanym endpointem Scarnox, więc zaplanuj infrastrukturę, zanim się zdecydujesz.

Co Scarnox robi, a czego nie robi

API Scarnox działające na żywo rozwiązuje tokeny widgetów PopularCaptcha. Żądanie to POST https://api.scarnox.com/api/tasks/create z typem zadania PopularCaptcha, sitekey i adresem strony, a odpowiedzią jest token do pola formularza. To inne zadanie niż odczytywanie tekstu z obrazu, a Scarnox dziś nie oferuje endpointu obraz-na-tekst. Jeśli twój problem to captcha obrazkowe, użyj OCR albo modelu, który uruchamiasz sam, a inne przewodniki pokażą, co Scarnox obejmuje. Możesz założyć konto i zacząć z darmowym kredytem próbnym, bez karty, dla przepływów PopularCaptcha, które obsługuje. Aktualny cennik znajdziesz na stronie cennika.

Zastosowania zgodne z prawem

Nie używaj OCR, żeby ominąć captcha na stronie, która nie zezwala na zautomatyzowany dostęp. Captcha obrazkowe istnieją właśnie po to, żeby spowalniać takie działania.

Dalsze kroki