POL
ENG

Histogram

Czasem chcemy pokazać ile jest takich samych elementów w całym zbiorze. Weźmy na przykład, dziecięcy basen z kolorowymi plastikowymi piłkami. Załóżmy, że jest ich 1000 i że są w 5 kolorach (żółty, czerwony, zielony, niebieski, biały). Żeby pokazać na jednym wykresie ile jest piłek danego koloru, musimy wyciągnąć każdą piłkę i policzyć każdy kolor osobno. Posumowane wyniki umieścić na wykresie gdzie oś X to kolory, a Y to liczba piłek.

W ten oto sposób otrzymujemy histogram. W odniesieniu do zdjęć stosuje się go do pokazania ile składowych danego koloru znajduje się na danym obrazie. Niedawno potrzebowałem dodać taki rodzaj analizy do jednego swojego projektu. OpenCV oferuje gotową funkcję do tego calcHist(...). Użyłem jej do porównania, czy moje rozumienie algorytmu jest poprawne i czy kod daje takie same rezultaty. Tak powstała prosta aplikacja, która jako parametr przyjmuje ścieżkę do pliku i jako wynik wyświetla jego histogram.

Algorytm

W przypadku tej aplikacji, intersuje mnie histogram obrazu w skali szarości, dlatego na wstępie po wczytaniu pliku jest on konwertowany do takiej palety barw. Aby wyznaczyć histogram obrazu należy wybrać przedziały poszukiwanych wartości z całego spektrum dostępnych. Dla skali szarości, każdy pixel może mieć wartość od 0 (czarny) do 255 (biały). Mnie interesowało pełny zakres, dlatego na wykresie będzie się znajdować 256 słupków. Teraz iterując po każdym pikselu sprawdzam jego wartość i dodaję jeden do grupy pikseli o tej samej barwie:

for (uint16_t r = 0; r < gray.rows; ++r) {

const uint8_t* row = gray.ptr(r);

for (uint16_t c = 0; c < gray.cols; ++c)

frequency[row[c]] += 1;

}

}

Obrazy różnią się treścią i wielkością, przez co ilość pikseli o tym samym kolorze (np. białym) będzie się znacznie różniła w zależności pliku. Z tego powodu trudno było by (choć nie niemożliwe) dobrać uniwersalny zakres osi Y.Trudo było by dobrać uniwersalną maksymalną wartość na wykresie. Dlatego korzysta się z normalizacji, rodzaju przeskalowania, dla któego maksymalna wartość przyjmuje ustaloną wielkość a reszta jest modyfikowana proporcjonalnie do niej

for (uint16_t x = 0; x < histSize - 1; ++x) {

histVector[x] = (uint32_t)((100.0 / max) * histVector[x]);

}

Przykładowe zdjęcia:

Aplikacja:

partipar 2020-09-27
Very simple example. Good explained.
@lbert 2020-08-31
This is what I was looking for. Thanks!
Dodaj komentarz

Histogram, openCV, picture processing

Wszelkie prawa zastrzeżone. Projekt i wykonanie strony SrcPro.pl