algorytm.org

Retinex



Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Retinex
Ocena użytkowników:***** / 123
SłabyŚwietny 
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:
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 oryginalnyRetinex, σ = 5
Obraz oryginalnyRetinex, σ = 5
Retinex, σ = 50Retinex, σ = 250
Retinex, σ = 50Retinex, σ = 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 oryginalnyWieloskalowy retinex, σ = 5, 50, 250
Obraz oryginalnyWieloskalowy retinex, σ = 5, 50, 250
Obraz oryginalnyWieloskalowy retinex, σ = 5, 50, 250 (kolor)


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 oryginalnyWieloskalowy retinex, σ = 5, 50, 250
z przywracaniem kolorów
Obraz oryginalnyWieloskalowy retinex, σ = 5, 50, 250 z przywracaniem kolorów
Obraz oryginalnyWieloskalowy retinex, σ = 5, 50, 250 z przywracaniem kolorów (kolor)


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

Plik:
Waga skali 1:
Współczynnik σ (skala 1):
Waga skali 2:
Współczynnik σ (skala 2):
Waga skali 3:
Współczynnik σ (skala 3):
Alfa:
Beta:

Implementacje
AutorJęzyk
programowania
KomentarzOtwórzPobierzOcena
Tomasz LubińskiC#Visual Studio C# 2010 Express
.cs
.cs
***** / 4
Tomasz LubińskiJavaScriptFirefox 3.0+, Safari 3.0+, Chrome 3.0+, Opera 9.5+, IE 9.0+
.js
.js
***** / 2
 
Dodaj własną implementację tego algorytmu
  • Zaloguj się na stronie
Plik:
Język
programowania:
Komentarz:
  By móc dodać implementacje zaloguj się na stronie

Poprawiony: 18 lutego 2013 21:26
Komentarze
photo
+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ć
photo
-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