Ten sam kod, dwa różne światy. Jak adaptacyjny algorytm rozwiązał problem OCR w trybie jasnym i ciemnym.
Każdy, kto próbował zmusić komputer do odczytania tekstu ze zdjęcia, wie, że optyczne rozpoznawanie znaków (OCR) to często droga przez mękę. A jeśli to zdjęcie ekranu monitora? Wtedy wkraczamy na zupełnie nowy poziom wyzwań. Do gry wchodzą odblaski światła, denerwujące wzory moiré i ogólna nieostrość wynikająca z fotografowania siatki pikseli.
W jednym z moich ostatnich projektów stanęłam przed zadaniem zbudowania w Kotlinie rdzenia aplikacji mobilnej, której kluczową funkcją było właśnie precyzyjne odczytanie treści ze zdjęcia ekranu. Wiedziałam, że bez solidnego mechanizmu „czyszczenia” obrazu, cała funkcja będzie bezużyteczna, a silnik OCR zwróci cyfrową sałatkę, a nie sensowny tekst.
Główny wróg: Nieprzewidywalność
Szybko odkryłam, że największym problemem nie są same zakłócenia, ale ich zmienność. Kluczowym wyzwaniem okazała się różnica między trybem jasnym i ciemnym w systemach operacyjnych. Zestaw filtrów i parametrów, które świetnie radziły sobie z czarnym tekstem na białym tle, kompletnie zawodził przy białym tekście na ciemnym tle.
Mogłabym próbować znaleźć jeden uniwersalny zestaw ustawień, ale byłby to kompromis, który działałby słabo w obu przypadkach. Wiedziałam, że rozwiązanie musi być mądrzejsze. Musi być adaptacyjne.
Rozwiązanie: Algorytm, który najpierw patrzy, potem działa
Zamiast siłowo narzucać jedno rozwiązanie, postanowiłam nauczyć mój kod najpierw analizować problem. Stworzyłam w Kotlinie funkcję, która w pierwszym kroku sprawdza średnią jasność obrazu. Na tej podstawie jest w stanie z dużą pewnością stwierdzić, czy ma do czynienia z interfejsem w trybie jasnym, czy ciemnym.
Dopiero wtedy, uzbrojona w tę wiedzę, dynamicznie dobiera zupełnie inny zestaw narzędzi z biblioteki OpenCV – inny tryb progowania (thresholdingu) i inne wartości dla operacji, które usuwają cyfrowy „szum”. To tak, jakby lekarz najpierw stawiał diagnozę, a dopiero potem dobierał leki.
Serce rozwiązania: Kod, który adaptuje się do tła
Cała ta „magia” dzieje się w jednej, przemyślanej funkcji. Poniższy fragment kodu z mojego obiektu OpenCvEnhancer pokazuje kluczowy moment decyzyjny, w którym algorytm wybiera strategię przetwarzania w zależności od tła.
fun preprocessForTesseract(srcMat: Mat): Mat? {
try {
val grayMat = Mat()
Imgproc.cvtColor(srcMat, grayMat, Imgproc.COLOR_BGR2GRAY)
// Kluczowy krok: sprawdzam średnią jasność obrazu, by wykryć tryb
val avgBrightness = Core.mean(grayMat).`val`[0]
val isDarkBackground = avgBrightness < 100 // Mój próg dla "dark mode"
// Dynamiczny dobór parametrów progowania
val thresholded = Mat()
Imgproc.adaptiveThreshold(
grayMat,
thresholded,
255.0,
Imgproc.ADAPTIVE_THRESH_MEAN_C,
// Jeśli tło jest ciemne (dark mode), odwracam działanie filtra
if (isDarkBackground) Imgproc.THRESH_BINARY_INV else Imgproc.THRESH_BINARY,
// I dobieram inne parametry "czyszczenia"
if (isDarkBackground) 31 else 45,
if (isDarkBackground) 11.0 else 15.0
)
grayMat.release()
return thresholded
} catch (e: Exception) {
// ... obsługa błędów
return null
}
}
Efekt: Od chaosu do stabilności
Wprowadzenie tej adaptacyjnej logiki przyniosło natychmiastowe rezultaty. Dokładność OCR wzrosła diametralnie, a aplikacja radziła sobie równie dobrze ze zdjęciem Notatnika w Windowsie, jak i z terminalem programisty na ciemnym tle.
Co najważniejsze, nieprzewidywalna i zawodna funkcja przekształciła się w stabilny i godny zaufania komponent. Mój moduł OCR stał się solidnym fundamentem, który odblokował możliwość dalszego, bezproblemowego rozwoju całej aplikacji.
Uwielbiam takie wyzwania, bo wierzę, że w programowaniu diabeł tkwi w szczegółach. Zamiast szukać drogi na skróty, wolę dogłębnie zrozumieć unikalne problemy i zbudować solidne, elastyczne rozwiązanie, które sprawdzi się w realnym świecie.
Mierzysz się z trudnym wyzwaniem technicznym w swojej aplikacji mobilnej, gdzie standardowe biblioteki zawodzą? Potrzebujesz rozwiązania, które poradzi sobie ze specyficznymi, nieprzewidywalnymi danymi?
Skontaktuj się ze mną – chętnie pomogę Ci znaleźć skuteczne i solidne rozwiązanie.
