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:
- w jednej linii, z równymi odstępami;
- o wysokim kontraście, z ciemnymi literami na jasnym tle;
- wolny od mocnych zniekształceń, nakładających się znaków i przecinających linii.
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
- Szum i linie. Usuwaj linie operacjami morfologicznymi albo zaakceptuj niższy wskaźnik.
- Obrót. Oszacuj kąt i obróć obraz przed odczytem.
- Stykające się litery. Dzielenie znaków po kolumnach i odczyt każdego osobno często działa lepiej niż odczyt całej linii.
- Zmiany w czasie. Strona może zmienić styl bez ostrzeżenia, a dokładność spadnie z dnia na dzień. Zachowuj oznaczony zbiór i uruchamiaj go regularnie.
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ł:
- Sprawdź rozmiar wejścia. Bardzo małe captcha często lepiej się czytają po powiększeniu 3x.
- Konwertuj do skali szarości i rozciągnij kontrast, żeby litery wyróżniały się.
- Zastosuj próg i wypróbuj kilka wartości, zanim wybierzesz jedną.
- Usuń szum punktowy filtrem medianowym, a potem ewentualnie ponów progowanie.
- Przytnij obraz do obszaru tekstu, żeby tło nie zmylało silnika.
- Ogranicz zestaw znaków do tego, którego używa captcha.
- 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
- Odczytywanie tekstu ze zeskanowanych dokumentów, zrzutów ekranu lub własnych obrazów testowych.
- Narzędzia dostępności, które opisują lub odczytują captcha, tak aby użytkownik z niepełnosprawnością wzroku mógł skorzystać z alternatywnej ścieżki udostępnionej przez stronę.
- Testowanie własnego projektu captcha, żeby sprawdzić, jak łatwo odczytają je zautomatyzowane narzędzia, i go wzmocnić.
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.