Laboratorium 3 – Przetwarzanie obrazów 1

Zakres materiału

Tablice statyczne, tablice dwuwymiarowe. Odczyt z i zapis do pliku. Pętla for. Interfejs użytkownika programu.

Przygotowanie do zajęć

Przed przystąpieniem do zajęć przygotuj opisane poniżej trzy funkcje operujące na niepełnych, statycznych tablicach dwuwymiarowych (czyli tablicach o wielkości znanej i zadeklarowanej w chwili kompilacji, zaś wykorzystywanych w trakcie działania programu w miarę potrzeb, np. tablicy o wymiarach 10x10, z której w programie wykorzystane są jedynie pierwsze 3 wiersze i 7 kolumn). Dostosuj nagłówki opracowanych przez Ciebie funkcji tak, by mogły zostać użyte poprawnie w ich testowym wywołaniu opisanym w punkcie 4.

  1. Wypełnienie elementów tablicy liczbami będącymi iloczynem ich indeksów. Wymiar wykorzystanej części tablicy powinien być podany jako parametr funkcji.
  2. Wypisanie zawartości tablicy niepełnej (przy wymiarze podanym jak wyżej) na standardowe wyjście.
  3. Zmianę znaków wszystkich elementów tablicy niepełnej (przy wymiarze podanym jak powyżej) na przeciwny.
  4. Testowe wywołanie powyżej opisanych funkcji w rodzaju (wersja prosta):
    int main(){
      wypelnij(3,7);
      printf("Zawartość oryginalna:\n");
      wypisz(3,7);
      zmien_znaki(3,7);
      printf("Zawartość po zmianie znaków:\n");
      wypisz(3,7);
      return 0
    }
    
    przy tablicy, na której dokonywane są operacje zadeklarowanej jako zmienna globalna, powinno spowodować wypełnienie tej zmiennej, wypisanie jej zawartości na standardowe wyjście, zmianę znaków elementów tablicy i ponowne wypisanie zawartości na wyjście. W wersji bardziej rozbudowanej wywołanie przygotowanych funkcji powinno mieć postać wypelnij(obraz,3,7), gdzie obraz jest zmienną lokalną funkcji main. Przykładowy efekt działania wywołania testowego:
    [john_doe@diablo:~]$ ./a.out
    Zawartość oryginalna:
       0    0    0    0    0    0    0
       0    1    2    3    4    5    6
       0    2    4    6    8   10   12
    Zawartość po zmianie znaków:
       0    0    0    0    0    0    0
       0   -1   -2   -3   -4   -5   -6
       0   -2   -4   -6   -8  -10  -12
    
  5. Przygotuj także funkcję obsługi prostego menu (na bazie funkcji switch) złożonego z 4 pozycji (w tym pozycji Zakończ działanie), które po wybraniu liczby odpowiadającej danej pozycji poinformuje o tym fakcie i pozwoli na ponowne dokonanie wyboru (nie dotyczy pozycji Zakończ działanie). Przykładowy efekt działania funkcji:
    [john_doe@diablo:~]$ ./a.out
    Proste menu:
       1 - Pozycja pierwsza
       2 - Pozycja druga
       3 - Pozycja trzecia
       4 - Zakończ działanie
    Twój wybór: 2
    Wybrano pozycję drugą
    Proste menu:
       1 - Pozycja pierwsza
       2 - Pozycja druga
       3 - Pozycja trzecia
       4 - Zakończ działanie
    Twój wybór: 1
    Wybrano pozycję pierwszą
    Proste menu:
       1 - Pozycja pierwsza
       2 - Pozycja druga
       3 - Pozycja trzecia
       4 - Zakończ działanie
    Twój wybór: 4
    Koniec działania programu
    
Ponadto również:

Uwaga do programu odczyt.c

Program odczyt.c zawiera oprócz funkcji wczytującej do pamięci obraz z pliku w formacie PGM, funkcję wyświetlającą tenże obraz za pomocą popularnego programu display (program ten wchodzi w skład służącego do obróbki obrazów pakietu ImageMagick - w przypadku jego braku na lokalnym komputerze można go doinstalować lub skorzystać z usług innego programu przeznaczonego do wyświetlania obrazów). Przykład ten pokazuje jak w najprostszy sposób odwoływać się z poziomu programu w C do poleceń systemowych. Ponieważ program display jest programem graficznym, by zadziałał poprawnie musimy pracować w środowisku graficznym. W tym celu albo używamy konsoli graficznej w dowolnym systemie UNIX lub Linux (poprawnie skonfigurowanej), albo przy pracy z poziomu systemu MS Windows korzystamy z programu emulującego serwer X Window (przykładowe dostępne na stronie diablo) i uzyskujemy pożądany efekt łącząc się z diablo programem putty z ustawioną opcją ,,Enable X11 forwarding'' (w zakładce ,,Tunnels'' ). Przy pierwszym uruchamianiu programu odczyt.c z funkcji wyświetlającej można zrezygnować.

Wskazówka

Często dobrym pomysłem na realizację interfejsu użytkownika programu jest wyposażenie go w menu. Takie menu daje możliwość dokonania wyboru jednej z funkcji programu lub jego zakończenia. Może ono przyjmować formy od rozbudowanego menu graficznego po proste, wyświetlane sekwencyjnie menu tekstowe. Takie proste menu tekstowe w programie realizowane jest w pętli, która kończy swoje działania w chwili wybrania pozycji koniec działania programu. W każdym kroku tej pętli najpierw wysyłana jest na standardowe wyjście lista dostępnych pozycji menu, odczytywany jest wybór użytkownika i na jego podstawie wykonywana odpowiednia funkcja programu z ewentualnym zapytaniem o potrzebne argumenty.

Zadanie do wykonania

Napisać program do obsługi czarno-białych obrazów rastrowych (ze skalą szarości). Takie obrazy mogą być przedstawione w postaci dwuwymiarowej tablicy, której elementy są liczbami całkowitymi. Każda z liczb reprezentuje kolor jednego punktu (piksela) obrazu, przy czym przyjmuje się, że kolorowi czarnemu odpowiada wartość 0, a kolorowi białemu wartość maksymalna, zależna od liczby poziomów szarości.

Program ma obsługiwać obrazy zapisane w plikach w formacie PGM. Przykładowe obrazy w formacie PGM znajdują się na diablo w katalogu /usr/local/air/info2/zadania/splot/obrazki (alternatywnie w /home/mucha/edu/info2/obrazki).

W programie należy zdefiniować:

W pliku odczyt.c przedstawiony został prosty program zawierający funkcje do odczytu obrazu PGM z pliku oraz do jego wyświetlenia programem display.

Wskazówki

  1. W ramach realizacji zadania należy poprawić funkcję wczytującą obrazy, tak aby była odporna na nieprawidłowości w danych wejściowych oraz aby mogła wczytywać wszystkie pliki w formacie PGM zgodne z ustaloną specyfikacją.
  2. Po wykonaniu operacji na obrazie, opracowywany program nie może samoczynnie nadpisywać pliku z wczytanym obrazem. Zapis obrazu wynikowego do pliku następuje po wybraniu odpowiedniej pozycji z menu, która zapyta o nazwę pliku wynikowego.
  3. Przyjmując, że zakres szarości obrazu wejściowego wynosi od 0 do MAX_SZAROSC, zastanowić się nad rozpiętością zakresu szarości w obrazie wynikowym, uzyskanym w efekcie konturowania obrazu według formuły podanej w pliku obrazy_filtry.pdf. Jak można zaradzić zaobserwowanemu zjawisku? Podaj 3 sposoby.

Zadania dodatkowe (dla chętnych)

  1. Wyposażyć program w możliwość wykonywania filtracji obrazu przy użyciu operacji splotu, opisanej w pliku filtrsplot.pdf.
  2. Zmodyfikować funkcje wczytywania i zapisywania obrazu, tak aby zapisując przetworzony obraz, funkcja zapisu umieszczała w nim oryginalne komentarze oraz dodała komentarze informujące o wykonanych operacjach i datach ich wykonania.

Przebieg ćwiczenia

Kolejność realizacji zadań prowadząca w miarę bezboleśnie do celu: Alternatywnie można:

Sprawozdanie

Sprawozdanie powinno zawierać:

Pytania kontrolne

  1. Zapisz deklarację tablicy dwuwymiarowej o rozmiarze 100 na 30. Jak odwołać się do poszczególnych elementów takiej tablicy?
  2. Co spowoduje niezainicjowanie w programie odczyt.c zmiennej odczytano?
  3. Zapisz składnię pętli for. Podaj przykład wypisania za jej pomocą zawartości tablicy dwuwymiarowej.
  4. W jaki sposób można przekazać tablicę dwuwymiarową (MxN) do funkcji?
  5. Jak jest zdefiniowany nagłówek pliku pgm?
  6. Wymień funkcje pozwalające na zapis danych do pliku.
  7. Na co pozwala funkcja fprintf(stderr,...)?
  8. Jakie operacje trzeba wykonać, by wczytać z pliku daną typu int?
  9. Czym się różnią funkcje fgetc od fgets?
  10. Opisz przeznaczenie argumentów funkcji int czytaj(FILE *p,int obraz_pgm[][MAX],int *wymx,int *wymy, int *szarosci) z programu odczyt.c. Ustal jaką wartość ta funkcja zwraca.
  11. W oparciu o jakie instrukcje można łatwo zbudować proste menu użytkownika? Uzasadnij.