Zestaw zadań A


Informacje

Celem każdego zadania jest napisanie dwóch funkcji:

  1. def zadAX(...),
  2. def testAX(),

gdzie A to nazwa zestawu, a X to numer zadania (czyli np. zadA4 to nazwa funkcji konwertującej obraz RGB na odcienie szarości w poniższym zestawie zadań).
Funkcja zadAX(...) to implementacja danego zadania, natomiast funkcja testAX() ma testować poprawność implementacji tej pierwszej.
Funkcja z testami nie przyjmuje żadnych parametrów i w przypadku pomyślnego przejścia wszystkich testów w niej zaimplementowanych nie powinna zwracać żadnej wartości (ewentualnie może zwrócić wartość True).
W przypadku gdy uruchomienie funkcji testAX() zakończy się wyjątkiem albo funkcja ta zwróci wartość inną niż None lub True, sprawdzarka uzna, że funkcja zadAX nie przeszła testów użytkownika.
Wewnątrz funkcji testAX powinien znaleźć się kod uruchamiający funkcję zadAX() dla różnych argumentów i sprawdzający poprawność zwróconych wyników (patrz przykład niżej).

Rozwiązanie każdego zadania należy rozpocząć od implementacji testów a dopiero później od implementacji właściwej funkcji, np.:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def zadA1(image):
    return
 
def testA1():
    result = zadA1(np.array([[0,1,255]], np.uint8))
    expected = [[255,254,0]]
 
    np.testing.assert_array_equal(result, expected)
    
    # lub gdy mogą wystąpić błędy zaokrągleń
    # np.testing.assert_allclose(result, expected)
    
    # tutaj inne testy
    # ...
 
if __name__ == "__main__":
    testA1()
    ...
    testA9()

UWAGA!
Każde gotowe i samodzielnie przetestowane rozwiązanie zadania należy wysłać na serwer przy pomocy sprawdzarki uruchomionej z linii poleceń (patrz niżej).
Proszę zwrócić uwagę, że programy mają być przetestowane – premiowane będą rozwiązania które przed wysłaniem (czyli przed uruchomieniem checkera dla danego zadania) są na tyle dobre, że przejdą od razu testy ze sprawdzarki.
Dlatego proszę wcześniej przygotować własne testy i odpowiednio je uruchamiać jak np. w przykładzie powyżej.

Sprawdzarka

Do wysłania gotowego rozwiązania należy wykorzystać odpowiednią sprawdzarkę dla

Wymaga ona pliku konfiguracyjnego umieszczonego w tym samym katalogu co checker.pyc w którym należy odpowiednio uzupełnić 3 linie (bez żadnych dodatkowych znaków jak < czy >).
Wszystkie znaki powinny być kodowane w utf-8.

Uruchomienie z linii poleceń: python3 checker.pyc PlikZFunkcją.py nazwaFunkcji/zadania, np.:

python3 checker.pyc MojeZadania zadA1 — nazwa pliku może być bez rozszerzenia
python3 checker.pyc PlikZFunkcją.py a1 — w nazwie zadania można ominąć “zad”, wielkość liter w nazwie zadania nie ma znaczenia

Sprawdzarka:

  • najpierw uruchamia testy użytkownika (testAX()). Gdy funkcja zadAX() przejdzie je pomyślnie to:
  • uruchamia swoje testy, oraz
  • wysyła je na serwer.

Jeśli wysyłana funkcja nie przejdzie jakiegoś testu zapisanego w sprawdzarce to zostaną wyświetlone argumenty wywołania, wynik zwrócony przez funkcję oraz poprawny wynik dla tego testu jaki był spodziewany.

Uwaga: podczas uruchomienia sprawdzarki wykonywany jest cały plik z kodem testowanej funkcji, dlatego proszę aby były w nim tylko zdefiniowane funkcje, a ewentualny własny kod (np. do uruchamiania testów) był uruchamiany warunkowo tak jak w poniższym przykładzie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  import numpy as np
  def zadA1(obrazek):
      return obrazek
  def testA1():
      # przykładowy test...
      result = zadA1(np.zeros((10,20), np.uint8))
      expected = ...
      np.testing.assert_array_equal(result, expected)
      assert result.shape == (10,20)  # jeśli przejdzie wcześniejszy test to ten też musi :) 
  def funkcjaPomocnicza(a):
      return a + 5
  def zadA2(argument):
      return funkcjaPomocnicza(a)
  ...
  if __name__ == "__main__":
      testA1()
      # coś tam...
      obr = np.array([1,2,3], np.uint8)
      wynik = zadA1(obr)
      print(wynik)

Zadania A

Jeśli nie napisano inaczej to wszystkie zadania zakładają, że obraz wejściowy jest jednokanałowy (lub 3 kanałowy w przypadku obrazów kolorowych) i jest dany jako tablica o typie np.uint8 (liczby całkowite z przedziału 0-255), np. np.array([[0,1],[2,255]], np.uint8). Proszę uważać na zakresy i typ wartości pojawiające się w obliczeniach!

  1. Napisz funkcję zadA1(image) przyjmującą jeden argument (obraz wejściowy) i zwracającą negatyw tego obrazu.

  2. Napisz funkcję progującą zadA2(image, thr) przyjmującą dwa argumenty (obraz oraz liczbę określającą próg). Funkcja ma zwrócić obraz którego piksele mają wartość 255 gdy wartość oryginalnego piksela była większa od podanego progu, oraz 0 w przeciwnym wypadku.

  3. Napisz funkcję zadA3(image, gamma) zwracającą obraz po wykonaniu korekcji gamma (gamma > 0). Użyj funkcji np.rint do zaokrąglenia wartości ułamkowych do najbliższej liczby całkowitej.
    Uwaga: W internecie można znaleźć 2 różne wzory (jedno przekształcenie będące cofnięciem drugiego z nich). W zadaniu proszę zastosować wzór który jest podany m.in. na slajdach do wykładów.

  4. Napisz funkcję zadA4(image) konwertującą obraz kolorowy RGB (tablica 3D) na obraz w odcieniach szarości (tablica 2D). Do wyliczenia wartości piksela użyj formuły: 0.21 R + 0.72 G + 0.07 B. Użyj funkcji np.rint do zaokrąglenia wartości ułamkowych do najbliższej liczby całkowitej.

  5. Napisz funkcję zadA5(image) obliczającą wartość Hue dla każdego piksela obrazu RGB (wynik jest tablicą 2D). Użyj formuły trygonometrycznej. Wyraź Hue jako kąt w stopniach w przedziale [0;360).

  6. Napisz funkcje zadA6(imageA, imageB, alpha) obliczającą kombinację liniową obu obrazków, gdzie imageA i imageB to obrazki o identycznych rozmiarach, a alpha wartość rzeczywista z przedziału [0;1]. Każdy piksel wynikowego obrazka zależy w stopniu alpha od imageA i w stopniu 1-alpha od imageB. Użyj funkcji np.rint do zaokrąglenia wartości ułamkowych do najbliższej liczby całkowitej.