Ćwiczenie P-3 „Processing - przetwarzanie obrazów 2D i

Komentarze

Transkrypt

Ćwiczenie P-3 „Processing - przetwarzanie obrazów 2D i
Grafika komputerowa
Ćwiczenie P-3
„Processing przetwarzanie obrazów 2D i renderowanie scen 3D”
Instrukcja laboratoryjna
opracował: mgr inż. Jakub Możaryn
„Człowiek - najlepsza inwestycja”
Projekt współfinansowany przez Unię Europejską
w ramach Europejskiego Funduszu Społecznego
Warszawa 2009
2
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
SPIS TREŚCI
1. Operacje na plikach graficznych............................................................................................. 3
1.1. WYŚWIETLANIE PLIKÓW GRAFICZNYCH - KLASA PImage ......................... 3
1.1.1. Dopasowanie okna do rozmiaru obrazu ............................................................. 3
1.1.2. Modyfikacja nasycenia i przezroczystości obrazu.............................................. 4
1.2. OBRÓBKA OBRAZU – OPERACJE NA PIKSELACH ............................................ 5
1.2.1. Dostęp do pikseli i modyfikacje koloru.............................................................. 7
1.2.2. Interaktywne przetwarzanie obrazu .................................................................... 7
2. Oświetlenie ........................................................................................................................... 11
2.1. ŚWIATŁO OTACZAJĄCE ....................................................................................... 11
2.2. ŚWIATŁO KIERUNKOWE ...................................................................................... 11
2.3. ŚWIATŁO PUNKTOWE ........................................................................................... 11
2.4. ŚWIATŁO SKONCENTROWANE .......................................................................... 12
2.5. DODATKOWE FUNKCJE ZWIĄZANE Z OŚWIETLENIEM ............................... 12
2.6. OŚWIETLANIE SCENY ........................................................................................... 13
3. Nakładanie tekstury .............................................................................................................. 15
3.1. INFORMACJE PODSTAWOWE.............................................................................. 15
3.2. NAKŁADANIE TEKSTURY NA ZŁOŻONY KSZTAŁT....................................... 16
4. Kamera.................................................................................................................................. 18
5. Zadania do samodzielnego wykonania ................................................................................. 19
5.1. ZADANIE – INTERAKTYWNE PRZETWARZANIE OBRAZU, c.d. ................... 19
5.2. ZADANIE – NAKŁADANIE TEKSTURY NA RUCHOME OBIEKTY ................ 20
6. Literatura............................................................................................................................... 20
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
3
1. Operacje na plikach graficznych
1.1. WYŚWIETLANIE PLIKÓW GRAFICZNYCH - KLASA PImage
W Procesingu uproszczono pracę z plikami graficznymi, udostępniając klasę PImage.
Obiekty tej klasy przechowują informacje o plikach graficznych. Klasa PImage obsługuje popularne formaty, t.j. GIF, JPEG, TGA i PNG.
Wyświetlanie pliku graficznego z wykorzystaniem klasy PImage jest stosunkowo proste. Na początku należy dodać plik graficzny do tworzonego projektu. W tym celu wybiera się
z menu głównego opcje Sketch >Add File… . Pozwala to na dodanie pliku danych do projektu
(nie zawsze musi być to plik graficzny, dotyczy to generalnie plików z danymi). Innym sposobem jest wyświetlenie folderu z plikami dodanymi do projektu Sketch > Show Sketch Folder i
przekopiowanie pliku graficznego do katalogu “/data”.
1.1.1. Dopasowanie okna do rozmiaru obrazu
Pierwsza przykładowa aplikacja będzie wyświetlała obraz i dopasowywała okno do jego rozmiaru. Na początku zostanie zadeklarowany obiekt klasy PImage.
Aplikacja 1.1 – deklaracja zmiennych
// Deklaracja obiektu klasy PImage
PImage img;
Następnie, w funkcji inicjującej, obiekt klasy PImage musi zostać skojarzony z wybranym plikiem graficznym z katalogu “/data”. W tym celu należy skorzystać z funkcji
loadImage(), która wywoływana jest z parametrem będącym nazwą pliku.
Img=loadImage(string nazwaPliku)
Rozmiar obrazka można odczytać, korzystając z własności width (szerokość) i height (wysokość) obiektu klasy PImage.
Aplikacja 1.1 – funkcja inicjująca
void setup() {
//przypisanie obiektowi img odpowiedniego pliku graficznego
img = loadImage("Lilie wodne.jpg");
//dopasowanie rozmiaru okna do rozmiaru obrazu
size(img.width,img.height);
};
W ostatnim etapie zostaje do napisania funkcja rysująca. Jest w niej wykorzystana
funkcja image(img,0,0), która rysuje obraz w oknie.
image(PImage img, int/float WspX, int/float WspY)
Parametry WspX, WspY określają współrzędne lewego górnego rogu obrazu oraz położenie
obrazu na ekranie.
Grafika komputerowa
4
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
Aplikacja 1.1 – funkcja rysująca
void draw() {
background(0);
//wyświetlenie obrazu zapisanego w obiekcie img
image(img,0,0);
};
Inną przydatną funkcją zaimplementowaną w Processingu jest CreateImage(), pozwalająca na utworzenie nowego, pustego obrazu.
img=CreateImage(int/float szer, int/float wys, format)
Funkcja CreateImage()wywoływana jest z trzema parametrami: szerokość, wysokość
określającymi rozmiar tworzonego obrazu, oraz informacją o formacie – format.
Zmienna format może przyjmować wartości RGB, ARGB (RGB z kanałem alpha),
ALPHA (skala szarości z kanałem alpha).
1.1.2. Modyfikacja nasycenia i przezroczystości obrazu
Kolejny przykład będzie dotyczył obsługi parametru nasycenia obrazu i parametru alpha (przezroczystość). W aplikacji zostaną nałożone na siebie dwa rożne obrazy. Nasycenie i
przezroczystość jednego z obrazów będą zmieniały się w zależności od położenia kursora
względem okna aplikacji. W ten sposób uzyskany zostanie efekt przenikania dwóch obrazów.
Na początku zostaną zadeklarowane dwa obiekty klasy PImage. Następnie w funkcji
inicjującej jeden z obrazów zostanie potraktowany jako tło, natomiast drugi zostanie wyświetlony jako obraz. Funkcja rysująca pozostaje pusta - nie będą się w niej znajdowały instrukcje.
Aplikacja 1.2 – deklaracja zmiennych, funkcja inicjująca, funkcja rysująca
PImage img1, img2;
void setup() {
img1 = loadImage("Lilie wodne.jpg");
img2 = loadImage("Niebieskie góry.jpg");
size(img1.width,img1.height);
background(img1);
//tło
image(img2,0,0);
//obraz
}
void draw() {}
//pusta funkcja rysująca
Pozostaje do obsłużenia ruch myszy (funkcja mouseMoved()). Do zmiany parametru
nasycenia obrazu img2, oraz parametru odpowiadającego za przezroczystość zostanie wykorzystana funkcja tint(). Funkcja ta określa sposób wyświetlania pikseli na ekranie. Wywoływana może być z różną liczbą parametrów (jeden – przezroczystość; dwa – nasycenie i
przezroczystość; pięć – wartości kanałów RGB, nasycenie i przezroczystość ).
tint(int/float argR, int/float
int/float alpha);
argG,
int/float
argB,
int/float
intens,
W tworzonej aplikacji przezroczystość i nasycenie zależy od położenia kursora wobec
okna z programem. Współrzędna X położenia kursora wpływa na wartość parametru intensywności obrazu img2, natomiast współrzędna Y położenia kursora wpływa na wartość parametru przezroczystości obrazu img2.
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
5
Aplikacja 1.2 – obsługa zdarzenia związanego z ruchem kursora
void mouseMoved(){
background(img1);
tint(round(mouseX*255/width), round(mouseY*255/height));
image(img2,0,0);
};
Rysunek 1.1. Okno aplikacji 1.2 , przenikanie dwóch rysunków
1.2. OBRÓBKA OBRAZU – OPERACJE NA PIKSELACH
W przypadku kiedy w programie wymagany jest dostęp do poszczególnych pikseli obrazka, należy skorzystać z dwóch funkcji, loadPixels() i updatePixels().
Funkcja loadPixels(), wywołana dla danego obrazka, zapisuje informację o kolorze poszczególnych pikseli do wektora o nazwie pixels[]. Można się odwołać do pikseli
ekranu (tła) lub do pikseli obiektu będącego obrazkiem.
Ekran (tło)
pixels[1]=c;
Obrazek
img.pixels[1]=c;
W Processingu położenie każdego piksela jest podawane jako liczba całkowita, obliczana wg. następującej zależności.
położenie=x + szerokość_okna*y;
(1)
Przykładowo dostęp do piksela [10, 10] na oknie o szerokości 200, jest następujący
pixels[x+200*y]=c;
Po zakończeniu pracy z pikselami należy wywołać funkcję updatePixels(). Tylko
wtedy zmiany zostaną zapisane.
Operacje na poszczególnych pikselach wymagają modyfikacji różnych parametrów
m.in. składowych barw RGB, przezroczystości, intensywności. W języku Processing umożli-
Grafika komputerowa
6
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
wiono zaawansowaną obsługę własności poszczególnych pikseli i określenie ich koloru, udostępniając typ danych o nazwie color, który przechowuje wartości związane z określonym
kolorem. Każdy element wektora pixels[] jest zmienną typu color. Kolory mogą być
ustawione z wykorzystaniem funkcji get(), color(), lub określone w postaci heksadecymalnej np. #FFCC00 lub 0xFFFFCCOO. Przydatne funkcje związane z określaniem koloru zostały zebrane w tabeli 1.1.
W tabeli 1.1 opisano funkcję get(), która oprócz odczytania wartości koloru wybranego piksela pozwala na wybranie całego fragmentu obrazu. W przypadku odczytywania koloru piksela należy podać jego współrzędne. Jeśli wybierany jest fragment obrazu należy podać współrzędne jego górnego lewego rogu, oraz szerokość i wysokość.
Odczytanie koloru piksela
color cp;
cp=get(10,10);
Wybór fragmentu obrazu
PImage img;
img=get(10,10,300,300);
Tabela 1.1. Funkcje związane z określeniem i modyfikacją koloru
Opis
Funkcja
hex(color c);
red(color);
green(color c);
blue(color c);
Konwertuje wartość typu byte, char, int, color na łańcuch
znaków w notacji heksadecymalnej.
Odczytanie rzeczywistych wartości składowych RGB ze zmiennej
typu color podawanej jako parametr
Odczytuje rzeczywistą wartość odcienia ze zmiennej typu color
podawanej jako parametr.
Odczytuje rzeczywistą wartość nasycenia ze zmiennej typu
saturation(color c);
color podawanej jako parametr.
Odczytuje rzeczywistą wartość jasności ze zmiennej typu color
brightness(color c);
podawanej jako parametr.
Odczytuje kolor danego piksela, w tym wypadku zwraca zmienną
get();
typu color. Parametrami są wartości x i y położenia piksela na
obrazie.
Generuje kolor zwracając zmienną typu color. Parametry
color c=color();
interpretowane są jako wartości kanałów RGB lub HSB, w
zależności od ustawionego trybu wyświetlania kolorów.
colorMode();
Ustawienie trybu wyświetlania kolorów.
hue(color c);
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
7
1.2.1. Dostęp do pikseli i modyfikacje koloru
Sposób dostępu do poszczególnych pikseli obrazu i modyfikacji ich własności zostanie
pokazany na przykładzie aplikacji służącej do prostej obróbki obrazu.
Na początku zostanie zadeklarowany obiekt klasy PImage. W funkcji inicjującej zostanie przypisany mu odpowiedni rysunek, do którego dopasowane zostanie okno programu.
Aplikacja 1.3. – deklaracja zmiennych i funkcja inicjująca
PImage img;
void setup() {
img = loadImage( "Lilie wodne.jpg");
size(img.width,img.height);
noLoop();
};
Funkcja rysująca będzie wybierała poszczególne piksele z obrazu i przenosiła je na tło okna. Z
każdego piksela wartości składowych RGB zostaną odczytane z wykorzystaniem funkcji
red(), green(), blue(). Następnie dla każdego piksela zostaną wyzerowane składowe barwy zielonej i niebieskiej.
Aplikacja 1.3. – funkcja rysująca
void draw() {
loadPixels();
//inicjacja pikseli ekranu
img.loadPixels();
//inicjacja pikseli obrazu
for (int y=0; y<height; y++ ) {
for (int x=0; x<width; x++ ) {
int loc = x + y*width;
//połoŜenie piksela na obrazie
// algorytm przetwarzania obrazu, odczytanie wartości składowych RGB dla
// kaŜdego z pikseli obrazu
float r = red(img.pixels [loc]);
float g = green(img.pixels[loc]);
float b = blue(img.pixels[loc]);
pixels[loc] = color(r,0,0);
//wyświetlenie pikseli, składowa r
};
};
updatePixels();
//przeniesienie zmian na ekran
};
1.2.2. Interaktywne przetwarzanie obrazu
Możliwość łatwego zaprogramowania interakcji z użytkownikiem pokazuje istotę
praktycznego zastosowania Processingu. Kolejny przykład będzie dotyczył interaktywnej obróbki obrazu.
Zadaniem jest napisanie programu, który będzie wgrywał określone zdjęcie na ekran i
dokonywał przetworzenia wybranego przez użytkownika fragmentu. Na wybrany fragment
zostanie nałożony prosty filtr operujący na pikselach i pozwalający na wykrywanie krawędzi.
Grafika komputerowa
8
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
Na początku zostaną zadeklarowane dwa obiekty klasy PImage. Jeden z nich należy
skojarzyć z plikiem graficznym, na którym będziemy dokonywać przekształceń. Rozmiar
okna zostanie dopasowany do rozmiaru obrazka.
Aplikacja 1.4. – deklaracja zmiennych, funkcja inicjująca i funkcja rysująca
PImage img,img2;
void setup() {
img = loadImage( "Lilie wodne.jpg");
size(img.width,img.height);
};
void draw() {};
Następnie zostanie obsłużone zdarzenie związane z ruchem kursora. Z kursorem zostanie powiązany prostokąt – okno, w którym będzie nałożony odpowiedni filtr i którego położenie będzie zmieniało się wraz z ruchem kursora.
Aplikacja 1.4. – obsługa zdarzenia związanego z ruchem kursora
void mouseMoved(){
background(img);
int WspX=mouseX;
int WspY=mouseY;
stroke(255,0,0);
noFill();
strokeWeight(2);
rect(mouseX-25,mouseY-25,150,150); //rysowanie prostokąta
};
Kolejne obsłużone zdarzenie będzie związane z naciśnięciem klawisza myszy. Zgodnie z postawionym zadaniem, po naciśnięciu przycisku na wybranym fragmencie obrazu zostanie dokonanie przetworzenie pikseli - filtracja. W tym celu zostanie zdefiniowana funkcja
przetworzObraz(), do której będą przekazywane współrzędne górnego lewego rogu zaznaczonego fragmentu oraz jego szerokość i wysokość. Po przetworzeniu obrazu w zaznaczonym miejscu zostanie wyświetlony zmodyfikowany fragment.
Aplikacja 1.4. – obsługa zdarzenia związanego z naciśnięciem klawisza myszy
void mousePressed(){
int WspX=mouseX;
int WspY=mouseY;
stroke(255,0,0);
noFill();
strokeWeight(2);
przetworzObraz(WspX-25,WspY-25,150,150);
image(img2,WspX-25,WspY-25);
rect(mouseX-25,mouseY-25,150,150);
};
Funkcja przetworzObraz() składa się z następujących zbiorów instrukcji. Najpierw
z obiektem img2 zostanie powiązany pusty obszar o rozmiarze identycznym z rozmiarem
przetwarzanego fragmentu obrazu i pikselach wyświetlanych w formacie RGB. Następnie zostaną załadowane piksele obydwu obrazów img2 i img1. W dwóch zagnieżdżonych pętlach
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
9
for zostaną przetworzone i przepisane zmodyfikowane piksele z obiektu img1 do obiektu
img2. Ostatecznie zmiany pikseli drugiego obrazka (img2) zostaną utrwalone przy pomocy
funkcji updatePixels().
Poszczególne piksele w wybranym fragmencie zostaną zmodyfikowane. Najpierw zostanie wybrany piksel i piksel sąsiadujący z nim z lewej strony. Z każdego z nich można odczytać wartość jasności korzystając z funkcji brightess(), a następnie nadać pierwszemu
wybranemu pikselowi wartość koloru będącą wartością bezwzględną różnicy pomiędzy jego
jasnością a jasnością najbliższego piksela z lewej strony. W ten sposób można łatwo wykryć
pionowe krawędzie, ponieważ pomiędzy pikselami znajdującymi się na krawędzi występują
największe różnice jasności.
Aplikacja 1.4. – funkcja do przetwarzania obrazu
void przetworzObraz(int imgx, int imgy, int imgw,int imgh){
img2=createImage(imgw,imgh,RGB);
img.loadPixels();
img2.loadPixels();
for (int y=imgy; y<imgy+imgh; y++ ) {
for (int x=imgx; x<imgx+imgw; x++ ) {
int loc=x+y*img.width;
int loc2=x-imgx+(y-imgy)*imgw;
//filtr –wykrywanie krawędzi
color pix=img.pixels[loc];
int leftLoc=(x-1)+y*img.width;
color leftPix = img.pixels[leftLoc];
float diff = abs(brightness(pix) - brightness(leftPix));
img2.pixels[loc2] = color(diff);
};};
img2.updatePixels();
};
Przedstawiony przykład jest bardzo prosty. Jednak korzystając z tej metody można zaprojektować bardziej złożone metody filtracji obrazu. Wykorzystywane są wtedy informacje
zawarte w większej liczbie sąsiadujących pikseli (Rys. 1.2), zaś wartości składowych koloru
piksela są funkcją wartości składowych kolorów pikseli znajdujących się wokół niego.
Rysunek 1.2. Położenie pikseli obrazu i ich współrzędne w wektorze pixels[]
Grafika komputerowa
10
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
W Processingu możliwe jest też zastosowanie predefiniowanych metod przetwarzania
obrazu, które można wywołać stosując funkcję
filter(MODE)
filter(MODE, level)
Parametr MODE mówi o sposobie filtracji (tabela 1.2), zaś parametr level odpowiada za jakość filtracji i może przyjmować wartości rzeczywiste lub całkowite.
Rysunek 1.3. Okno aplikacji 1.4 (interaktywne przetwarzanie obrazu)
Tabela 1.2. Wartości parametru MODE i opis sposobu przetwarzania obrazu.
Wartość
Opis
THRESHOLD
Konwertuje rysunek do czarnych i białych pikseli, w zależności od tego czy
wartości koloru znajdują się powyżej czy poniżej granicy, określonej przez
parametr level. Wartość tego parametru powinna znajdować się pomiędzy
0.0 (czarny) a 1.0 (biały), standardowa wartość to 0.5.
GRAY
Konwertuje kolory do odpowiadających im kolorów w skali szarości.
INVERT
Odwraca wartości barw składowych.
POSTERIZE
Ogranicza wartości kanałów w obrazie do liczby kolorów określonej przez
parametr level.
BLUR
Dokonuje rozmycia gaussowskiego. Parametr level określa rozmiar rozmycia,
standardowo ustawiony jest na 1.
OPAQUE
Ustawia kanał alpha na całkowitą przezroczystość.
ERODE
Zmniejsza jasne obszary o wartość podawaną jako parametr level.
DILATE
Powiększa jasne obszary o wartość podawaną jako parametr level.
Filtry wywoływane przy pomocy funkcji filter() stosowane są do całego obrazka
wyświetlanego na ekranie z wykorzystaniem funkcji image(). Filtrację najlepiej wykonywać
od razu po wyświetleniu obrazka.
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
11
2. Oświetlenie
W Processingu umożliwiono określenie oświetlenia sceny trójwymiarowej. Wszystkie
funkcje z nim związane należy umieścić w funkcji rysującej, ponieważ oświetlenie jest inicjowane podczas każdego wywołania funkcji draw().
Podstawowa funkcja, lights(), ustawia domyślne wartości oświetlenia, tj. światło
otaczające ( ambientLight(128,128,128) ), światło kierunkowe ( directionalLight(128, 128, 128, 0, 0, -1) ), ogólny kształt stożka światła ( falloff(1, 0,
0) ) oraz połysku ( specular(0, 0, 0) ).
Całe oświetlenie sceny można wyłączyć, korzystając z funkcji noLights().
2.1. ŚWIATŁO OTACZAJĄCE
Światło otaczające wypełnia równomiernie całą wyświetlaną scenę. Promienie padają
ze wszystkich kierunków. Należy je wykorzystywać z innymi źródłami światła. Światło otaczające definiuje się przy pomocy funkcji ambientLight().
ambientLight(R, G, B)
Parametry tej funkcji to wartości składowych RGB, określających barwę światła. Wszystkie
parametry mogą być typu int lub float.
2.2. ŚWIATŁO KIERUNKOWE
Światło kierunkowe pada z określonego kierunku. Powierzchnie, na które padają promienie pod kątem prostym są silniej oświetlone, natomiast jeśli kąt jest większy, to oświetlenie jest słabsze. Promienie odbijają się we wszystkich kierunkach od powierzchni, na którą
padają. Światło kierunkowe definiuje się przy pomocy funkcji directionalLight().
directionalLight(R, G, B, nx, ny, nz)
Parametry tej funkcji to wartości składowych RGB, oraz nx, ny, nz – współrzędne określające kierunek źródła światła (nz = -1 oznacza, że światło pada z dołu sceny). Wszystkie
parametry mogą być typu int lub float.
2.3. ŚWIATŁO PUNKTOWE
Światło punktowe pada z określonego punktu sceny. Światło punktowe definiuje się
przy pomocy funkcji pointLight().
pointLight(R, G, B, x, y, z)
Parametry tej funkcji to wartości składowych RGB, x, y, z – współrzędne źródła światła.
Wszystkie parametry mogą być typu int lub float.
Grafika komputerowa
12
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
2.4. ŚWIATŁO SKONCENTROWANE
Światło skoncentrowane pada z określonego punktu sceny, w określonym kierunku.
Światło skoncentrowane definiuje się przy pomocy funkcji spotLight().
spotLight(int/float R, int/float G, int/float B, int/float x, int/float y,
int/float z, int/float nx, int/float ny, int/float nz, float kąt,
float koncentracja)
Parametry tej funkcji to odpowiednio wartości składowych RGB, x, y, z – współrzędne
źródła światła, nx, ny, nz – wartości określające kierunek rozchodzenia się światła,
kąt – kąt rozwarcia stożka światła, koncentracja – wartość określająca intensywność źródła światła.
2.5. DODATKOWE FUNKCJE ZWIĄZANE Z OŚWIETLENIEM
W Processingu zaimplementowano kilka dodatkowych funkcji związanych z własnościami oświetlenia. Część dotyczy własności źródła światła (tabela 2.1.), natomiast pozostałe
dotyczą własności powierzchni, na którą pada światło (tabela 2.2.).
Tabela 2.1. Funkcje związane z oświetleniem
Funkcja
Opis
lightFalloff()
Przy pomocy tej funkcji można ustawić trzy współczynniki określające
kąt stożka światła w miejscu wygaszenia promieni. Dotyczy światła otaczającego, punktowego i skoncentrowanego.
lightSpecular() Funkcja określa kolor odbijanego światła i zależy od własności odbijających materiału. Wywoływana jest z trzema parametrami określającymi
wartości składowych RGB.
Tabela 2.2. Funkcje związane z własnościami materiału
Funkcja
ambient()
specular()
emissive()
shininess()
Opis
Funkcja określająca stopień pochłaniania promieni o określonych własnościach. Wywoływana może być z różną liczbą parametrów (zwykle
trzema, określającymi wartości składowych RGB).
Funkcja określa kolor materiału zależny od kierunku światła. Wywoływana może być z różną liczbą parametrów (zwykle czterema, określającymi wartości składowych RGB i przezroczystość powierzchni). Pozwala
uzyskać efekt podświetlenia
Funkcja określa kolor światła emitowanego przez materiał. Wywoływana
może być z różną liczbą parametrów (zwykle trzema, określającymi wartości składowych RGB).
Funkcja określa ilościowo połysk materiału. Wywoływana jest z jednym
parametrem.
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
13
2.6. OŚWIETLANIE SCENY
Kolejny przykład służy do zobrazowania, w jaki sposób można oświetlić scenę. Dodatkowo zostanie pokazane jak tworzyć trójwymiarowe bryły definiując ich wierzchołki i boki.
Na początku zostanie zainicjowane okno wraz z odpowiednim silnikiem 3D (P3D).
Aplikacja 2.1. – funkcja inicjująca
void setup(){
size(800,400,P3D);
};
Działanie funkcji draw() jest następujące. W środku okna w trzech wymiarach rysowany jest ostrosłup o podstawie kwadratu, obrócony o 30 stopni wokół każdej z osi. Oświetlenie bryły zależy od położenia kursora myszy. W funkcji rysującej zostanie określone światło otaczające, o wartościach składowych R=128, G=128, B=128. Następnie zostaną odczytane współrzędne kierunkowe światła (dirX, dirY) zależne od położenia kursora, przeskalowane do zakresu [-1…1] i określone zostanie światło kierunkowe o wartościach składowych
R=204, G=204, B=204.
Dalsze instrukcje dotyczą przesunięcia układu współrzędnych do środka okna i dokonania obrotów wokół każdej osi o 30 stopni. Ostatecznie wywołana jest funkcja rysujOstroslup(), która rysuje ostrosłup o podstawie kwadratu i czterech bokach będących trójkątami.
Aplikacja 2.1. – funkcja rysująca
void draw(){
background(0,0,0);
ambientLight(128,128,128);
float dirY = (mouseY / float(height) - 0.5) * 2;
float dirX = (mouseX / float(width) - 0.5) * 2;
directionalLight(204, 204, 204, -dirX, -dirY, 1);
translate(width/2,height/2);
rotateX(radians(30));
rotateY(radians(-30));
rotateZ(radians(30));
rysujOstroslup();
};
W funkcji rysujOstroslup()wykorzystano bloki beginShape … endShape() (opisane
w podrozdziale 3.3), które definiują boki rysowanej bryły na podstawie podanych współrzędnych wierzchołków.
Grafika komputerowa
14
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
Aplikacja 2.1. – funkcja rysujOstroslup()
void rysujOstroslup(){
fill(255,0,0);
noStroke();
beginShape(QUADS);
vertex( 100, 0, 100);
vertex( 100, 0, -100);
vertex(-100, 0, -100);
vertex(-100, 0, 100);
endShape();
beginShape(TRIANGLES);
//rysowanie boku 1
vertex(-100, 0, 100);
vertex( 100, 0, 100);
vertex(0, -150, 0);
//rysowanie boku 2
vertex(100, 0, 100);
vertex(100, 0, -100);
vertex(0, -150, 0);
//rysowanie boku 3
vertex(-100, 0, -100);
vertex( 100, 0, -100);
vertex(0, -150, 0);
//rysowanie boku 4
vertex(-100, 0, -100);
vertex(-100, 0, 100);
vertex(0, -150, 0);
endShape();
}
// rysowanie podstawy
Rysunek 2.1. Okno aplikacji 2.1.
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
15
3. Nakładanie tekstury
3.1. INFORMACJE PODSTAWOWE
W Processingu istnieje możliwość nakładania tekstury na zdefiniowane kształty. Dotyczy to kształtów utworzonych z wierzchołków w blokach definiujących nowe kształty (beginShape()…endShape() – podrozdział 3.3) .
Tekstura jest fragmentem obrazu nałożonym na dany kształt. Obraz powinien być dodany do programu przed nałożeniem tekstury i skojarzony z obiektem klasy PImage. Do skojarzenia obrazu z teksturą należy wykorzystać funkcję texture().
texture(PImage img);
gdzie img jest obiektem klasy PImage przechowującym dane o obrazie nakładanym jako
tekstura.
Wywołanie tej funkcji powinno znaleźć się wewnątrz bloku definiującego nowe
kształty beginShape() … endShape(), przed instrukcjami definiującymi wierzchołki. W
przypadku nakładania tekstury kolor wypełnienia zdefiniowanego kształtu jest ignorowany.
Zamiast tego stosowana może być funkcja tint() określająca kolor nakładanej tekstury.
Nałożenie tekstury na określoną powierzchnię zależy od dwóch dodatkowych parametrów podawanych przy definiowaniu wierzchołków z wykorzystaniem funkcji vertex()
(funkcja opisana w instrukcji 2).
vertex(x, y, z, ox, oy)
Dodatkowe parametry ox i oy określają w pikselach położenie na obrazie, nakładanym jako
tekstura, punktu przyporządkowanego danemu wierzchołkowi. Położenie punktu jest określone względem górnego, lewego rogu obrazu. Wszystkie parametry mogą być typu int lub
float.
Po zdefiniowaniu wierzchołków i odpowiadających im punktów obrazu, wybrany
fragment zostanie rozciągnięty na zadanej powierzchni.
Możliwe jest nakładanie tekstury w dwóch trybach określanych przy pomocy dyrektywy textureMode().
textureMode(TRYB)
Parametr TRYB może przyjmować wartości IMAGE lub NORMALIZED.
Domyślnym trybem jest IMAGE. W tym przypadku współrzędne punktów obrazu, nakładanego jako tekstura, podawane są w pikselach. Na przykład mając obraz o rozmiarach
100 × 200 pikseli i nakładając go w całości na powierzchnię prostokątną podawane punkty
będą miały współrzędne (0,0),(0,100),(100,200),(0,200).
Drugi tryb to NORMALIZED, który normalizuje rozmiar obrazu do współrzędnych z zakresu (0,1). Tak więc współrzędne punktów przykładowego obrazu będą następujące:
(0,0),(0,1),(1,1),(0,1).
Grafika komputerowa
16
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
3.2. NAKŁADANIE TEKSTURY NA ZŁOŻONY KSZTAŁT
Kolejna aplikacja służy do pokazania, jak można nakładać teksturę na złożony kształt.
Działanie programu jest następujące. W środku okna w trzech wymiarach jest rysowany
ostrosłup o podstawie trójkąta z nałożoną na każdy z boków teksturą. Sposób ustawienia bryły
względem okna będzie zależał od ruchu myszy.
Na początku zadeklarowano cztery obrazy, z których każdy będzie się pokazywał na
poszczególnych bokach bryły. Następnie zadeklarowano zmienne określające położenie układu współrzędnych, który będzie się zmieniał wraz z ruchem kursora po ekranie.
Aplikacja 3.1. – deklaracja zmiennych.
//deklaracja zmiennych przechowujących 4 obrazy nakładane jako tekstura
PImage img1,img2,img3,img4;
//deklaracja zmiennych związnych z połoŜeniem i sterowaniem ruchem bryły
float rotX = 0.0, rotY = 0.0;
int ostX, ostY;
float distX = 0.0, distY = 0.0;
W funkcji inicjującej określono rozmiary okna oraz silnik 3D. Następnie przyporządkowano każdemu obiektowi klasy PImage odpowiednie obrazy. Wcześniej muszą być one
dodane do folderu aplikacji. Ostatnia linijka mówi, że współrzędne obrazów nakładanych jako
tekstura będą znormalizowane.
Aplikacja 3.1. – funkcja inicjująca
void setup(){
size(800,400,P3D);
img1=loadImage("Lilie wodne.jpg");
img2=loadImage("Niebieskie gory.jpg");
img3=loadImage("Zachod slonca.jpg");
img4=loadImage("Zima.jpg");
textureMode(NORMALIZED);
};
Funkcja rysująca składa się instrukcji określających wygląd okna programu oraz określających położenie układu współrzędnych. Wartości podawane jako parametry funkcji
rotateX() i rotateY() zależą od położenia kursora na ekranie.
Ostrosłup z nałożoną teksturą jest rysowany z wykorzystaniem funkcji rysujOstroslupTekstura(). Na każdy z boków nakładany jest fragment innego obrazu. Ponieważ w bloku definicji nowego kształtu nakładana jest tylko tekstura określona przy pierwszym wywołaniu funkcji texture(), każdy z boków musi być zdefiniowany oddzielnie.
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
17
Aplikacja 3.1. – funkcja rysująca
void draw(){
background(255,255,255);
noStroke();
translate(width/2,height/2); //przesunięcie bryły na środek okna
rotateX(rotX+distY);
//obrót bryły wokół osi OX
rotateY(rotY+distX);
//obrót bryły wokół osi OY
rysujOstroslupTekstura();
};
Aplikacja 3.1. – funkcja rysujOstroslupTekstura()
void rysujOstroslupTekstura(){
beginShape(TRIANGLES);
//rysowanie podstawy
texture(img1);
vertex( 100, 0, 100,0,0);
vertex( 100, 0, -100,0,1);
vertex(-100, 0, -100,1,1);
endShape();
beginShape(TRIANGLES);
//rysowanie boku 1
texture(img2);
vertex( 100, 0, 100,0,0);
vertex( 100, 0, -100,0,1);
vertex(0, -150, 0,1,1);
endShape();
beginShape(TRIANGLES);
//rysowanie boku 2
texture(img3);
vertex(100, 0, -100,0,0);
vertex(-100, 0, -100,0,1);
vertex(0, -150, 0,1,1);
endShape();
beginShape(TRIANGLES);
//rysowanie boku 3
texture(img4);
vertex(-100, 0, -100,0,0);
vertex( 100, 0, 100,0,1);
vertex(0, -150, 0,1,1);
endShape();
};
//określenie tekstury
//określenie tekstury
//określenie tekstury
//określenie tekstury
Ostatecznie zostaną zaprogramowane funkcje związane z ruchem myszy. W przypadku naciśnięcia klawisza myszy (mousePressed()) zapamiętane jest położenie kursora. Podczas ruchu kursora z wciśniętym klawiszem myszy (mouseDragged()) zmieniane są wartości kątów obrotu bryły. Zwolnienie klawisza (mouseReleased()) blokuje obraz.
Grafika komputerowa
18
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
Aplikacja 3.1. – funkcje obsługujące zdarzenia związane z ruchem myszy
void mousePressed(){
ostX = mouseX;
ostY = mouseY;
}
void mouseDragged(){
distX = radians(mouseX - ostX);
distY = radians(ostY - mouseY);
}
void mouseReleased(){
rotX += distY;
rotY += distX;
distX = distY = 0.0;
}
Rysunek 3.1. Okno aplikacji 3.1.
4. Kamera
W Processingu umożliwiono ustawienie kamery i określenie punktu, z którego obserwowana jest dana scena. W tym celu należy skorzystać z funkcji camera().
camera(int/float eyeX, int/float eyeY, int/float eyeZ, int/float centerX,
int/float centerY, int/float centerZ, upX, upY, upZ)
Parametrami tej funkcji są eyeX, eyeY, eyeZ – współrzędne położenia obserwatora, centerX, centerY, centerZ – współrzędne położenia centrum sceny, upX, upY, upZ –
określenie, która oś skierowana jest w górę sceny (wartości 0, 1, -1).
Zmiana powyższych parametrów pozwala na ruch obserwatora względem sceny. Domyśle ustawienia kamery, obowiązujące jeśli nie podano żadnych parametrów, są następujące:
camera(width/2.0, height/2.0, (height/2.0) / tan(PI*60.0 / 360.0),
width/2.0, height/2.0, 0, 0, 1, 0)
W Processingu umożliwiono także zaawansowane zarządzanie położeniem kamery,
przy pomocy bloku beginCamera()…endCamera(). Bloki te nie mogą być zagnieżdżane.
Grafika komputerowa
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
19
Blok beginCamera()…endCamera()umożliwia zastosowanie transformacji (instrukcje
translate(), rotate()) do kamery a nie obiektów na scenie.
Funkcje związane z kamerą anulują wykonane wcześniej funkcje związane z przemieszczeniem układu współrzędnych. Z tego powodu najpierw należy ustawić kamerę (blok
beginCamera()…endCamera()), a dopiero późnej dokonywać transformacji obiektów na
scenie korzystając ze stosu macierzy przekształceń.
5. Zadania do samodzielnego wykonania
5.1. ZADANIE – INTERAKTYWNE PRZETWARZANIE OBRAZU, c.d.
Treść zadania:
Podczas omawiania operacji na plikach graficznych zaproponowano aplikację do interaktywnej obróbki obrazu (podrozdział 2.4). Kolejnym zadaniem do samodzielnego wykonania będzie uzupełnienie tej aplikacji o:
• samodzielne zdefiniowanie rozmiaru okna, w którym dokonywane jest przekształcenie
obrazu,
• wykorzystanie trzech filtrów wyświetlających poszczególne składowe RGB występujące w zaznaczonym fragmencie.
• wykorzystanie dwóch wybranych filtrów wywoływanych przy pomocy funkcji
filter().
Przydatne informacje:
Do narysowania okna, w którym znajduje się przetwarzany fragment obrazu wystarczy
zmieniać położenie lewego górnego rogu (określającego położenie obrazu) i prawego dolnego
rogu (określającego szerokość i wysokość okna). Do blokowania i odblokowywania punktów
zaznaczanego obszaru można skorzystać z funkcji związanych z obsługą wciśnięcia klawisza
myszy i ruchu kursora opisanych w programie do zmiany kształtu krzywych Beziera (instrukcja nr 2).
Odpowiednie składowe RGB koloru można odczytać korzystając z funkcji red(),
green(), blue()(tabela 1.1). Wybór odpowiedniego filtru można określić korzystając
z klawiszy. Funkcje związane z obsługa klawiatury i sprawdzeniem, który klawisz został
wciśnięty zostały opisane w instrukcji 1.
Podczas wykonywania operacji z wykorzystaniem funkcji filter() przydatne może
być użycie funkcji get() do skopiowania odpowiedniego fragmentu obrazka.
Grafika komputerowa
20
Ćwiczenie P-3
Przetwarzanie obrazów 2D i renderowanie scen 3D
5.2. ZADANIE – NAKŁADANIE TEKSTURY NA RUCHOME OBIEKTY
Treść zadania:
Należy napisać aplikację nakładającą różne tekstury na dwa sześciany poruszające się w przestrzeni.
• Sześcian pierwszy porusza się po „orbicie” wokół środka ekranu.
• Drugi sześcian porusza się po „orbicie” wokół pierwszego sześcianu.
Obydwa sześciany obracają się w trzech osiach z różnymi prędkościami.
Rysowanie każdego sześcianu należy zrealizować przy pomocy uniwersalnej funkcji o następującym nagłówku
void szescian(float bok,PImage tekstura)
gdzie bok - długość jednego boku sześcianu, tekstura – obrazek nakładany jako tekstura na
każdy z boków.
6. Literatura
[1] Bożena Pawlak “Processing – nowe narzędzie do tworzenia apletów. Analiza możliwości
na przykładzie apletów z dziedziny grafiki komputerowej”, Praca dyplomowa inżynierska,
Wydział Mechatroniki, 2005/2006.
[2] Ira Greenberg: ”Processing: Creative Coding and Computational Art”, Friendsof, 2007.
[3] Casey Reas, Ben Fry, „Processing: A Programming Handbook for Visual Designers
and Artists”, MIT Press, 2007.
[4] Daniel Shiffman: “Learning Processing. A Beginners Guide to Programming Images,
Animation and Interaction”, Elsevier, 2008.
[5] Pomoc środowiska Processing.
Grafika komputerowa

Podobne dokumenty