Obraz jako signál: pixely, barvy, konvoluce a hrany
Obraz jako matice čísel, barvy a jas, 2D konvoluce (rozmazání a zostření), Sobelův detektor hran v šumu, aliasing a moaré při zmenšování a cesta od ručně navržených jader ke konvolučním sítím.
Série Základy AI Díl 60 z 83
- Mapa umělé inteligence: co je co a jak to do sebe zapadá
- Stručná historie umělé inteligence: od Turinga po jazykové modely
- Data, model, trénink, inference: základní pojmy na jednom příkladu
- Jak číst matematický zápis: symboly, indexy, sumy a kvantifikátory
- Množiny a relace: stavebnice, ze které se skládají definice v AI
- Funkce a zobrazení: proč je každý model v AI funkce
- Logika a důkazy: pravidla, podle kterých se v AI uvažuje
- Grafy a stromy: struktura, na které stojí hledání i neuronové sítě
- Lineární algebra pro strojové učení: vektory, matice a proč AI hlavně násobí
- Derivace, gradient a řetízkové pravidlo: jak model zjistí, kterým směrem se učit
- Gradientní sestup: jak se model učí
- Co je pravděpodobnost: od hodu kostkou ke Kolmogorovovým axiomům
- Podmíněná pravděpodobnost a Bayesova věta: jak změnit odhad, když se dozvíte něco nového
- Náhodná veličina a distribuční funkce: jedna funkce, která o rozdělení řekne všechno
- Funkce hustoty a pravděpodobnostní funkce: proč má spojitá veličina v bodě pravděpodobnost nula
- Střední hodnota, rozptyl a kovariance: kde rozdělení leží, jak je široké a co s čím souvisí
- Přehled pravděpodobnostních rozdělení: Bernoulli, binomické, Poisson, rovnoměrné, normální a exponenciální
- Zákon velkých čísel a centrální limitní věta: proč se průměry chovají tak předvídatelně
- Statistika a odhady parametrů: maximální věrohodnost, MAP a intervaly spolehlivosti
- Teorie informace: entropie, křížová entropie a KL divergence — odkud se berou ztrátové funkce
- Prohledávání stavového prostoru: BFS, DFS, UCS a A* s animacemi
- Hry a protivník: minimax, alfa-beta ořezávání a Monte Carlo tree search
- Splňování omezujících podmínek: backtracking, propagace omezení a AC-3 na sudoku a mapě krajů
- Logika a znalostní systémy: dopředné a zpětné řetězení, rezoluce a expertní systémy
- Plánování: STRIPS, svět kostek, heuristiky z relaxace a plánování v AI agentech
- Lokální hledání a simulované žíhání: obchodní cestující přes krajská města
- Genetické algoritmy: populace, křížení, mutace a výběr na batohu na výlet
- Evoluční strategie a genetické programování: od pravidla jedné pětiny po Keplerův zákon
- Optimalizace mravenčí kolonií: jak feromonová stopa najde krátkou cestu
- Optimalizace hejnem částic: setrvačnost, vlastní zkušenost a zkušenost hejna
- Neuroevoluce: evoluce vah i tvaru neuronových sítí a algoritmus NEAT
- Fuzzy množiny a funkce příslušnosti: jak zapsat „trochu teplo“
- Fuzzy logika a pravděpodobnost: proč „trochu teplo“ neznamená „pravděpodobně teplo“
- Fuzzy logika: t-normy, implikace a pravidla KDYŽ–PAK
- Fuzzy řízení: Mamdani a Sugeno od ventilátoru po kyvadlo na vozíku
- Fuzzy shlukování: algoritmus fuzzy c-means a body mezi shluky
- Neuro-fuzzy systémy (ANFIS): fuzzy pravidla, která se učí z dat
- Markovovy řetězce: přechodová matice, stacionární rozdělení a PageRank
- Skryté Markovovy modely: Viterbiho algoritmus a nepoctivé kasino
- Bayesovské sítě: proč je tráva mokrá a co z toho plyne pro postřikovač
- Kalmanův filtr: jak z nepřesných měření odhadnout, kde auto je a jak rychle jede
- Druhy strojového učení: s učitelem, bez učitele, s částečným učitelem a další
- Přeučení a regularizace: proč model, který zná data nazpaměť, selže
- Vyhodnocení modelu: křížová validace, F1 a křivka ROC
- Shlukování a snížení dimenze: k-means, PCA a t-SNE
- Klasifikace a regrese: dvě úlohy učení s učitelem
- Lineární regrese: nejmenší čtverce geometricky i maticově
- Polynomiální a nelineární regrese: jak přímku ohnout
- Logistická regrese: sigmoida, šance a křížová entropie
- Vícetřídní klasifikace a softmax: od dvou tříd k mnoha
- Naivní Bayesův klasifikátor: spamový filtr, který funguje lépe, než by měl
- Ztrátové funkce: co přesně model minimalizuje
- Rozhodovací stromy a k nejbližších sousedů: modely bez vzorců
- Ansámbly: náhodný les a gradient boosting
- SVM a jádrový trik: nejširší hranice a jak ji ohnout
- Signál a vzorkování: proč platí Nyquistův teorém
- Fourierova transformace: rozklad signálu na frekvence
- Filtry a konvoluce: vyhlazení, hrany a odstranění šumu
- Zvuk a řeč: spektrogram, melová škála a MFCC
- Obraz jako signál: pixely, barvy, konvoluce a hrany
- Perceptron a umělý neuron: nejjednodušší neuronová síť a co neumí
- Neuronová síť od nuly: zpětné šíření chyby krok za krokem
- Aktivace, inicializace a normalizace: drobnosti, na kterých hluboká síť stojí
- Konvoluční sítě: jak síť poznává obrázky
- Rekurentní sítě: paměť pro posloupnosti a mizející gradient
- LSTM a GRU: brány, které rozhodují, co si síť zapamatuje
- Autoenkodéry: síť, která se učí data stlačit a zase rozbalit
- Embeddingy a word2vec: jak se slovo stane vektorem
- Mechanismus pozornosti: jak se model naučí, kam se dívat
- Transformery a velké jazykové modely: architektura krok za krokem
- Tokenizace: jak se text rozseká na kousky pro model
- Předtrénování a škálování: proč větší model a víc dat funguje
- Doladění a RLHF: jak se z doplňovače textu stane asistent
- Prompty, kontext a RAG: jak modelu dát správné informace
- Variační autoenkodéry (VAE): nové obrázky ze spojitého latentního prostoru
- Generativní adversariální sítě (GAN): padělatel proti detektivovi
- Difúzní modely: jak se z čistého šumu stane obrázek
- Markovovy rozhodovací procesy: stavy, akce, odměny a Bellmanovy rovnice
- Q-learning a DQN: učení hodnoty akcí od tabulky po neuronovou síť
- Policy gradient a PPO: učení přímo strategie
- Jak funguje AI agent: jazykový model ve smyčce s nástroji
- Programování s AI agenty: zadání, testy a kontrola
- Vyhodnocení a bezpečnost AI systémů: jak měřit a jak hlídat
Celá osnova série 83 z 83 témat hotovo
- Jak počítač ukládá obraz a barvy a kolik čísel to je.
- Co dělá 2D konvoluce a jak se jí hledají hrany.
- Proč zmenšování obrázku vyrábí moaré a proč se konvoluční sítě učí jádra samy.
Co se hodí znát předem: Signál a vzorkování: proč platí Nyquistův teorém, Filtry a konvoluce: vyhlazení, hrany a odstranění šumu
Pro počítač je fotka tabulka čísel. Kočka, západ slunce i rentgenový snímek jsou jen matice hodnot jasu — a všechno, co jsme se v posledních dílech naučili o signálech, platí i pro ně. Vzorkování, aliasing, konvoluce a hrany mají v obraze dva rozměry místo jednoho, ale princip je stejný. A právě na obrazech se ukázalo, jak silná konvoluce je: konvoluční neuronové sítě, které se ji učí samy, v roce 2012 překvapivě vyhrály soutěž v rozpoznávání obrázků a odstartovaly dnešní vlnu umělé inteligence.
Navazuje na díly Signál a vzorkování a Filtry a konvoluce.
1. Obraz jako matice čísel
Definice — digitální obraz a pixel
Nechť H, W ∈ ℕ (výška a šířka) a V je množina možných hodnot jasu — pro 8bitový obraz V = {0, 1, …, 255}, ve výpočtech V = ℝ. Digitální šedotónový obraz je funkce
I : {0, …, H − 1} × {0, …, W − 1} → V,
tedy matice I[y, x] s H řádky a W sloupci. Každá dvojice (y, x) je pixel a I[y, x] je jeho jas (řádek y shora, sloupec x zleva). Barevný obraz má v každém pixelu tři hodnoty, I : {0, …, H − 1} × {0, …, W − 1} → V3. Obraz je tak dvourozměrný signál, vzorkovaný (hodnoty jen v bodech mřížky) a kvantovaný (konečně mnoho úrovní jasu).
Mozaika z dlaždiček, každá jednobarevná. Z dálky obraz, zblízka čísla. Fotka z telefonu s 12 megapixely (4 000 × 3 000) má po třech barvách 36 milionů čísel. Neuronové sítě na rozpoznávání obrázků proto obvykle dostávají obrázek zmenšený na 224 × 224 pixelů — i tak je to 150 528 čísel.
Naše scéna má 48 × 48 pixelů: pozadí plynule světlající zleva doprava, světlý kruh a tmavý čtverec. Výřez ukazuje, co z toho „vidí“ počítač: hranice kruhu není čára, ale místo, kde čísla skočí ze zhruba 230 na zhruba 120 — a šum do čísel přimíchá náhodné výkyvy.
Definice — kvantování jasu
Výpočty v tomhle dílu pracují s jasem v ∈ ℝ jako s reálným číslem (0 = černá, 1 = bílá). Nechť round(t) značí celé číslo nejbližší k t ∈ ℝ (poloviny nahoru). Kvantování na 8 bitů je funkce q : ℝ → {0, 1, …, 255},
q(v) = round(255 · min(1, max(0, v))).
Hodnoty mimo [0, 1] se tedy nejdřív ořežou a pak se výsledek zaokrouhlí na nejbližší z 256 úrovní.
kruh: v = 0,9 ⇒ 255 · 0,9 = 229,5 ⇒ 230
pozadí ve sloupci x = 26: v = 0,3 + 0,3 · 26/47 = 0,4660 ⇒ 255 · 0,4660 = 118,8 ⇒ 119
fotka 4 000 × 3 000 se třemi kanály po 8 bitech: 36 000 000 bajtů = 36 MB bez komprese
Definice — aditivní gaussovský šum
Nechť I : {0, …, H − 1} × {0, …, W − 1} → ℝ je obraz, σ > 0 a εy,x (pro všechny pixely (y, x)) jsou nezávislé náhodné veličiny s normovaným normálním rozdělením 𝒩(0, 1) (střední hodnota 0, rozptyl 1). Obraz s aditivním gaussovským šumem je
Ĩ[y, x] = I[y, x] + σ · εy,x pro všechny pixely (y, x).
K jasu každého pixelu se tedy přičte vlastní náhodný výkyv se směrodatnou odchylkou σ, nezávisle na ostatních pixelech. U nás σ = 0,12 — na stupnici 0–255 typický výkyv kolem 31 úrovní. Je to nejjednodušší a nejběžnější model šumu snímače (skutečný šum je navíc závislý na jasu).
2. Barvy
Definice — model RGB a jas
V modelu RGB je barva trojice (R, G, B) ∈ [0, 255]3 intenzit červené, zelené a modré složky, které se sčítají (aditivní míchání světla): (0, 0, 0) je černá, (255, 255, 255) bílá. Jas barvy (R, G, B) podle normy ITU-R BT.601 je číslo
Y = 0,299 R + 0,587 G + 0,114 B ∈ [0, 255].
Jas je tedy vážený součet složek; je to nejčastěji používaná volba vah.
Displej má v každém pixelu tři maličké lampičky. Oko má na barvy tři druhy čípků a nejcitlivější je na zelenou — proto má zelená ve vzorci pro jas největší váhu. Plně svítící zelená má jas 150 z 255, červená 76, modrá jen 29. Žlutá (červená + zelená) 226. Proto modrý text na černém pozadí čte oko tak špatně.
Y = 0,299 R + 0,587 G + 0,114 B
- Y
- jas — jak světlý pixel připadá oku; tohle číslo zbude po převodu na šedou
- 0,299 R
- příspěvek červené: oko ji vnímá zhruba poloviční silou než zelenou
- 0,587 G
- příspěvek zelené — největší váha, protože na zelenou je oko nejcitlivější
- 0,114 B
- příspěvek modré — nejmenší, modrou vnímá oko jako nejtmavší
Příklad — jas základních barev
Barvy podle vzorce výše:
zelená (0, 255, 0): 0,587 · 255 = 149,685 ≈ 150
červená (255, 0, 0): 0,299 · 255 = 76,245 ≈ 76; modrá (0, 0, 255): 0,114 · 255 = 29,07 ≈ 29
žlutá (255, 255, 0): 76,245 + 149,685 = 225,93 ≈ 226
Pro neuronovou síť je barevný obrázek tři matice nad sebou — tři kanály. Většina operací v tomhle dílu se dělá na každém kanálu zvlášť, a tak budeme pracovat jen se šedotónovými obrázky.
3. 2D konvoluce
Definice — dvourozměrná konvoluce
Nechť I : ℤ2 → ℝ je obraz (mimo svůj rozsah doplněný podle definice okrajů níže), m ∈ {0, 1, 2, …} a K : {−m, …, m}2 → ℝ je jádro — matice vah velikosti (2m + 1) × (2m + 1), např. 3 × 3 pro m = 1. 2D konvoluce obrazu I s jádrem K je obraz I * K daný pro každý pixel (y, x) předpisem
(I * K)[y, x] = ∑i=−mm ∑j=−mm K[i, j] · I[y − i, x − j].
Jádro se tedy posouvá po obraze a v každé poloze se spočte vážený součet pixelů pod ním.
Stejné jako v jednom rozměru, jen šablona je čtvereček a jezdí po řádcích i sloupcích. Každý pixel výsledku je směs jeho sousedů podle vah v šabloně. Různé šablony dělají různé věci:
(I * K)[y, x] = ∑i=−mm ∑j=−mm K[i, j] · I[y − i, x − j]
- (I * K)[y, x]
- pixel výsledku v řádku y a sloupci x — každý pixel výstupu se počítá zvlášť, stejným předpisem
- ∑i ∑j
- přes všechna políčka jádra velikosti (2m + 1) × (2m + 1); m = 1 pro 3 × 3 — výsledek závisí jen na blízkém okolí
- K[i, j]
- váha jádra: určuje, co konvoluce dělá (rozmazává, zostřuje, hledá hrany); v konvoluční síti jsou to učené parametry
- I[y − i, x − j]
- soused pixelu [y, x] posunutý o (i, j); mínus znamená, že se jádro „otočí“ o 180° — díky tomu má konvoluce pěkné vlastnosti (je záměnná a asociativní)
Příklad — jeden pixel z výřezu
Pixel ve 4. řádku a 4. sloupci výřezu výše (v obraze řádek 17, sloupec 25; bez šumu by měl 230) a jeho sousedé, hodnoty 0–255:
| 214 | 227 | 180 |
| 217 | 229 | 176 |
| 241 | 255 | 255 |
Barvy podle vzorce výše:
průměr 3 × 3 (všech 9 vah 1/9): 1/9 · (214 + 227 + 180 + 217 + 229 + 176 + 241 + 255 + 255) = 1 994/9 ≈ 221,6
zostření: 5 · 229 + (−1) · (227 + 217 + 176 + 255) = 1 145 − 875 = 270 ⇒ víc než bílá, po ořezání 255
Pixel leží těsně u okraje kruhu a vpravo od něj je tmavší pozadí. Průměr do něj přimíchá kus pozadí, zostření ho naopak od pozadí „odtlačí“ — a přetáhne až za bílou.
Definice — okraje obrazu
Na okraji chybí jádru sousedé. Nechť obraz I má H řádků a W sloupců (u nás H = W = 48) a pro N ∈ ℕ a t ∈ ℤ označme omezN(t) = min(N − 1, max(0, t)). Doplnění opakováním okraje rozšíří obraz na celé ℤ2 předpisem
I[y, x] = I[omezH(y), omezW(x)] pro všechna (y, x) ∈ ℤ2,
tj. pixel mimo obraz nahradí nejbližším pixelem uvnitř (index se ořízne do rozsahu 0 … 47); to dělá náš kód. Jiné možnosti jsou doplnění nulami, I[y, x] = 0 mimo obraz (běžné v neuronových sítích), nebo zrcadlení. Výsledek konvoluce pak počítáme jen v pixelech původního obrazu, takže má stejnou velikost jako vstup.
| Jádro | váhy | co dělá | odchylka od scény bez šumu |
|---|---|---|---|
| žádné | — | zašuměný obrázek | 0,121 |
| průměr 3 × 3 | všech 9 vah 1/9 | rozmaže, potlačí šum | 0,066 |
| gaussovka 5 × 5 | (1 4 6 4 1)ᵀ(1 4 6 4 1)/256 | rozmaže hladčeji | 0,061 |
| zostření | střed 5, čtyři sousedé −1 | zvýrazní rozdíly | 0,678 |
Rozmazání sníží šum na polovinu, ale rozmaže i hrany. Zostření dělá opak: k pixelu přičte jeho rozdíl od sousedů, takže hrany vyniknou — a šum s nimi, odchylka vzroste víc než pětkrát. Zostřovat se vyplatí jen obrázek, který šum nemá. Gaussovka 5 × 5 je zajímavá i jinak: jde napsat jako součin sloupce a řádku, takže se dá spočítat jako dvě 1D konvoluce — místo 25 násobení na pixel jen 10.
Věta — co udělá konvoluce se šumem
Nechť Ĩ = I + σε je obraz s aditivním šumem, kde σ ≥ 0 a εy,x jsou nezávislé náhodné veličiny se střední hodnotou 0 a rozptylem 1, a nechť K : {−m, …, m}2 → ℝ je jádro. Pak v každém pixelu (y, x), který je od okraje obrazu vzdálen aspoň m (takže se žádný pixel nepoužije dvakrát), má šumová složka výsledku (σε) * K směrodatnou odchylku
σpo = σ · √∑i,j K[i, j]2.
Důkaz. Konvoluce je lineární, takže Ĩ * K = I * K + (σε) * K a šumová složka výsledku je ∑i,j K[i, j] · σεy−i, x−j. Rozptyl součtu nezávislých veličin je součet rozptylů a konstanta před veličinou se do rozptylu dostane na druhou: Var = ∑ K[i, j]2 σ2. Odmocnina dá tvrzení. ∎
Příklad — proč tabulka vyšla tak, jak vyšla
průměr 3 × 3: √9 · (1/9)2 = √1/9 = 1/3 ⇒ 0,12/3 = 0,040
gaussovka 5 × 5: 1 + 16 + 36 + 16 + 1/256 = 70/256 = 0,2734 ⇒ 0,12 · 0,2734 = 0,033
zostření: √52 + 4 · 12 = √29 = 5,385 ⇒ 0,12 · 5,385 = 0,646
U gaussovky jsme využili, že její váhy jsou součiny K[i, j] = gigj/256 s (gi) = (1, 4, 6, 4, 1), takže ∑ K2 = (∑ gi2)2/2562 a √∑ K2 = ∑ gi2/256. Zbylý šum v naší scéně opravdu vyjde 0,041, 0,034 a 0,644. Celková odchylka v tabulce je větší, protože rozmazání poškodí i hrany scény: u průměru 3 × 3 tak vznikne další chyba 0,052 a zhruba √0,0412 + 0,0522 ≈ 0,066 (zjednodušeně — obě chyby bereme jako nezávislé). Lepšího filtru proti šumu tedy nedosáhneme jen menším ∑ K2; větší jádro šum potlačí víc, ale hrany rozmaže víc.
def konvoluce(I, K): # K má velikost (2m+1) × (2m+1)
for y in 0 … výška−1:
for x in 0 … šířka−1:
s = 0
for i in −m … m:
for j in −m … m:
s += K[i][j] · I[omez(y+i)][omez(x+j)] # omez = opakování okraje
V[y][x] = s
return V
def gauss5(I): # oddělitelné jádro: dva průchody po 5 násobeních
g = [1, 4, 6, 4, 1] / 16
return konvoluce_sloupcu(konvoluce_radku(I, g), g)
4. Detekce hran
Definice — gradient obrazu a Sobelův operátor
Nechť f : ℝ2 → ℝ, (x, y) ↦ f(x, y), je diferencovatelná funkce jasu spojitého obrazu. Její gradient v bodě (x, y) je vektor
∇f(x, y) = (∂f/∂x(x, y), ∂f/∂y(x, y));
ukazuje směr, ve kterém jas nejrychleji roste, a jeho velikost |∇f| je strmost tohoto růstu.
Nechť I : ℤ2 → ℝ je digitální obraz (doplněný za okraji). Sobelův operátor odhaduje gradient dvěma jádry 3 × 3, indexovanými i, j ∈ {−1, 0, 1} (řádek, sloupec):
Sx s řádky (−1, 0, 1), (−2, 0, 2), (−1, 0, 1), Sy = SxT s řádky (−1, −2, −1), (0, 0, 0), (1, 2, 1),
a pro každý pixel (y, x) klade
Gx[y, x] = ∑i,j=−11 Sx[i, j] · I[y + i, x + j], Gy[y, x] = ∑i,j=−11 Sy[i, j] · I[y + i, x + j]
(vzájemná korelace; konvoluce s týmiž jádry by dala jen opačné znaménko). Velikost hrany v pixelu je
|∇I|[y, x] = √Gx[y, x]2 + Gy[y, x]2.
Gx je tedy (až na kladný násobek) odhad ∂I/∂x a Gy odhad ∂I/∂y, kde y roste směrem dolů.
Jádro Gx odečte levé sousedy od pravých: kde je obraz rovný, dá nulu, kde jas vodorovně skočí, dá velké číslo. Prostřední řádek má dvojnásobnou váhu — malé rozmazání ve svislém směru je v jádře rovnou zabudované. Gy totéž svisle a dohromady najdou hrany v libovolném směru.
Rozepsané do jednotlivých pixelů je Gx rozdíl sloupců vážený přes tři řádky:
Gx[y, x] = ∑i=−11 wi · ( I[y + i, x + 1] − I[y + i, x − 1] ), (w−1, w0, w1) = (1, 2, 1)
- Gx[y, x]
- odhad vodorovné derivace jasu (bez dělení vzdáleností — na měřítku pro hledání hran nezáleží)
- wi = (1, 2, 1)
- vyhlazení ve svislém směru: rozdíl se změří ve třech řádcích a prostřední řádek váží nejvíc — jeden zašuměný řádek tak výsledek nepokazí
- I[·, x + 1] − I[·, x − 1]
- rozdíl pravého a levého souseda (centrální diference) — na rovné ploše 0, na svislé hraně velké číslo; znaménko říká, kterým směrem jas roste
Příklad — Sobel na hraně a mimo ni (scéna bez šumu)
levá hrana tmavého čtverce, pixel [30, 27]: vlevo pozadí 0,4660, vpravo čtverec 0,1 ve všech třech řádcích
Gx = (1 + 2 + 1) · (0,1 − 0,4660) = −1,464, Gy = 0 ⇒ |∇I| = 1,464, směr 180° (jas roste doleva)
pozadí, pixel [40, 10]: Gx = (1 + 2 + 1) · (0,3 · 11/47 − 0,3 · 9/47) = 4 · 0,6/47 ≈ 0,051, Gy = 0
(barvy podle vzorce výše)
Plynulý přechod pozadí dá skoro nulu, skutečná hrana skoro třicetkrát víc. Nejlepší práh na čisté scéně vyjde zhruba 1,0 — a všechno nad ním se prohlásí za hranu.
Ve scéně je 240 skutečných hranových pixelů. Detektor porovnáme s nimi jako klasifikátor z dílu o vyhodnocení modelu: při nejlepším prahu má Sobel na čisté scéně F1 0,994. Na zašuměné jen 0,859 — práh musí být vysoko, aby nebral šum, a tak najde jen 80 % hran. Když obrázek nejdřív rozmažeme gaussovkou, F1 stoupne na 0,880 a najde se 90 % hran. Stejný recept jako v 1D: nejdřív vyhladit, pak derivovat.
F1 = 2 · P · R/P + R, P = TP/TP + FP, R = TP/TP + FN
- F1
- jedno číslo pro porovnání detektorů; harmonický průměr je vysoký jen tehdy, když jsou vysoké oba členy — detektor, který označí všechno, nebo skoro nic, dostane málo
- P (preciznost)
- z pixelů, které detektor označil, podíl skutečných hran (TP); trestá falešné poplachy FP — tady zrnka šumu
- R (úplnost)
- ze všech 240 skutečných hran podíl nalezených; trestá přehlédnuté hrany FN — práh příliš vysoko
Příklad — F1 se šumem, bez rozmazání a s ním
Barvy podle vzorce výše:
bez rozmazání: označeno 207, z toho TP = 192, FP = 15, FN = 48 ⇒ P = 192/207 = 0,928, R = 192/240 = 0,800, F1 = 0,859
s rozmazáním: označeno 253, z toho TP = 217, FP = 36, FN = 23 ⇒ P = 217/253 = 0,858, R = 217/240 = 0,904, F1 = 0,880
Rozmazání si koupí 25 nalezených hran navíc za 21 falešných poplachů — preciznost klesne, úplnost stoupne víc, a F1 tak vzroste.
def hrany(I, prah):
J = konvoluce(I, gauss5) # 1. vyhladit (bez toho najdeme šum)
Gx = konvoluce(J, sobelX) # 2. derivovat vodorovně
Gy = konvoluce(J, sobelY) # a svisle
G = sqrt(Gx² + Gy²) # 3. velikost gradientu v každém pixelu
return G > prah # 4. hrana = silná změna jasu
5. Aliasing při zmenšování
Zmenšit obrázek čtyřikrát nejjednodušeji jde tak, že se vezme každý čtvrtý pixel. To je převzorkování — a víme, co hrozí. Vyzkoušíme to na zónové desce: soustředných kroužcích, které se od středu zahušťují.
Z[y, x] = 1/2 + 1/2 cos(π r2/96), r2 = (x − 48)2 + (y − 48)2, x, y ∈ {0, …, 95}
- Z[y, x]
- jas pixelu zónové desky 96 × 96
- 1/2
- střední šeď — kolem ní jas kmitá
- 1/2 cos
- kmit s amplitudou 1/2, takže jas běhá přesně mezi 0 (černý kroužek) a 1 (bílý)
- πr2/96
- fáze roste s druhou mocninou vzdálenosti od středu, ne lineárně — proto se kroužky směrem ven zahušťují a deska obsahuje všechny frekvence od 0 do 0,5 cyklu na pixel najednou
Po zmenšení na 24 × 24 je Nyquistova frekvence 0,125 cyklu na původní pixel. Kroužky ve vzdálenosti přes 12 pixelů od středu jsou hustší, a tak se výběrem každého čtvrtého pixelu převléknou za falešné kroužky — moaré. Ve vnějším prstenci mají kontrast 0,35, ačkoli tam žádné kroužky, které by se daly zachytit, nejsou. Když se před zmenšením každý blok 4 × 4 zprůměruje (rozmazání = antialiasingový filtr), vnější prstenec splyne v šeď s kontrastem 0,04 — informace je ztracená, ale nic falešného nepřibylo. Stejně proto fungují kvalitní zmenšovací algoritmy a stejně tak se chová fotoaparát s antialiasingovým filtrem před snímačem.
Věta — kam se frekvence při zmenšení přesune
Nechť k ∈ ℕ, k ≥ 2, f ≥ 0, φ ∈ ℝ a s[x] = cos(2πfx + φ), x ∈ ℤ, je kmit s frekvencí f cyklu na pixel. Zmenšení výběrem každého k-tého pixelu ponechá jen hodnoty s[kt], t ∈ ℤ; nová vzorkovací frekvence je 1/k cyklu na původní pixel a Nyquistova frekvence 1/2k. Pak:
- pro každé n ∈ ℤ má kmit s frekvencí f − n/k (a toutéž fází φ) v bodech x = kt tytéž hodnoty jako s, protože se jeho fáze liší o 2πnt, celý násobek 2π;
- zvolíme-li n jako celé číslo nejbližší k · f, je
fa = |f − n/k| ∈ [0, 1/2k]
a zmenšený obraz kmitu se nedá odlišit od kmitu s frekvencí fa mezi 0 a Nyquistovou frekvencí (absolutní hodnota jen obrátí znaménko fáze, cos je sudá funkce). Tomuto kmitu říkáme alias.
Příklad — falešné kroužky na zónové desce (k = 4)
Na vodorovné ose desky (řádek 48) ve vzdálenosti r od středu:
r = 12: f = 12/96 = 0,125 = Nyquistova frekvence — hranice, kam až zmenšení věrně funguje
r = 24: f = 0,25, n = 1 ⇒ fa = |0,25 − 1/4| = 0 — kmit se tváří jako konstanta: falešný „střed“
r = 36: f = 0,375, kf = 1,5 ⇒ fa = |0,375 − 2/4| = 0,125 (nebo stejně tak s n = 1)
r = 48: f = 0,5, n = 2 ⇒ fa = 0 — další falešný střed, uprostřed strany
Mimo osy je místní frekvence vektor (x − 48/96, y − 48/96) a každá složka se „přeloží“ zvlášť. Falešný střed vznikne tam, kde jsou obě složky násobky 1/4, tedy kde jsou x − 48 i y − 48 násobky 24 — to je pravidelná mřížka falešných středů v prostředním obrázku.
|H(f)| = |sin(πkf)/k · sin(πf)|, 0 < f < 1
- |H(f)|
- kolikrát průměr k sousedních pixelů zmenší amplitudu kmitu s frekvencí f (1 = projde celý, 0 = zmizí)
- sin(πkf)
- je nulový, když se do bloku k pixelů vejde celý počet period (f = 1/k, 2/k, …) — kladné a záporné půlvlny se v průměru přesně vyruší
- k · sin(πf)
- normalizace: pro f → 0 je poměr 1, takže rovnoměrná plocha projde beze změny
Příklad — průměr bloků 4 × 4 jako antialiasingový filtr
k = 4, barvy podle vzorce výše:
f = 0,125: sin π/2/4 sin π/8 = 1/4 · 0,3827 ≈ 0,65
f = 0,25: sin π/4 sin π/4 = 0 — právě frekvence, která by vyrobila falešný střed, zmizí úplně
f = 0,375: |sin(1,5π)|/4 sin(0,375π) = 1/4 · 0,9239 ≈ 0,27
Ve vnějším prstenci propustí průměr v jednom směru nejvýš asi čtvrtinu amplitudy; šikmé kroužky tlumí ve dvou směrech zároveň, a tak naměřený kontrast spadne z 0,35 až na 0,04. Pod Nyquistovou frekvencí ale ubírá i to, co by zmenšení zvládlo (0,65 na hranici) — proto zmenšený obrázek působí měkce. Lepší zmenšovací filtry (např. Lanczos) mají ostřejší přechod mezi „propustit“ a „utlumit“.
6. Od ručních jader k učeným
- Jádra jako příznaky. Desítky let se do systémů pro počítačové vidění ručně navrhovala jádra: Sobel, gaussovky, Gaborovy filtry. Z jejich odezev se skládaly příznaky pro klasifikátor.
- Konvoluční síť. Konvoluční vrstva obsahuje desítky jader, jejichž váhy se učí gradientním sestupem. Vrstva s 64 jádry 3 × 3 nad barevným obrázkem 224 × 224 provede asi 87 milionů násobení.
- Co se síť naučí. Jádra první vrstvy natrénované sítě vypadají jako detektory hran v různých směrech a barevné skvrny — síť sama znovu objeví Sobela. Hlubší vrstvy skládají hrany do textur, tvarů a částí objektů.
- Proč konvoluce. Kočka je kočka, ať je vlevo nahoře, nebo vpravo dole. Konvoluce použije stejné váhy na každém místě, takže stačí naučit jedno „oko na kočičí ucho“, ne zvláštní pro každou pozici.
násobení = Hout · Wout · k2 · Cin · Cout
- Hout · Wout
- počet poloh jádra = počet pixelů výstupu; v každé se počítá znovu
- k2
- políčka jádra k × k — jedno násobení na každé
- Cin
- vstupní kanály: jádro v síti není čtvereček, ale kvádr k × k × Cin, který sčítá přes všechny kanály naráz (u fotky R, G, B)
- Cout
- počet jader ve vrstvě — každé vyrobí jeden výstupní kanál (jednu „mapu příznaků“)
Definice — velikost výstupu, okraj a krok
Nechť vstup má šířku W ∈ ℕ, jádro velikost k × k (k ∈ ℕ), okraj p ∈ {0, 1, 2, …} je počet pixelů doplněných na každé straně a krok s ∈ ℕ je počet pixelů, o který se jádro posouvá, přičemž k ≤ W + 2p. Jádro se přiloží v polohách, kde jeho levý okraj leží na sloupci 0, s, 2s, … doplněného vstupu a celé jádro se do doplněné šířky W + 2p vejde. Počet těchto poloh, tedy šířka výstupu, je
Wout = ⌊W − k + 2p/s⌋ + 1
(pro výšku totéž; ⌊t⌋ je dolní celá část). Příklad pro W = 224 a k = 3: s p = 1, s = 1 vyjde ⌊223/1⌋ + 1 = 224 — velikost se zachová; s p = 1, s = 2 vyjde ⌊223/2⌋ + 1 = 112 — obraz se zmenší na polovinu; bez okraje (p = 0, s = 1) 222.
Příklad — kolik vah ušetří sdílení jádra
konvoluční vrstva: 64 jader · (3 · 3 · 3 vah + 1 posun) = 64 · 28 = 1 792 parametrů
plně propojená vrstva se stejným vstupem a výstupem: 150 528 vstupů · (224 · 224 · 64 = 3 211 264) výstupů ≈ 4,8 · 1011 vah
Rozdíl je přes dvě stě milionů krát. Konvoluce si to může dovolit, protože předpokládá dvě věci, které pro obrazy platí: pixel souvisí hlavně se svým okolím (malé jádro) a co je užitečné hledat na jednom místě, je užitečné i jinde (stejné váhy všude).
7. Shrnutí
- Obraz je matice vzorků jasu; fotka 12 Mpx má 36 milionů čísel, vstup sítě 224 × 224 × 3 = 150 528.
- Barva jsou tři kanály RGB; jas váží zelenou nejvíc (plná zelená 150, červená 76, modrá 29 z 255).
- 2D konvoluce posouvá malé jádro po obraze: rozmazání snížilo šum z 0,121 na 0,061, zostření ho zvětšilo na 0,678.
- Sobelův operátor najde hrany; na zašuměném obrázku pomůže nejdřív rozmazat (F1 0,859 → 0,880).
- Zmenšení výběrem pixelů vyrobí moaré (kontrast 0,35), průměr bloků předem ho odstraní (0,04).
Chcete si to osahat? Nechte AI agenta načíst vaši fotku, převést ji na šedou, pustit na ni Sobelův operátor a uložit výsledek — a pak to zkuste znovu na fotce zmenšené výběrem každého čtvrtého pixelu.
Máte na to jiný názor? Napište na support@coden-app.com.