Práce s maticemi a vektory III
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 na problematiku z různých úhlů.
V první části jsme si vysvětlili 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í. Podobná témata se probírají i v této části, pouze s pomocí matic (dvourozměrná pole) a na praktické ukázce úpravy fotografie.
Tvorba matic
K jednoduché tvorbě matic se používají, stejně jako u vektorů,
hranaté závorky. Oddělovačem prvků je mezera nebo čárka, oddělovačem
řádků je středník. Chceme-li tedy matici s prvky od 1
do
25
, kde budou hodnoty naskládané ve sloupcích, můžeme ji
zapsat takto:
A = [1,6,11,16,21;2,7,12,17,22;3,8,13,18,23;4,9,14,19,26;5,10,15,20,25]
A nebo pomocí funkce reshape()
, která změní tvar (odtud
název) vektoru od 1
do 25
, tak aby v první i druhé
dimenzi bylo 5 prvků:
A = reshape(1:25,5,5);
reshape()
je funkce, kterou je vhodné mít v povědomí.
Občasné "reshapnutí" dokáže častokrát kód zjednodušit.

Co znamenají zrzavá čísla s modrými šipkami je předmětem následující kapitoly.
Indexování matic
Matice se v MATLABu dají indexovat dvojím způsobem. Chceme-li přistoupit k prvku na prvním řádku pátého sloupce, bude to nepřekvapivě takto:
prvek_1_5 = A(1,5); %21
Řádky i sloupce se indexují od jedničky a z levého horního rohu (stejně jako běžná tabulka, například v Excelu). Kromě tohoto dvoučíselného náběru můžeme využít pouze jednu hodnotu:
devaty_prvek = A(9); %9
Tímto zápisem říkáme – vezmi prvek, který je na deváté pozici. MATLAB pozici počítá zas z levého horního rohu po sloupečcích. Názorně je to vysvětleno na obrázku výše. Výhoda takového zápisu je, že jedno číslo je jednodušší pro uchování a počítání. Dají se tak pochopitelně indexovat i vícerozměrné objekty.
Výřezy matic
Kromě jednotlivých čísel je možné vybírat i "podmatice", tedy výřez původní matice. Je to jen kombinace znalostí, které jsou vysvětleny v předchozím článku (tvorba a indexování vektorů).

Proměnná vyrez = A(1:3,1:2)
obsahuje všechny řádky jedna
až tři v prvním a druhém sloupečku. Ekvivalentním zápisem by bylo
vyrez = A([1 2 3],[1 2])
. Existuje pár vychytávek, jak si takové
vyřezávání zjednodušit. Jednou z nich je dvojtečka a druhou klíčové
slovo end
. Dvojtečka říká "všechny" a end
je
odkazem na poslední prvek. Tím pádem dvojtečka je stejná jako
1:end
. Pro ukázku si zde uveďme několik způsobů, jak vybrat
čtvrtý sloupec z matice o velikosti 5x5:
A(1:end, 4) %Od prvního řádku do posledního A(:,4) %Dvojtečka znamená "všechny" (řádky) A(1:1:5, 4) %Řádky od 1 po 1 do 5 A(1:5,4) %Řádky od 1 do 5 (prostřední 1 tam být nemusí) A([1, 2, 3, 4, 5], 4) %Řádky 1,2,3,4,5 A([1 2 3 4 5], 4) %V definici [vektoru] je mezera ekv. čárce
Nejlepší způsob je (téměř vždy) ten nejkratší, tedy výběr
čtvrtého sloupce pomocí příkazu: A(:,4)
. Navíc je tento
zápis obecný pro jakoukoliv matici, která má alespoň 4 sloupce.
Úprava matic
Chceme-li změnit hodnotu v matici, musíme říci kde a na co. Před rovnítkem bude kde, za rovnítkem co. Nuly do čtvrtého sloupečku přiřadíme následovně:
A_nuly_ve_4sl = A ;%kopie matice A, abychom si ji nepřepsali. A_nuly_ve_4sl(:, 4) = 0;
Tři horní řádky nahradíme jedničkou pomocí:
A_prvni3radky = A; A_prvni3radky(1:3, :) = 1;
Poslední sloupec nakopírujeme do posledního řádku:
A_posledni_rad_sl = A; A_posledni_rad_sl(end, :) = A_posledni_rad_sl(:,end);
Nakonec ztrojnásobíme každý druhý prvek matice:
A_3x = A; A_3x(1:2:end) = A_3x(1:2:end)*2;
Nyní máme znalosti o vytváření, indexování a úpravě matic. Tyto znalosti využijeme v následující kapitole k úpravě jasu fotografie - takový Photoshop od podlahy.
Cvičení – úprava fotografie
Digitální fotografie je soubor pixelů v mřížce – tedy matice. Černobílá fotografie je pouze jedna matice, kde hodnoty prvků určují jak bude daný pixel světlý. Jedna taková fotografie je součástí každé verze MATLABu a načtete ji a zobrazíte takto:
I = imread('cameraman.tif');
imshow(I)
Jedná se o následující fotografii kameramana:

Nynějším úkolem bude následující:
Změňte všechny pixely, které jsou nižší než průměr, na bílou barvu.
Průměr hodnot pixelů
K vypočítání průměru existuje nepříliš složitě nazvaná funkce
mean()
. Parametrem all
sdělujeme, že to chceme
spočítat přes všechny prvky (jinak bychom počítali průměr v každém
řádku).
prumer = mean(I, 'all');
Výsledkem je hodnota 117.7245
, což je v blízkosti poloviny
šedotónového rozsahu (0
- 255
).
Výběr pixelů vyšších než průměr
Nemusíme zde využívat dvojitý cyklus na projití dvojrozměrného pole. Stačí jeden řádek kódu:
kde_vice_nez_prumer = I < prumer;
Výsledkem bude binární matice o stejné velikosti jako je obrázek. Prvky pole, které splňují podmínku, se stanou jedničkou, ostatní nulou.
Bílá barva
Jak již jsem zmínil výše, šedotónový obraz se pohybuje v rozsahu od
0
- 255
. Důvod je prostý – na jeden pixel je
třeba jeden bajt paměti. V jenom bajtu je 8 bitů, 82 = 256.
Nejtmavší barva, tedy černá (neboli absence světla) je definována nulou.
Nejsvětlejší barva, tedy bílá, 255
. Potřebujeme tedy na
všechny místa, která splňují podmínku, nastavit 255
.
Změna barev vybraných pixelů
Binární matice kde_vice_nez_prumer
může sloužit též pro
indexování, tedy "náběru" daných prvků, se kterými chceme něco
dělat:
I2 = I;%nakopirovani matice
I2(kde_vice_nez_prumer) = 255;
Zobrazení výsledku
Výsledek zobrazíme takto:
imshow(I2)
Což vyústí v následující obrázek:

Závěr
Celý MATLAB je založený na maticích (má to i v názvu). Pochopení toho, jak se zde s nimi správně nakládá, je užitečná znalost nejen pro zpracování obrazu.
Druhá úloha
Řešení následující úlohy naleznete na konci přiloženého souboru (obsahuje též všechen kód z článku). Polovinu obrázku kameramana změňte na šedou barvu:

Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 14x (1.45 kB)
Aplikace je včetně zdrojových kódů