Zestaw zadań C — histogramy

Uwagi do wszystkich zestawów:

  • Jeśli nie napisano inaczej to obraz wejściowy ma typ numpy.uint8 (czyli liczba całkowita z przedziału [0;255]).
  • Jeśli funkcja ma zwracać obraz i nie napisano inaczej to ma on mieć ten sam typ co obraz wejściowy (czyli zazwyczaj numpy.uint8). Dlatego proszę używać funkcji np.rint do zaokrąglenia wartości ułamkowych do najbliższej liczby całkowitej (tam gdzie to jest potrzebne).
  • Jeśli nie napisano inaczej to przetwarzamy obrazy jednokanałowe (czyli dwuwymiarowa tablica NumPy).

Zestaw C

  1. Napisz funkcję zadC1(image) obliczającą histogram obrazu. Należy zwrócić 1D tablicę NumPy (typu float) o 256 elementach, w której i-ty element (i z zakresu 0-255) określa prawdopodobieństwo wystąpienia piksela o wartości i w danym obrazie wejściowym.
    Można wykorzystać zarówno funkcję np.histogram jak i “ręcznie” zliczyć liczbę wystąpień poszczególnych wartości.
    Zachęcam do zaimplementowania obu wariantów (ale na serwer wystarczy wysłać jeden). Iterować po wszystkich wartościach tablicy image można np. przy użyciu konstrukcji:

    1
    2
    
      for value in image.flat: # image.flat zwraca widok na "spłaszczoną" (czyli 1D) tablicę image
          ... # tutaj robimy coś z wartością value (wartości dla kolejnych elementów tablicy image)
  2. Napisz funkcję zadC2(image) rozciągającą histogram. Funkcja przyjmuje jako argument obraz wejściowy i zwraca obraz po wykonaniu operacji rozciągania histogramu.
    Proszę założyć, że w obrazie image występują przynajmniej dwa piksele o różnych wartościach. Jakiego problemu dzięki temu unikamy?

  3. Napisz funkcję zadC3(image) wyrównującą histogram. Funkcja przyjmuje jako argument obraz wejściowy i zwraca obraz po wykonaniu operacji wyrównania histogramu.
    Do zamiany punktu o wartości x w oryginalnym obrazie na wartość y w obrazie wynikowym proszę użyć wzoru:
    y = 255*(D[x]-D0)/(1-D0), gdzie:
    D – dystrybuanta histogramu oryginalnego obrazu (do wyliczenia dystrybuanty z wcześniej policzonego histogramu można użyć funkcji np.cumsum,
    D0 – pierwsza niezerowa wartość w dystrybuancie D

    Proszę założyć, że w obrazie image występują przynajmniej dwa piksele o różnych wartościach. Jakiego problemu dzięki temu unikamy?

    Zachęcam aby wykorzystać technikę tablicowania czyli tak zwaną “lookup table” (LUT). Służy ona do zamiany wartości wszystkich punktów według wcześniej zdefiniowanego mapowania oryginalnej wartości na określoną nową wartość.
    Przyda się do tego znajomość specjalnego indeksowania w NumPy (które nie pojawiło się jeszcze wcześniej na zajęciach). Proszę przeanalizować przykład:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    tab = np.array([100,101,102,103])  # wartość i będziemy zamieniać na wartość tab[i], czyli np. 0 -> 100
    print(tab)
    # [100 101 102 103]
    img = np.array([[0,1,2],[3,2,1]])
    print(img)
    # [[0 1 2]
    #  [3 2 1]]
    out = tab[img] # <-- stosujemy LUT: wynik ma kształt tablicy img, out[y,x] == tab[img[y,x]]
    print(out)
    # [[100 101 102]
    #  [103 102 101]]