Lekce 3 - Práce s maticemi a vektory
Způsob práce s vektory a maticemi v MATLABu je natolik zásadní téma, že je rozděleno do třech lekcí. Informace v jednotlivých částech se překrývají a pokaždé jsou podány trochu jiným způsobem. Umožní tak nahlédnout do problematiky z různých úhlů.
V této části si vysvětlíme indexování a práci s buňkami. Druhá část se dopodrobna zabývá tvorbou vektorů, přístupem k jednotlivým prvkům a jejich filtrováním. Podobná témata jsou vysvětlena v třetí části, pouze s pomocí matic a na praktické ukázce úpravy fotografie.
Indexování v MATLABu
Pro začátečníky - index je jednoznačná pozice hodnoty v poli, v našem případě v matici, a je tedy reprezentován pozicí na řádku a ve sloupci.
Pro ty již políbené múzou programovacích jazyků je v MATLABu velký rozdíl v zápisu indexace. V céčkových jazycích se pro zápis indexů používají hranaté závorky, nicméně v MATLABu se pro indexování používají závorky kulaté a nebo také složené. Rozdíl je popsán níže.
Indexování v maticích a vektorech
Pro indexování v maticích se používají kulaté závorky. V případě matic se uvádí do závorek vždy čísla v pořadí řádek, sloupec, vrstva, rozměr4, ... Jedná-li se o vektor, stačí do závorek uvést pouze jedno číslo.
M = [1, 2, 3; 4, 5, 6; 7, 8, 9]; V = [10, 20, 30]; M(2,3) V(2)
Výstupem budou hodnota 6
pro matici M
a
hodnota 20
pro vektor V
.
Buňky (cells)
Buňky jsou speciálními maticemi, které v sobě dokáží nést hodnoty různých datových typů. Ovšem nejčastěji se s nimi v MATLABu člověk potká při práci s vektory textových řetězců. Jelikož je textový řetězec vektor znaků, není možné vytvořit souvislou matici řetězců o pevně daných rozměrech, protože by jinak musely všechny řetězce mít stejnou délku. Ovšem kdyby délka byla stejná, vytvořila by se nám matice znaků, ale ne matice řetězců.
Buňka se definuje podobně jako matice s tím rozdílem, že se namísto hranatých závorek používají závorky složené. Pak již pravidla pro řádky a sloupce platí stejná. Hodnoty ve sloupcích jsou odděleny mezerou či čárkou a hodnoty na řádcích jsou odděleny středníky.
M = ['abcd'; 'efgh']; % Matice znaků C = {'Ahoj'; 'Nazdar'}; % Buňka s textovými řetězci různých délek D = {'Ahoj', 2; .5, true}; % Buňka s různými datovými typy
Indexování v buňkách (cells)
Při indexování buněk se používají jak závorky kulaté, tak závorky složené, ovšem pak už je indexace opět stejná jako u matic. Rozdílem je návratová hodnota po indexaci.
Pokud budeme indexovat v kulatých závorkách, bude nám navrácena opět buňka. Pokud budeme indexovat ve složených závorkách, bude navrácena hodnota v datovém typu uloženém v buňce na daném indexu.
A to je velmi značný rozdíl, protože pokud bychom chtěli například
pracovat s hodnotou 2
, z buňky D
(uvedené výše),
tak při indexaci pomocí kulatých závorek dostaneme novou buňku obsahující
pouze hodnotu 2
, ale nejedná se o číslo 2
. Museli
bychom znovu použít indexaci se složenými závorkami. V případě buněk
můžeme zapisovat i vnořená indexování. Například pokud bychom chtěli
první znak textového řetězce v druhém řádku buňky C
(viz
poslední řádek kódu níže):
M(2,3) % Výstupem bude znak 'g' C{1} % Výstupem bude řetězec (vektor) znaků 'Ahoj' D(1,2) % Výstupem bude nová buňka obsahující číslo 2 2 * D(1,2) % Řádek nám vyvolá chybu, protože nemůžeme násobit buňku 2 * D{1,2} % Tento řádek už nám ovšem navrátí číslo 4 C{2}(1) % Výstupem bude znak 'N'
Dynamické indexování
Dynamické indexování pravděpodobně není oficiální termín pro to, co hodláme popisovat, ale tento termín ve spojení s následujícími vlastnostmi MATLABu osobně používám a myslím, že je nejvýstižnější.
V systému MATLAB totiž nemusíme indexovat pouze pro získání jedné konkrétní hodnoty, ale je možné nechat si navrátit rozsah hodnot podle indexů, tedy vektor nebo matici. Tento princip platí pro všechny pole v MATLABu, ať už jde o vektory, matice či buňky.
Binární (logická) matice
Než se do toho pustíme, tak zde pro lepší pochopení ještě uvedeme
termín binární matice, neboli matice obsahující pouze logické hodnoty
1
nebo 0
(platí nebo neplatí, aneb true nebo false).
Tyto matice je možné vytvořit nespočetně způsoby. Některé z nich si
uvedeme.
- Pomocí funkce
true()
nebo funkcefalse()
(další detaily parametrů v nápovědě F1). Tyto funkce navrací binární matice buď plné jedniček (funkcetrue()
) nebo nul:
true(2,2) % Matice 2x2 plná logických jedniček false(5,3) % Matice 5x3 plná logických nul
- Pomocí cyklů
for
awhile
(cykly probereme podrobně v další lekci), kdy procházíme jednotlivé indexy matice a nastavujeme jejich hodnotu:
for a = 1 : 4 A(a) = false; end % Výstupem bude matice 1x4 (vektor) plný logických nul
- Výstupy podmínek. Toto je asi jeden z největších meisterstücků MATLABu. Protože nemusíme procházet hodnotu po hodnotě, ale jedním příkazem získáme binární matici splňující danou podmínku. Navíc o této funkci spousta uživatelů MATLABu většinou ani neví:
V = [10, 20, 30]; A = V >= 20 % Ukládám výsledky podmínky do matice A
Matice A
bude o stejných rozměrech, jako jsou rozměry matice
V
s tím, že hodnota na daném indexu matice A
bude
výsledek dané podmínky pro hodnotu na indexu matice V
. V tomto
případě bude výsledek vektor s hodnotami 0
, 1
,
1
.
Implementace dynamického indexování
Dynamicky indexovat můžeme dvěma způsoby:
- Vektorem indexů (Vektor obsahující čísla indexů)
- Maskováním indexů (Použitím binární matice)
Pomocí vektoru indexů můžeme získat novou matici (např. při zpracování obrazu získáme pouze oblast zájmu):
M = [1, 2, 3; 4, 5, 6; 7, 8, 9] N = M(1:2, 2:3) N = M([1, 2], [2, 3]) O = M(:, [1,3]) P = M(end, [1,3])
Pro matici N
definujeme, že chceme 1. až 2. řádek a 2. až
3. sloupec. Jsou zde pro lepší pochopení uvedeny dva zápisy, které jsou
naprosto rovnocenné (Rozdíl je pouze v definici vektoru).
U definice matice O
se nám objevuje "nový" znak a tím je
dvojtečka. Ta totiž při indexaci znamená všechno.
Výsledkem tedy budou všechny řádky pro 1. a 3. sloupec matice
M
.
U definice matice P
se nám objevuje pro změnu nové slovo a
tím je end
, které při indexaci znamená
poslední. Výsledkem tedy bude poslední řádek pro 1. a 3.
sloupec matice M
.
Výstup:
M = 1 2 3 4 5 6 7 8 9 N = 2 3 5 6 O = 1 3 4 6 7 9 P = 7 9
Pomocí maskování můžeme jednoduše projít a případně změnit všechny hodnoty v dané matici. Princip je jednoduchý. Dosadíme do indexu logickou matici o stejných rozměrech jako je ovlivňovaná matice a tam, kde je logická jednička, se provede žádaná změna:
M = [1, 2, 3; 4, 5, 6; 7, 8, 9] B = mod(M, 2) == 0 M(B) = 0 % Rovnocenný zápis: M(mod(M, 2) == 0) = 0
V tomto případě zjišťujeme, jestli je zbytek po celočíselném dělení
(operace modulo) nulový, tedy, zdali se jedná o sudé číslo. Pokud ano, tak
se v binární matici B
zapíše na dané pozici logická
jednička. Pak tuto binární matici dosadíme jako index do matice
M
a provedeme požadovanou operaci. V kódu výše je to
vynulování hodnoty. Toto se dá použít např. pro prahování při
zpracování obrazu:
Výstup:
M = 1 2 3 4 5 6 7 8 9 B = 0 1 0 1 0 1 0 1 0 M = 1 0 3 0 5 0 7 0 9