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ů


