Analiza i przetwarzanie obrazów W. 1 – 2007-10-08
Podstawy MatLaba
Znak zachęty >>
porzez ten znak wprowadza się wszystkie wyrażenia w aplikacji.
Podstawowe wyrażenia
Podstawowym wyrażeniem jest przypisanie wartości do zmiennej:
>> a = 20
W tym momencie zainicjowana została zmienna a, która jest macierzą, w tym przypadku o rozmiarze 1x1.
W Matlabie rozróżniana jest wielkość znaków, więc:
>> a = 20;
jest różne od
>> A = 20;
Ogólnie można powiedzieć, że praca w Matlabie polega na pracy z macierzami
– wszystkie dane zapisywane są w różnej postaci, ale zawsze jest to traktowane jako wektor/macierz.
Fakt ten ma wpływ na prawidłowe rozróżnianie stosowanych operatorów.
Wyświetlanie zmiennych w obszarze roboczym Matlaba Możliwość taką umożliwia polecenie
>> whos //bez średnika
Wyświetlane są zmienne wraz z ich rozmiarem oraz typem – typ danych jest istotny na przetwarzanie obrazów.
Wprowadzanie macierzy do programu
Wprowadzanie macierzy przebiega wg schematu:
>> nazwaMacierzy = [war1 war 2 ; war3 war4]
Powstaje wówczas macierz:
⎡
1
war
war 2 ⎤
⎢
⎥
⎣ war 3 war 4⎦
kolumny oddzielamy spacjami bądź przecinkami (przecinek nie jest separatorem dziesiętnym przy liczbach); wiersze oddzielamy średnikiem Ważną rzeczą przy pracy z macierzami w MatLabie jest to, że wiersze i kolumny są liczone od 1 (a nie od 0).
1
Podstawowe manipulacje na macierzach Transpozycja macierzy – stosujemy pojedyńczy apostrof:
>> A = [2 3 ; 4 5]
>> B = A’ // stosujemy apostrof
Obliczenie wyznacznika macierzy – wykorzystujemy funkcję det(M):
>> wznMac = det(A) // w wyniku macierz 1x1
Wyznaczenie macierzy odwrotnej do danej – funkcja inv(M):
>> Aodwr = inv(A) // w wyniku macierz taka jak A, o ile istnieje odwr.
Sumowanie elementów macierzy
Do sumowania używamy funkcji sum(M).
Podstawowa wersja tej komendy zwraca wektor, którego elementami są sumy poszczególnych kolumn:
>> sumy = sum(A) // w wyniku wektor
sumy = 6 8
Redukowanie macierzy (el. Gaussa):
Stosujemy polecenie rref(M):
>> B = rref(A)
B =
1 0
0 1
Konkatenacja macierzy
Ważna możliwość, pozwala łączyć ze sobą macierze – muszą być one zgodne albo ilością wierszy albo ilością kolumn.
Mamy dwie macierze:
⎡1 2⎤
⎡1 2
⎤
A =
B =
3
⎢
⎥
⎢
⎥
⎣3 4⎦
⎣3 4 5⎦
Macierze te są zgodne pod względem ilości wierszy, więc możliwe jest ich skonkatenowanie poziome. Nie możliwa jest konkatenacja pionowa. (różna liczba kolumn)
Konkatenację macierzy wykonuje się w sposób analogiczny do poniższego:
>> LC = [A,B]
Wynik:
⎡1 2 1 2
⎤
3
⎢
⎥
⎣3 4 3 4 5⎦
2
Polega na obróceniu macierzy albo w poziomie – wtedy ostatnia kolumna starej macierzy jest pierwszą kolumną nowej, przedostatnia starej macierzy jest drugą w nowej itd; albo w pionie – tutaj sytuacja jest analogiczna.
Mamy macierz A którą obracamy w poziomie:
>> A = [1 2 3 ; 2 4 6 ; 3 6 9]
⎡1 2 3⎤
⎢
⎥
⎢2 4 6⎥
⎢3 6 9⎥
⎣
⎦
>> obrA = A(3:-1:1)
⎡3 2
⎤
1
⎢
⎥
⎢6 4 2⎥
⎢9 6 3⎥
⎣
⎦
Pamiętać należy, że w przypadku cofania, trzeba podać skok o wartości ujemnej.
OPERATORY ALGEBRY LINIOWEJ
Poniższe operatory stosuje się tak, jak sie stosuje przy działaniach na macierzach (a nie przy działaniach na elementach macierzy – innymi słowy: operatory poniższe muszą spełniać zasady algebry liniowej): Dodawanie:
+
Odejmowanie:
–
Mnożenie:
*
Dzielenie: /
Dzielenie lewostronne: \
Potęgowanie:
^
Transpozycja:
‘
Mamy dwie macierze:
⎡2 3⎤
⎢
⎥
⎡10 11 12⎤
A = 4 5
B =
⎢
⎥
⎢
⎥
⎣12 13 14⎦
⎢6 7⎥
⎣
⎦
W tym wypadku nie powiodą się operacje:
>> X = A + B
>> X = A – B
>> X = A / B
>> X = A \ B
>> X = A^B
3
Jedyna dozwolona operacja to mnożenie – w tym przypadku ilość wierszy w pierwszej macierzy jest równa ilości kolumn w drugiej – zgodnie z zasadami algebry.
Wsystkie operacje są dozwolone na macierzach o równej ilości wierszy i kolumn.
Często jednak zamiast wykonywania operacji na macierzach, potrzebne jest wykonanie operacji na elementach macierzy w sposób naturalny – np. możemy chcieć przemnożyć elementy jednej macierzy przez elementy drugiej.
Do tego celu stosujemy poniższe operatory:
OPERATORY SKALARNE
Dodawanie:
+
// dodawanie sie nie zmienia
Odejmowanie:
–
//
odejmowanie
również
Mnożenie:
.*
Dzielenie: ./
Dzielenie lewostronne: .\
Potęgowanie:
.
Transpozycja:
.‘
Ważne jest, by macierze miały jednakowe wymiary.
Wymnożenie na przykład takich macierzy:
[1]
[2]
[3]
oraz [1 2 3]
nie będzie możliwe, CHYBA ŻE zastosujemy transpozycję do którejś z nich:
>> iloczyn = [1 2 3] .* [1 ; 2 ; 3]’
w wyniku powstaje wektor
iloczyn = [1 4 9]
OPERATOR :
Operator ten jest jednym z podstawowych operatorów.
Stosuje się go do:
1. utworzenia wektora składającego się z określonych elementów:
>> wek1 = 1:5
powstaje wektor:
wek1 = [1 2 3 4 5]
Powstał wektor (wierszowy) składający się z liczb od 1 do 5 ze skokiem domyślnym równym 1.
Aby zmienić skok domyślny, stosujemy dodatkową liczbę: 4
powstaje wektor:
wek2 = [1 1.5 2 2.5 3 3.5 4 4.5 5]
W zapisie tym określiśmy: element początkowy równy 1, wartość skoku 0.5, oraz element końcowy 5.
Idea takiego zapisu: [elPoczątkowy]:[skok]:[elKońcowy]
2. odnoszenia się do elementów macierzy
Bardzo ważne zastosowanie.
Przykładowo, stwórzmy macierz A:
>> A = [2 5 7 ; 4 1 2]
⎡2 5 7⎤
A = ⎢
⎥
⎣4 1 2⎦
W tym momencie odwołanie do poszczególnych elementów macierzy jest proste i polega na wykonaniu instrukcji:
>> wybrany_element = A(i,j) // zwraca skalar Przykład:
>> wybrany_element = A(2,3)
wybrany_element = 2
Odwołujemy się do i-tego wiersza i j-tej kolumny. (w tym przypadku do 2
wiersza i 3 kolumny)
Operator : pozwala na bardziej elastyczne docieranie do danych. Stosując ten operator, możemy np. dostać się do całej kolumny nr 2 w powyższej macierzy:
>> kolumna_dwa = A(:,2) // zwraca wektor wierszowy Wynik:
kolumna_dwa = [5 1]
Co wybraliśmy? Wybraliśmy wszystkie te komórki wierszowe w macierzy A, które znajdują się w kolumnie numer 2.
Analogicznie możemy wybrać cały wiersz drugi, stosując zapis:
>> wiersz_dwa = A(2,:) // zwraca wektor wierszowy Wynik:
wiersz_dwa = [4 1 2]
Operator : pobiera wszystkie komórki (kolumny) znajdujące się w wierszu 2
5
Powyższa wersja operatora : jest podstawowa.
Najczęściej stosujemy ogranicznie – wybieramy, które komórki (licząc od 1) chcemy „wyłuskać”. Stosujemy wówczas zapis:
[od]:[ do]
PRZYPISYWANIE FRAGMENTÓW MACIERZY DO INNYCH MACIERZY
• Macierze dwuwymiarowe
Stwórzmy macierz A o wymiarach 5x5 (za pomocą fukcji magic(M)):
>> A = magic(5)
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
Chcemy teraz do tworzonej macierzy B przypisać część macierzy A określonej następująco:
wiersze (licząc od 1): 3-5
kolumny (licząc od 1): 2-4
Przypisujemy odpowiednią część macierzy A do B – stosujemy zapis [od]:[do]
>> B = A(3:5,2:4) // określiśmy macierz zawierającą 3 wiersze i 3 kolumny Wynik:
⎡6 13 20⎤
⎢
⎥
B = ⎢12 19
⎥
21
⎢18 25 2⎥
⎣
⎦
Ogólna idea posługiwania się takim zapisem:
macierzNowa = macierzStara([wier_od]:[wier_do],[kol_od]:[kol_do]) 1. Należy bacznie zwrócić uwagę na to, ile wierszy i kolumn chcemy
„wydobyć” z macierzy wejściowej.
Zapis 30:60 – wcale nie oznacza wydobycie 30 komórek, tylko 31
komórek, ponieważ 60 komórka też się wlicza w zakres.
• Macierze 3- i więcej wymiarowe
Problem jest tu głównie z terminologią. Jeżeli się pojawiają macierze o takich wymiarach, najlepiej jest wyrobić sobie poniższą notację: macierzNowa = macierzStara([od]:[do],[od]:[do],[od]:[do],...) 6
- piersze [od]:[do]
- przedział w pierwszym wymiarze
- drugie [od]:[do]
- przedział w drugim wymiarze
- trzecie [od]:[do]
- przedział w trzecim wymiarze
- itd.
INNE WARIANTY WYBIERANIA KOMÓREK
Sekcja [od]:[do] oznacza wybranie pewnego zakresu komórek i często jest zapisywany w postaci właśnie takiej (np. 2:5), ale istnieją dodatkowe możliwości:
1. istnieje słowo kluczowe end oznaczające element (wiersz bądź kolumnę) końcowy – dzięki temu w pewnych sytuacjach nie musimy znać końcowego numeru kolumny:
>> nowaMacierz = A(4:end,4:end)
/*
wybieramy nową macierz nie znając numerów końcowych kolumn Wynik:
⎡21 3 ⎤
⎢
⎥
⎣2
9⎦
*/
2. Zapis [od]:[do] obowiązują zasady takie jak przy operatorze : - na przykład można podać skok (całkowity) – wówczas możemy określić, które kolumny chcemy wybrać (co drugą, co trzecią itp):
>> nowaMacierz = A(1:2:end,1:2:end)
/*
wybieramy z macierzy A co drugi wiersz i co drugą kolumnę Wynik:
⎡17 1 15 ⎤
⎢
⎥
⎢4 13 22⎥
⎢11 25 9⎥
⎣
⎦
*/
PRZYPISANIE WARTOŚCI ELEMENTOM MACIERZY
Przypisanie takie wykonuje się w prosty sposób:
>> nazwaMac([od]:[do],[od]:[do],..) = <wartość lub jakaś macierz> 7
OBRAZKI
• Przetwarzane obrazki są dla Matlaba macierzami pikseli – o odpowiednich wymiarach, np 300x100, 256x256.
• Obrazy – macierze typu DOUBLE zawierają piksele o wartości 0 lub 1
• Obrazy – macierze typu UINT8 zawierają piksele o 256 odcieniach szarości (0-255).
• W przypadku DOUBLE – wartości poniżej 0 – są zaokrąglane do 0 (obraz czarny); wartości powyżej 1 – zaokrąglane do 1 (obraz biały)
Podstawowa funkcja do pokazywania obrazków:
>> a = [2 3 5 ; 4 5 1]
>> imshow(a, ‘notruesize’)
/* Wyświetlona macierz będzie biała */
Czasami wywołanie samego imshow może nie zadziałać, wówczas stosuje się dodatkowo funkcję figure. (otwiera okno).
>> figure
>> imshow(...)
Funkcja do otwierania obrazka znajdującego się w pliku na dysku:
>> L = imread(‘ścieżka_do_pliku’) // L – macierz obrazu Na przykład:
>> L = imread(‘cameramon.tiff’)
Operacje na obrazku polegają na odpowiednim manipulowaniu tym obrazkiem będącym macierzą odpowiednich liczb.
Przykład:
Mamy na przykład załadowany obrazek 256x256 8bitowy (UINT8).
Chcemy w określonym obszarze zrobić biały obszar. Posługujemy się wówczas komendą przypisania:
>> L = imread(obrazek)
>> L(100:200,50:150) = 255 [lub odpowiednia macierz]
8
==========
Na ćwiczeniach trzeba będzie:1. otworzyć obrazek (np. zdjęcie z dowodu)
>> L = imread(‘ścieżka’);
2. podzielić ten obrazek na dwie równe pionowe części (A i B)
% Wyznaczenie wysokości i szerokości obrazka
>> [wys, szer, gleb] = size(L)
% Połowa długości
>> srodek = int32(szer / 2);
>> srodek1 = srodek + 1; // nie działa, wymagana wcześniejsza konwersja do double. Od wersji 7.0 ta usterka już nie występuje
% Tworzymy macierze połowy obrazka
>> LA = L(1:wys,1:srodek);
>> LB = L(1:wys,srodek1:end);
% Tworzymy macierze odwrócone
>> odwLA = LA(1:end,end:-1:1);
>> odwLB = LB(1:end,end:-1:1);
3. wyświetlić nowy obrazek składający się z części A starego oraz odwróconej części A starego
% Tworzymy odpowiedni obraz – poprzez konkatenację
>> OBRAZ1 = [LA,odwLA];
% Wywołanie figure
>> figure
% Wyświetlenie obrazka
>> imshow(OBRAZ1,’notruesize’);
4. wyświetlić nowy obrazek składający się z obróconej części B oraz normalnej części B starego obrazka
% Konkatenacja
>> OBRAZ2 = [LB,odwLB];
% Wywołanie figure
>> figure
% Wyświetlenie obrazka
>> imshow(OBRAZ2,’notruesize’);
9
Efekty:
Początkowy obrazek:
49 x 166 px (bez ramek)
Obrazek: A i odwrócony A
(większy obraz - wina przeglądarki Matlaba)
Obrazek: obrócony B i B:
10