Wpisany przez Tomasz Lubiński,
05 lutego 2013 14:07
Często robiąc zdjęcia, na których są zarówno obszary mocno oświetlone jak i te położone w cieniu trudno jest dobrać tak parametry by wszystkie szczegóły były dobrze widoczne. W efekcie albo dobrze oświetlona część zdjęcia jest prześwietlona, albo szczegóły pozostające w cieniu nie są widoczne. A przecież ludzkie oko doskonale radzi sobie w takich sytuacjach. Przykładem może być tutaj zdjęcie ciemnego pokoju oświetlonego jedynie małą stojącą lampą, albo zdjęcie krajobrazu na którym jednocześnie znajdują się obszary położone w słońcu jak i cieniu. Skrajnym przykładem jest tutaj robienie zdjęć pod światło.
Retinex
Jeżeli posiadamy już taką fotografię możemy spróbować poprawić ją przy użyciu algorytmu Retinex. Metodę tą zaproponował w roku 1986 Edwin Land (współzałożyciel firmy Polaroid). Badał on sposób widzenia światła i kolorów przez człowieka. Doszedł on do wniosku, że postrzegane światło i jego kolor nie zależą wyłącznie od mocy i długości fali, ale również od światła emitowanego w jego sąsiedztwie. Nazwa metody Retinex jest zlepkiem dwóch słów: siatkówka oka (ang. retina) oraz kora mózgowa (ang. cortex). Algorytm zaproponowany przez Land'a przebiega następująco:
niech:
pi - oznacza i-ty piksel obrazu
I(pi) - oznacza jasność i-tego piksla obrazu
A - to tablica przechowująca akumulowaną względną jasność punktu
N - to tablica przechowująca licznik ile razy jasność w danym punkcie była akumulowana
Losujemy dowolny piksel obrazu. Niech będzie to punkt p. Zaczynając z tego punktu, tworzymy ścieżkę wybierając losowo sąsiednie punkty. Dla każdego punktu pi, położonego na tej ścieżce wykonujemy następujące obliczenia:
Parametrami wejściowymi do algorytmu są: obraz do przetworzenia, liczba ścieżek oraz ich długość. Po wykonaniu powyższych obliczeń dla zadanej liczby ścieżek, obliczamy wynikową jasność punktów obrazu L jako:
Niech:
Lmin - oznacza najmniejszą obliczoną wartość jasności,
Lmax - oznacza największą obliczoną wartość jasności,
Imax - oznacza największą możliwą wartość z zakresu obsługiwanego przez użyty format (np: 255, dla zakresu 0..255).
Wówczas każdą wartość wynikową przeskalujemy następująco:
Jednoskalowy Retinex (SSR - Single Scale Retinex)
Algorytm w takiej formie powoduje, że każde jego wywołanie daje nieco inne wyniki - ze względu na losowość ścieżek. Dlatego też algorytm uogólniono stosując rozmywanie Gaussowskie. Długość ścieżki, czyli wielkość sąsiedztwa branego pod uwagę określa się wówczas parametrem σ. Większa wartość oznacza większe sąsiedztwo czyli dłuższą ścieżkę.
Dla przypomnienia kolejne współczynniki filtru Gaussa x = 0, 1, 2, ... opisane są następującym wzorem:
Niech:
p - oznacza piksel obrazu
I(p) - oznacza jasność (lub składową) piksla obrazu
I'(p) - oznacza jasność (lub składową) piksla obrazu po użyciu filtra Gaussa
Wówczas wynik działania algorytmu Retinex dla danego punktu p będzie określony następującym wzorem:
Wieloskalowy Retinex (MSR - Multi Scale Retinex)
By uzyskać wszystkie zalety różnych wartości parametru σ, wprowadzono udoskonalenie, czyli wieloskalowy algorytm retinex (ang. MSR - multi scale retinex). Jest to prosta suma ważona pojedynczych wywołań dla różnych wartości σ.
n - liczba skal
wi - waga i-tej skali (w1 + w2 + ... + wn = 1)
p - piksel obrazu
I(p) - oznacza jasność (lub składową) piksla obrazu
Ii'(p) - oznacza jasność (lub składową) piksla obrazu po użyciu filtra Gaussa, z i-ta wartością σ
W praktyce najczęściej stosuje się 3 skale o równomiernym rozłożeniu (wagach równych 1/3), i wartościach σ np: 5, 50, 250.
Wieloskalowy Retinex z przywracaniem kolorów (MSRCR - Multi Scale Retinex with Color Restoration)
Algorytm Retiniex doskonale uwydatnia szczegóły położone w obszarach niedoświetlonych, ale jednocześnie powoduje wyblaknięcie obrazu. Dlatego też wprowadzono mechanizm, który ma na celu przywrócenie kolorów i dynamiki zdjęcia. Niech:
s - oznacza liczbę składowych (dla obrazu w trybie RGB, będą to trzy składowe R dla czerwonego, G dla zielenego, B dla niebieskiego)
Ic(p) - oznacza wartość c-tej składowej piksla obrazu wejściowego (dla obrazu w trybie RGB, będą to wartości kolejnych składowych R, G, oraz B)
Rc(p) - oznacza wartość c-tej składowej piksla obrazu po zastosowaniu algorytmu Reinex (w wersji jedno lub wieloskalowej)
Wówczas każdy punkt obrazu przetwarzamy zgodnie z poniższym wzorem:
Ustaw ścieżkę do pliku (lub pozostaw tą domyślną), wczytaj plik a następnie użyj przycisku "Retinex" by sprawdzić działanie metody.
Ze względu na zabezpieczenia w przeglądarkach, skrypt otwiera wyłącznie pliki graficzne w obrębie naszego serwisu, np:
http://www.algorytm.org/images/stories/po/retinex_color.jpg
http://www.algorytm.org/images/stories/po/retinex_grey.jpg
http://www.algorytm.org/images/stories/po/test.png
Retinex
Jeżeli posiadamy już taką fotografię możemy spróbować poprawić ją przy użyciu algorytmu Retinex. Metodę tą zaproponował w roku 1986 Edwin Land (współzałożyciel firmy Polaroid). Badał on sposób widzenia światła i kolorów przez człowieka. Doszedł on do wniosku, że postrzegane światło i jego kolor nie zależą wyłącznie od mocy i długości fali, ale również od światła emitowanego w jego sąsiedztwie. Nazwa metody Retinex jest zlepkiem dwóch słów: siatkówka oka (ang. retina) oraz kora mózgowa (ang. cortex). Algorytm zaproponowany przez Land'a przebiega następująco:
niech:
pi - oznacza i-ty piksel obrazu
I(pi) - oznacza jasność i-tego piksla obrazu
A - to tablica przechowująca akumulowaną względną jasność punktu
N - to tablica przechowująca licznik ile razy jasność w danym punkcie była akumulowana
Losujemy dowolny piksel obrazu. Niech będzie to punkt p. Zaczynając z tego punktu, tworzymy ścieżkę wybierając losowo sąsiednie punkty. Dla każdego punktu pi, położonego na tej ścieżce wykonujemy następujące obliczenia:
A_i = A_i + \log(I(p_i)) - \log(I(p))\\
N_i = N_i + 1
Przy czym należy zabezpieczyć się przed sytuacją, w której jasność piksla wynosi zero, gdyż wartość logarytmu z zera jest niezdefiniowana. Można to zrobić przesuwając zakres danych wejściowych. Jeżeli jest on równy 0..255, to wystarczy do każdej wartości dodać 1, tak by uzyskać zakres 1..256, w przypadku zakresu 0..1, można dodać wartość 0.001.Parametrami wejściowymi do algorytmu są: obraz do przetworzenia, liczba ścieżek oraz ich długość. Po wykonaniu powyższych obliczeń dla zadanej liczby ścieżek, obliczamy wynikową jasność punktów obrazu L jako:
L_i = \frac{A_i}{N_i}
Wynikową jasność należy teraz sprowadzić do zakresu obsługiwanego przez użyty format.Niech:
Lmin - oznacza najmniejszą obliczoną wartość jasności,
Lmax - oznacza największą obliczoną wartość jasności,
Imax - oznacza największą możliwą wartość z zakresu obsługiwanego przez użyty format (np: 255, dla zakresu 0..255).
Wówczas każdą wartość wynikową przeskalujemy następująco:
L_i = \frac{L_i-L_{min}}{L_{max}-L_{min}} * I_{max}
Jednoskalowy Retinex (SSR - Single Scale Retinex)
Algorytm w takiej formie powoduje, że każde jego wywołanie daje nieco inne wyniki - ze względu na losowość ścieżek. Dlatego też algorytm uogólniono stosując rozmywanie Gaussowskie. Długość ścieżki, czyli wielkość sąsiedztwa branego pod uwagę określa się wówczas parametrem σ. Większa wartość oznacza większe sąsiedztwo czyli dłuższą ścieżkę.
Dla przypomnienia kolejne współczynniki filtru Gaussa x = 0, 1, 2, ... opisane są następującym wzorem:
\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{x^{2}}{2\sigma^{2}}}
Filtr ten zastosujemy dwa razy. Pierwszy raz w kierunku poziomym (na kopii punktów z obrazu wejściowego), drugi raz w kierunku pionowym (na punktach rozmytych już w kierunku poziomym).Niech:
p - oznacza piksel obrazu
I(p) - oznacza jasność (lub składową) piksla obrazu
I'(p) - oznacza jasność (lub składową) piksla obrazu po użyciu filtra Gaussa
Wówczas wynik działania algorytmu Retinex dla danego punktu p będzie określony następującym wzorem:
R(p) = \log(I(p)) - \log(I'(p)) = \log\frac{I(p)}{I'(p)}
Tak zdefiniowany algorytm nosi nazwę jednoskalowego algorytmu retinex (ang. SSR - single scale retinex). Zazwyczaj każdy piksel obrazu opisany jest przez 3 składowe (R, G, B). Dlatego też algorytm ten wykonuje się niezależnie dla każdej z nich. W zależności od wielkości współczynnika σ, algorytm daje inne wyniki. Małe wartość uwydatniają niewielkie szczegóły ale powodują zawężenie zakresu wartości obrazu, większe wartości powodują utratę szczegółów ale dają lepszy zakres tonalny.Obraz oryginalny | Retinex, σ = 5 |
Retinex, σ = 50 | Retinex, σ = 250 |
Wieloskalowy Retinex (MSR - Multi Scale Retinex)
By uzyskać wszystkie zalety różnych wartości parametru σ, wprowadzono udoskonalenie, czyli wieloskalowy algorytm retinex (ang. MSR - multi scale retinex). Jest to prosta suma ważona pojedynczych wywołań dla różnych wartości σ.
R(p) = \sum_{i=1}^{n}{w_i * \log\frac{I(p)}{I_i'(p)}}
gdzie:n - liczba skal
wi - waga i-tej skali (w1 + w2 + ... + wn = 1)
p - piksel obrazu
I(p) - oznacza jasność (lub składową) piksla obrazu
Ii'(p) - oznacza jasność (lub składową) piksla obrazu po użyciu filtra Gaussa, z i-ta wartością σ
W praktyce najczęściej stosuje się 3 skale o równomiernym rozłożeniu (wagach równych 1/3), i wartościach σ np: 5, 50, 250.
Obraz oryginalny | Wieloskalowy retinex, σ = 5, 50, 250 |
Wieloskalowy Retinex z przywracaniem kolorów (MSRCR - Multi Scale Retinex with Color Restoration)
Algorytm Retiniex doskonale uwydatnia szczegóły położone w obszarach niedoświetlonych, ale jednocześnie powoduje wyblaknięcie obrazu. Dlatego też wprowadzono mechanizm, który ma na celu przywrócenie kolorów i dynamiki zdjęcia. Niech:
s - oznacza liczbę składowych (dla obrazu w trybie RGB, będą to trzy składowe R dla czerwonego, G dla zielenego, B dla niebieskiego)
Ic(p) - oznacza wartość c-tej składowej piksla obrazu wejściowego (dla obrazu w trybie RGB, będą to wartości kolejnych składowych R, G, oraz B)
Rc(p) - oznacza wartość c-tej składowej piksla obrazu po zastosowaniu algorytmu Reinex (w wersji jedno lub wieloskalowej)
Wówczas każdy punkt obrazu przetwarzamy zgodnie z poniższym wzorem:
R_c(p) = beta * \log\left(alfa * \frac{I_c(p)}{I_1(p) + I_2(p) + ... + I_s(p)} \right) * R_c(p)
Czyli dla obrazu w trybie RGB, będzie to wyglądać następująco:
R_r(p) = beta * \log\left(alfa * \frac{I_r(p)}{I_r(p)+I_g(p)+I_b(p)} \right) * R_r(p)\\\\
R_g(p) = beta * \log\left(alfa * \frac{I_g(p)}{I_r(p)+I_g(p)+I_b(p)} \right) * R_g(p)\\\\
R_b(p) = beta * \log\left(alfa * \frac{I_b(p)}{I_r(p)+I_g(p)+I_b(p)} \right) * R_b(p)\\\\
Wyznaczenie wartości minimalnej i maksymalnej do sprowadzenia wartości do zakresu obsługiwanego przez użyty format robimy przed operacją przywracania kolorów. Po złożeniu wszystkich operacji razem: wieloskalowy algorytm Retinex, przywracanie kolorów, powrót do zakresu obsługiwanego przez użyty format, otrzymujemy następujący wynik:Obraz oryginalny | Wieloskalowy retinex, σ = 5, 50, 250 z przywracaniem kolorów |
Przykład w JavaScript:
Ustaw ścieżkę do pliku (lub pozostaw tą domyślną), wczytaj plik a następnie użyj przycisku "Retinex" by sprawdzić działanie metody.
Ze względu na zabezpieczenia w przeglądarkach, skrypt otwiera wyłącznie pliki graficzne w obrębie naszego serwisu, np:
http://www.algorytm.org/images/stories/po/retinex_color.jpg
http://www.algorytm.org/images/stories/po/retinex_grey.jpg
http://www.algorytm.org/images/stories/po/test.png
Implementacje
Autor | Język programowania | Komentarz | Otwórz | Pobierz | Ocena |
Tomasz Lubiński | C# | Visual Studio C# 2010 Express | .cs | .cs | ***** / 4 |
Tomasz Lubiński | JavaScript | Firefox 3.0+, Safari 3.0+, Chrome 3.0+, Opera 9.5+, IE 9.0+ | .js | .js | ***** / 2 |
Poprawiony: 18 lutego 2013 21:26
Komentarze
+3
#
Borneq
2013-05-16 16:47
Algorytm może nadawać się do czarno-białego xero tekstów, gdzie w ciemniejszym rejonie progowanie miało by inną wartość niż w jaśniejszym
Odpowiedz | Odpowiedz z cytatem | Cytować
-2
#
Dashrek
2018-01-01 12:46
Pełno niedomówień takich jak niezdefiniowani e liczby losowej i sposobów wyboru pikseli. Dalej brak konkretu dla x we wzorze Gaussa, co to znaczy w kierunku poziomym i pionowym- kolejne parametry liczby x=1,2, to napisz tak i nie oczekuj, że każdy czytelnik wie o co Ci chodzi. Piszesz bzdury, którym brakuje połowy tekstu! Większość algorytmów z tej strony jest do prostego napisania w języku programowania po przeczytaniu opisu, tylko w kilku trzeba przeczytać program, aby zrozumieć autora. 3/5 bo przez ciebie musiałem rozkminiać Borlanda, kiedy pracuję z qt i gtk.
Odpowiedz | Odpowiedz z cytatem | Cytować
Dodaj komentarz