Celem projektu było napisanie programu, który usuwałby efekt czerwonych oczu na zdjęciach. Z założenia program miał być uniwersalny, czyli powinien działać z większością znanych formatów plików i nie powinien być zależny od wielkości i rozdzielczości obrazów.
Do realizacji programu przyjąłem następujący algorytm:
Program w całości powstał w oparciu o bibliotekę OpenCV. Rozpoznawanie twarzy zrealizowałem w oparciu o klasyfikator Haar-a (szerszy opis znajduje się w dokumentacji OpenCV). Znając punkty rozpinające obszar, w którym znajduje się twarz doświadczalnie wyznaczyłem obszar, w którym znajdują się oczy. Zawężony juz obszar przeszukuję piksel po pikselu w poszukiwaniu takich, w których wartość czerwieni jest dwa razy większa od wartości innych kolorów. W każdym takim pikselu zeruję wartość czerwieni. Dodatkowo zeruję wartość czerwieni wszystkich pikseli sąsiadujących ze znalezionym pikselem, których wartość czerwieni jest większa od innych wartości kolorów.
Program uruchamia się poprzez wydanie polecenia:
red_eyes_killer [--test] source_image [destination_image]
Do poprawnego działania programu w kartotece w której znajduje sie Red Eyes Killer musi znajdować sie plik haarcascade_frontalface_alt.xml, który jest bazą danych dla klasyfikatora Haar-a.
Jeżeli w argumentach wywołania programu użyjemy opcji --test to program uruchomi się w trybie testowym. Oznacza to, że na obrazie wynikowym program zaznaczy czerwonym prostokątem każdą znalezioną twarz, prostokątem zielonym obszar, w którym znajdują się oczy oraz niebieskimi okręgami orientacyjne obszary, w których dokonano zmian wartości kolorów w pikselach. W trybie testowym program nie modyfikuje obrazu, a jedynie go analizuje.
Jeżeli w argumentach wywołania programu podamy nazwę pliku docelowego to program wczyta plik źródłowy, przetworzy go i zapisze do pliku docelowego. Jeżeli w argumentach wywołania programu nie będzie nazwy pliku docelowego to program po przetworzeniu pliku źródłowego wyświetli go na ekranie i będzie czekał na wciśnięcie dowolnego klawisza, po czym zakończy działanie bez zapisywania obrazu wynikowego do pliku.
Zamieszczone poniżej przykłady ilustrują efekty działania programu. Zdjęcia są specjalnie tak duże, aby można było zaobserwować wszystkie szczegóły. Każdy przykład to zdjęcie oryginalne, obraz testowy i obraz po przetworzeniu.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Przykład 1 pokazuje, że udało mi się osiągnąć założenia projektowe. Program zlokalizował obydwie twarze i usunął całkowicie efekt czerwonych oczu. Obraz wynikowy wygląda bardzo dobrze i realistycznie. W pierwszym przykładzie można zauważyć, że klasyfikator Haar-a odpowiedzialny za lokalizowanie twarzy pomylił się i zlokalizował twarz w miejscu, w którym jej nie ma. W tym przykładzie nie powoduje to jednak żadnych błędów, ponieważ w wyznaczonym obszarze nie znajdowały się na tyle czerwone piksele, aby można je było zaklasyfikować jako składowe czerwonych oczu.
Przykład 2 ilustruje jak zachowuje się program w przypadku, gdy twarz zajmuje większą część obrazu. Jak widać nie utrudnia to jej lokalizacji i twarz jest rozpoznawana poprawnie. Jednak są dwie przyczyny nieprawidłowego zadziałania Red Eyes Killer-a. Pierwsza z nich to fakt, że wokół oczu mężczyzny na zdjęciu znajdują się piksele o wysokim stosunku czerwieni do innych kolorów. Program uznał, że są to składowe czerwonych oczu i zmienił ich barwę. Druga przyczyna miernego efektu działania to odcień czerwieni w oczach. Czerwień ta jest bardzo ciemna, co oznacza, że stosunek koloru czerwonego do innych jest w niektórych miejscach za mały, aby program sklasyfikował te miejsca jak składowe czerwonych oczu. Można oczywiście zmienić wartość progu dla klasyfikowania pikseli. Spowoduje to jednak, że duża ilość pikseli, które nie tworzą czerwonych oczu zostanie zaklasyfikowana błędnie. Wartość progu, która jest ustawiona w programie dobrałem doświadczalnie i jest to wartość, dla której efekt wizualny na testowanych zdjęciach(około 30 różnych zdjęć) był najlepszy.
Przykład 3 to próba usunięcia czerwonych oczu z zeskanowanego zdjęcia zrobionego "niedrogim" aparatem na kliszę. Efekt jest wysoce niezadowalający. Pomimo, że klasyfikator Haar-a poprawnie zlokalizował twarze, zastosowany przezemnie algorytm wyszukiwania czerwonych oczu zadziałał niepoprawnie. Powodem jest nadmierna i wręcz nienaturalna ilość czerwieni na zdjęciu.
Przykład 4 to próba usunięcia czerwonych oczu z bardzo dużym odblaskiem. Efekt znowu jest mało zadowalający. Odblask jest tak duży, że dominuje w nim kolor biały, co nie pozwala zaklasyfikować pikseli jako składowe czerwonych oczu. Ten efekt jest w zasadzie nie do usunięcia nawet przy próbach modyfikacji progu dla klasyfikatora czerwonych oczu. Jeżeli program analizujący piksele usunąłby taki odblask, to najprawdopodobniej usunąłby także piksele tworzące białko oka.
Przykład 5 to próba usunięcia czerwonych oczu osobie, która nosi okulary. Jak widać efekt jest bardzo dobry. Okulary nie wprowadziły w błąd ani klasyfikatora twarzy, ani klasyfikatora pikseli. Ten przykład pokazuje jednak inna wadę programu. Otóż klasyfikator Haar-a błędnie zlokalizował twarz na butelce napoju Fanta. Etykieta butelki posiadała natomiast piksele, które klasyfikator pikseli uznał za składowe czerwonych oczu. Efektem jest zmieniony kolor na butelce.
Przykład 6 to próba usunięcia czerwonych oczu na zdjęciu, na którym głowa jednej z postaci jest przekrzywiona. Tym razem całkowicie zawiódł klasyfikator Haar-a. Nie zlokalizował on przekrzywionej głowy, a tym samym Red Eyes Killer nie usunął czerwonych oczu tej postaci. Druga osoba na tym zdjęciu jest jednak wzorowym przykładem działania mojego programu.
Przykład 7 to pokazanie działania programu na zdjęciu o słabej ostrości. Jak widać klasyfikator Haar-a nie miał problemu ze zlokalizowaniem twarzy. Klasyfikator pikseli również poradził sobie z usunięciem czerwonych oczu. Efekt wizualny jest w miarę dobry. Można jednak zauważyć, że oczy postaci na obrazie były modyfikowane, ponieważ nie są tak samo nieostre jak reszta obrazu.
Przetestowałem działanie programu na 30 zdjęciach. Efekt działania programu na 21 z nich można uznać za dobry. Zatem skuteczność Red Eyes Killer-a to 70%. Nawiązując do przykładów należy zauważyć, że rzadko kiedy interesuje nas usuwanie efektu czerwonych oczu z obrazów o słabej ostrości ze względu na ogólną nikłą wartość takich zdjęć. Efekt bardzo dużego odblasku na oczach też występuje bardzo rzadko. Najczęściej występującym negatywnym efektem działania Red Eyes Killer-a była zmiana koloru pikseli, które nie tworzyły czerwonych oczu. Można by przypuszczać zatem, że analiza obrazu piksel po pikselu jest błędnym podejściem. Wychodząc z takiego założenia podczas tworzenia projektu próbowałem jeszcze dwóch innych sposobów lokalizowania czerwonych oczu w wyznaczonym przez klasyfikator Haar-a obszarze. W pierwszym podejściu próbowałem lokalizować oczy wykorzystując transformację Hough-a do lokalizowania kół i okręgów wykorzystując gotową funkcję cvHoughCircles. Mimo usilnych prób i sterowania parametrami przeszukiwania na różne sposoby nie udało mi się tym sposobem namierzyć ani jednego oka. Drugim sposobem było wykorzystanie klasyfikatora Haar-a do lokalizowania oczu. Jednak ten pomysł okazał się nie dobry już na etapie zapoznawania się z jego zasadą działania. Otóż klasyfikator Haar-a do detekcji oczu uczony był rozpoznawać oczy na przykładach, w których postacie nie miały czerwonych oczu, zatem nie potrafiłby on ich rozpoznać na obrazie. Autorzy biblioteki podają, że aby nauczyć klasyfikator rozpoznawać jakiś obiekt należy mu podać kilkaset dobrych przykładów, co zajęłoby mi zbyt dużo czasu. Dlatego w ostateczności zdecydowałem się na analizę obrazu piksel po pikselu.
Dokumentacja do biblioteki OpenCV.
Źródła biblioteki OpenCV.
Przykłady programów wykorzystujących bibliotekę OpenCV.
Wykorzystanie transformacji Hough-a do poszukiwania kół na obrazie.
Artykuły na temat wykorzystania biblioteki OpenCV.