tag:blogger.com,1999:blog-42989740356431265272024-03-05T11:48:29.510+01:00Počítačová grafikaAnonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.comBlogger18125tag:blogger.com,1999:blog-4298974035643126527.post-29831800506993137682017-10-10T16:50:00.005+02:002017-10-10T16:59:45.365+02:00Rasterizace čtyřstěnu (tetrahedronu)<b>Autor: Vojtěch Molek</b><br />
<br />
Mějme čtyřstěn zadaný čtyřmi vrcholy $P_0, P_1, P_2, P_3$ a šesti hranami. Konkrétní čtyřstěn, který použijeme pro demonstraci, je na následujícím obrázku:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyKvXC3e93cDodN1O1uqxhgXtjIlLU596eXIpHVNlE51eI6kx6eKmfrw9vPCEXavAr5PoZX2u2xKAQCxpiue3nt659dhnwU1JgL5UMcrkByUwKLnKaCq3q1Y1VxKuPiOkeWQUwk8lPR1nm/s1600/blender_tetrahedron.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyKvXC3e93cDodN1O1uqxhgXtjIlLU596eXIpHVNlE51eI6kx6eKmfrw9vPCEXavAr5PoZX2u2xKAQCxpiue3nt659dhnwU1JgL5UMcrkByUwKLnKaCq3q1Y1VxKuPiOkeWQUwk8lPR1nm/s400/blender_tetrahedron.png" width="400" height="227" data-original-width="1600" data-original-height="909" /></a></div><br />
<br />
Pozn.: Souřadnice na obrázku neodpovídají skutečným souřadnicím v programu Blender, jenž byl využit pro vytvoření ukázky. Souřadnice byly přeškálovány (vynásobeny konstantou) pro zvětšení při rasterizaci ve studentských frameworcích.<br />
<br />
V prvním kroku vytvoříme strukturu pro uložení vrcholů. Formálně se jedná o dvou rozměrnou matici:<br />
\[<br />
verticies = \begin{bmatrix}<br />
44 & 474 & 0 \\<br />
380 & 216 & 140 \\<br />
12 & 134 & 176 \\<br />
90 & 466 & 444 \\<br />
\end{bmatrix} <br />
\]<br />
kde řádky jsou jednotlivé vrcholy čtyřstěnu a sloupce jsou souřadnice $x, y, z$ jednotlivých vrcholů. Tuto matici převedeme do zdrojového kódu v jazyce Java jako dvourozměrné pole celočíselného datového typu. První dimenze pole bude obsahovat body (tj. řádky matice) a druhá dimenze souřadnice daných bodů (tj. sloupce matice):<br />
<pre class="java" name="code">int [][] vertices = {{44, 474, 0}, {380,216, 140}, {12, 134, 176}, {90, 466, 444}};
</pre>Dále definujme matici, která bude obsahovat informaci o hranách čtyřstěnu (byť jsou všechny vrcholy spojené hranou se všemi ostatními vrcholy). Matice bude ve sloupcích obsahovat všechny hrany (tedy 6 sloupců) a řádky indexy počátečních a koncových vrcholů hran (tedy 2 řádky). Indexy vrcholů musí korespondovat s vrcholy v poli/matici vertices! Matice bude vypadat následovně:<br />
\[<br />
verticies = \begin{bmatrix}<br />
0 & 1 & 2 & 3 & 3 & 3 \\<br />
1 & 2 & 0 & 0 & 1 & 2 \\<br />
\end{bmatrix}<br />
\]<br />
Po zapsání matice ve zdrojovém kódu, dostáváme opět dvourozměrné pole:<br />
<pre class="java" name="code">int [][] edges = {{0, 1}, {1, 2}, {2, 0}, {3, 0}, {3, 1}, {3, 2}};
</pre>Pro samotnou rasterizaci použijeme pouze $x, y$ souřadnice vrcholů, tzn. pouze první a druhý sloupec verticies. Budeme tedy iterovat skrze všechny hrany a ty následně rasterizovat pomocí algoritmu pro rasterizaci úsečky:<br />
<pre class="java" name="code">int p1, p2; // proměnné pro vrcholy hran, pro přehlednost
for(int i=0; <edges.length; i++){
p1 = edges[i][0]; // počáteční vrchol hrany
p2 = edges[i][1]; // koncový vrchol hrany
graphic.DDA(vertices[p1][0], //souřadnice x počátečního vrchol hrany
vertices[p1][1], //souřadnice y počátečního vrchol hrany
vertices[p2][0], //souřadnice x koncového vrchol hrany
vertices[p2][1]), //souřadnice y koncového vrchol hrany
G_Color.G_cBlack); //barva pro rasterizaci čtyřstěnu
}</pre>Po spuštění toho kódu, dostaneme následující výstup:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkL_XfhDspPs376UlbMukdQSjuMJcaRxsW49O-Pj8leZPPj6zwmqso7zwgux7mXabHanhtnri1KHrPXJ8F0grDQtjQBceS2hvmNS_47WYERjNCsVRSgP7K0CuonP8_DKQlJsdF84iz6ZT_/s1600/tetrahedron.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkL_XfhDspPs376UlbMukdQSjuMJcaRxsW49O-Pj8leZPPj6zwmqso7zwgux7mXabHanhtnri1KHrPXJ8F0grDQtjQBceS2hvmNS_47WYERjNCsVRSgP7K0CuonP8_DKQlJsdF84iz6ZT_/s400/tetrahedron.png" width="400" height="315" data-original-width="804" data-original-height="633" /></a></div><br />
Nyní můžeme ověřit, že náš výstup koresponduje s výstupem Blenderu. Jediný rozdíl nastává v měříku a přehození os (nezapomeňte, že Java ma počátek souřadnic v levém horním rohu). Náš výstup by měl korespondovat s okny Blenderu, které jsou označeny osami y (zelená osa) a x (červená osa). Po otočení a zmenšení dostáváme následující porovnání:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_hsG77uxzOBefH9mB-j8Ca_KLpUeuEhO-kvT7GYn1fgJ0xRHQfGLXfNrfFU76CNiNNT7yBWj7SBZ7Evl4sTD2qtLpgHj5V7OskrBozE6PTFOdRntYpADfca1GJWUBQGypxr6fqhl9XrDe/s1600/tetrahedron_comparison.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_hsG77uxzOBefH9mB-j8Ca_KLpUeuEhO-kvT7GYn1fgJ0xRHQfGLXfNrfFU76CNiNNT7yBWj7SBZ7Evl4sTD2qtLpgHj5V7OskrBozE6PTFOdRntYpADfca1GJWUBQGypxr6fqhl9XrDe/s400/tetrahedron_comparison.png" width="400" height="227" data-original-width="1600" data-original-height="909" /></a></div><br />
Vidíme, že jsou čtyřstěny (téměř) stejné. K drobné chybě došlo kvůli přeškálování souřadnic (zaokrouhlovací chyba).<br />
Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-78917484098043409952013-11-21T09:51:00.000+01:002013-11-21T09:56:10.042+01:00Komprese metodou RLERun-length encoding je jednoduchá metoda bezztrátové komprese. V článku vysvětlím, v čem spočívá, jak se s ní pracuje a ukážu příklad na obrázku BMP.
</br></br>
<h3>Motivace</h3>
Mějme řetězec 20-ti znaků
<pre>
AAABBCCCCCCCAAAAAAAA
</pre>
Dokážeme zmenšit počet znaků v řetězci, aniž bychom ztratili byť jen jedinou hodnotu, kterou obsahuje?</br>
</br>
Mějme obrázek
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrkWatT6bUkB4aBOlSItFBNCrtZBURzuz7_J195sE_3ORCRREwhvw0me2RL39sXt-QsMNNip4psH1a3Qq7Qsk8SMMolvNyaqdBknB9CnqeZPYgOu7XoqxVhZ25RbaIH9-q7BQQYb68fVmt/s1600/21.bmp" /></div></br>
Je nutné uložit jej pixelu po pixelu, aby pak mohl být ve stejné formě zobrazen?
</br></br>
<h3>Algoritmus RLE</h3>
Řetězec výše můžeme přečíst jako "á á á bé bé cé cé cé...", nebo možná přirozeněji "tři á, dvě bé, sedm cé a osm á". Stejně tak můžeme obrázek přečíst jako "tři černé, čtyři bílé, čtyři černé, pět bílých a čtyři černé". A to je ono - <strong>jednoduše nahradíme podřetězce stejných znaků jejich délkou a samotným znakem</strong>. Řetězec výše tedy bude po zakódování vypadat
<pre>
3A2B7C8A
</pre>
Vidíme, že z původních 20-ti znaků dostáváme 8, aniž bychom přišli o originál. Jsme totiž schopni z našich 8-mi znaků přesně rekonstruovat vstupní řetězec o délce 20-ti.
Algoritmus existuje ve více variantách a úpravách, které z části řeší nevhodná vstupní data. Používají se speciální symboly, které například detekují opakování celých skupin, mění směr průchodu, nebo značí nezakódovanou sekvenci. Poslední případ můžeme demonstrovat na řetězci
<pre>
AAABCDEFGHIII
</pre>
který by po zakódování neoptimalizovaným způsobem vypadal
<pre>
3A1B1C1D1E1F1G1H3I
</pre>
Docílili jsme záporné komprese, kdy z původních 13-ti znaků dostáváme 18. Zkusme zavést speciální symbol "#", který použijeme spolu s číslem reprezentující počet nezakódovaných znaků. Dostaneme
<pre>
3A7#BCDEFGH3I
</pre>
tedy 13 znaků po zakódování.
</br></br>
<h3>Implementace</h3>
<pre class="c++" name="code">
opakovani = 1;
vystup = "";
for(pro vsechny znaky - 1) {
if (znak == nasledujici znak) {
opakovani += 1;
} else {
vystup += opakovani + znak;
}
}
if (predposledni znak != posledni znak) {
vystup += "1" + posledni znak;
}
</pre>
Cyklus projde vstupní řetězec znak po znaku a ve chvíli kdy se následující znak nerovná zpracovávanému přidá k výstupnímu řetězci informaci o počtu jeho opakování. Na konci máme v proměnné <i>vystup</i> řetězec s výsledným tvarem vstupu po kompresi.
</br></br>
<h3>Příklad s BMP</h3>
Obrázek použitý nahoře jako příklad jsem v <a href="http://www.gimp.org/">Gimpu</a> uložil jako BMP a poté otevřel v HEX módu v <a href="http://www.pspad.com/cz/">PSPadu</a>. Jak vidíme, zapsal se nekomprimovaně. Byty 00 jsou pixely černé barvy a FF barvy bílé.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1Xsz1EhsFkOZne2xerK_l3vA2pGlgyhltW4s7pSt2RQXXpevt8y5EG2iK8PHI948jC0fotFm5pPBmgQZ4yRLdwzjgaq14m5aDbYe-LYmePiWCk-jyrGGXn2q4JN7ptEBtjGMfPGYb4E6D/s1600/hex1.png" /></div>
</br>
Pokud v Gimpu zaškrtneme při ukládání možnost "Run-Length Encoded" a podíváme se do souboru, uvidíme zkomprimovanou verzi.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAQzvMSyKTFJvdnxD19Fck-PIKVtlj-plZXMRSFLHaDKWQknWmr0VhnPzN6H6GHSeFFQhmzqpwYe0y9HBumLOwH7WjxKAgd0iYwyI85LlyKBx_BqEptGpVjKQaYrpi6PfU_DjrM3UYFsJk/s1600/hex2.png" /></div>
</br>
<h3>Literatura a odkazy</h3>
<a href="http://www.fileformat.info/format/bmp/egff.htm">http://www.fileformat.info/format/bmp/egff.htm</a></br>
<a href="http://www.root.cz/clanky/pcx-prakticky-implementace-komprimace-rle">http://www.root.cz/clanky/pcx-prakticky-implementace-komprimace-rle</a>Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-48625458353349691162013-11-21T09:37:00.000+01:002017-11-09T00:05:40.475+01:00Diskrétní dvourozměrná konvoluceKonvoluce je operátor, který ze dvou funkcí vytvoří funkci novou. Pro dvourozměrný případ ve spojitém prostoru vypadá následovně \[ (f*g)(x, y) = \int_{u=-\infty}^{\infty} \int_{v=-\infty}^{\infty} f(x-u, y-v) g(u, v) dudv \] V článku se ovšem budeme zabývat diskrétním tvarem, který použijeme na zpracování rastrového obrazu a který nám ve vztahu výše umožní nahradit integrály sumami. </br></br> <h3>Použití</h3>Obrázky níže ukazují možné aplikace. </br></br> <table width="100%" border="0"><tbody>
<tr> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwKKabTNsUmuu0cCtbj_4vkWNEjJf1H8yCfKEr3sAmjiy_HGQx79tMugQGdQH3qX3AZZlhz6ppHORV7fEDQh1tNhr8Un4XR-umdBRgD5rjeeW3XxK8n2V05YNIi5cAVZhaiD76f9AgciQJ/s1600/lena.png"></div></td> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_NddVUS4z47vOHQrz1_U4OmG8vJXd4rREXiX4BN4uDDNdQQRpvqpIRr9xNaDGNW3bcXTqbk6b6tepYdfBKKU61FspCb-rfoop16MWUBA7LiiHd__kCe8Ny6MzHALCmSBCRB6VLQO-ViuZ/s1600/lena-gauss.png"></div></td> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH0uUUJyRzlOMpaB64L_Vbg4pzaMv7G_j_v3DXkwDHzEFLxmmx6mFPpgOZeG5PFTu3l5tI3NoD1GCB5iN37InVFEB2ux4F8t_O_qaiPyu3G_S7bqLiSCpL22bRz2Fj65AND3_RKluU_NuR/s1600/lena-hrany.png"></div></td> </tr>
<tr> <td><span style="color: #808080;">a)</span></td> <td><span style="color: #808080;">b)</span></td> <td><span style="color: #808080;">c)</span></td> </tr>
<tr> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHhWp8Wlj6fGLDQgTzvIR9bv8t9mO4H6iG-oiQeauuTry3PXUlg4r_vbS5QDfEUJ5IsL76MeiFie1jPoSR5L6PGSfTMZKsHcn59gMJyNxt0HPnwLE-lSZVkktL2dknJNC5T38Mm18e5Uh7/s1600/lena-detHran.png"></div></td> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilijawzjih5i2yUxPxkjHMDSCLdBui-eW7AURygn5k1glG0hFEpmLRZ7B45DwZHWTX24z8wg4PJ_Ua40q_wknbByeNM7PrMUikeKv0WjzNPwx6tf4ljr7JLBlkdCMsta4YsJpJRJ7zwxt0/s1600/lena-svisle.png"></div></td> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGmBEE7Xc9MHMsD3MdSwdvpfbdHbiiiV7Xf7YzFB4QEroGmR1vbtlCg5Kqj8nZ8-X6tdfbDzSRLtTPMuj4g87H8Fi9V3wJw7vV_VI2cVBDHxkL_QZ4yiziD1tXtERYaBHDPIZkIKQ9GMc_/s1600/lena-vodo.png"></div></td> </tr>
<tr> <td><span style="color: #808080;">d)</span></td> <td><span style="color: #808080;">e)</span></td> <td><span style="color: #808080;">f)</span></td> </tr>
<tr> <td colspan="3"><span style="color: #808080;">a) vstupní obrázek; b) rozostření; b) zaostření; c) detekce hran; d) detekce vertikálních hran; e) detekce horizontálních hran</span></td> </tr>
</tbody> </table></br> Jak vidíme, dokážeme tímtéž algoritmem dosáhnout velmi odlišných výstupů. Každý pak může být zajímavý ať už vizuálním dojmem, nebo z hlediska další aplikace. </br></br> <h3>Algoritmus</h3>Mějme vstupní obrázek a jeden další velikosti $n*n$. Tomu budeme říkat maska a ono $n$ bude nejčastěji 3. Na obrázku můžete vidět graficky, co potřebujeme pro použití konvoluce. </br></br> <table width="100%" border="0"><tbody>
<tr> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKqNA3hs_yyZqrZ7u5ecpOS6OhWCt7AcgRdqDIqRX9l7NV70TRcqYahB2bql96zxEcW8n5dnLVmGEy-fwEqM2m0u1RFedwyrfa3nYzwxXJyYQxiCms1zhZm3eXox9FBT8qqO1kqxz_J_fD/s1600/img.png"></div></td> <td>\[\left( \begin{array}{ccc} 76 & 107 & 45 \\ 168 & 150 & 224 \\ 104 & 145 & 114 \end{array} \right)\]</td> </tr>
<tr> <td><span style="color: #808080;">a)</span></td> <td><span style="color: #808080;">b)</span></td> </tr>
<tr> <td colspan="2">\[\left( \begin{array}{ccc} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{array} \right)\]</td> </tr>
<tr> <td colspan="2"><span style="color: #808080;">c)</span></td> </tr>
<tr> <td colspan="3"><span style="color: #808080;">a) vstupní obrázek; b) intenzity pixelů vstupního obrázku; b) maska</span></td> </tr>
</tbody> </table></br> Masku položíme na obrázek a bod který leží pod jejím středem, budeme počítat. Jednoduše vynásobíme hodnotu jasu daného pixelu hodnotou masky, která mu svým překrytím odpovídá. Všechny takové hodnoty (pro masku $3*3$ jich bude 9) sečteme a dostaneme novou hodnotu pro náš počítaný pixel. Poté okno přesuneme na další bod a počítáme dále. Mějme na paměti, že pro obraz s více barevnými kanály než jedním, počítáme konvoluci pro každý kanál zvlášť. </br></br><h3>Matematicky</h3>Popišme si algoritmus matematicky. Následující vztah definuje diskrétní dvourozměrnou konvoluci \[ I(x,y)=\sum_{i=-k}^{k}\sum_{j=-k}^{k} f(x-i,y-j)\cdot g(i,j) \] kde $I(x,y)$ značí intenzitu výsledného pixelu na pozici $[x,y]$, $f(x,y)$ je intenzita vstupního obrázku na pozici $[x,y]$ a $h(i,j)$ intenzita bodu v masce na pozici $[i,j]$.</br> </br> Zkusme si spočítat příklad z obrázku výše. Počítáme bod $[1,1]$ (tedy ten uprostřed). Masku máme velkou 3*3 pixely, takže její indexy budou v každém směru $-1,0,1$ a $k=1$. Ve výrazu máme dvojitou sumu, ze které vidíme, že budeme sčítat 9 čísel. Zapišme si první část, kdy vypočítáme první z řady a to pixel vpravo dole. Indexy $i$ a $j$ se tedy pro první průchod budou rovnat \[ i=-k=-1 \] \[ j=-k=-1 \] po dosazení do vzorce dostaneme při středu $[1,1]$ pro políčko vpravo dole hodnotu \[ \begin{array}{lcl} I_{vd}(1,1)&=&f(1-(-1),1-(-1))\cdot h(-1,-1) \\ &=&f(2,2)\cdot h(-1,-1) \\ &=&114\cdot 1 \\ &=&114 \end{array} \] </br> <div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiMty27UMb8outIufLBQ0G3Tmkx4J8pPSkvfyn2Xz5MG1uzac-AeQuReUfUepl1LJQFcWbzwxhinKWfos2BBdJKLYXLJ5tYRwcZQk5kG5wct9Qi6cBj1J7tnX5Iaymsi33QlDZuGK8uyhx/s1600/imgmask.png"></div></br> Jak můžete vidět, pro políčko vpravo dole v původním obrázku používáme políčko vlevo nahoře v masce. Mějte na paměti, že <strong>se maska při použití otočí horizontálně a vertikálně!</strong></br> </br> Po dokončení výpočtu dostaneme hodnotu prostředního pixelu v rámci konvoluční masky. \[ I(1, 1)=76+107+45+168+150+224+104+145+114=1133 \] Vypočítaná hodnota značně přesahuje maximální intenzitu barevného kanálu, což nedokážeme vykreslit. Nabízí se řešení nahradit vyšší čísla maximální hodnotou 255. V tomto případě není řešení vhodné.</br> </br> Každý pixel ve vstupním obrázku je ohodnocen hodnotou v masce, která mu přiřadí jeho důležitost v daném okolí. Pro příklad uvažujme obrázek $300*200$ v šedé barvě, kde má každý pixel jas 125. Po aplikaci masky uvedené výše by každý pixel obrazu nabyl hodnoty $9*125=1125$. Kdybychom se rozhodli velké hodnoty jednoduše nahradit nejvyšší možnou intenzitou, což je 255, dostali bychom bílý obdelník. Jak vidíme, výsledek rozostření šedého obrázku by pravděpodobně neměl být obrázek bílý. Zkusme vyzkoušet, co se stane když se zaměříme pouze na poměr hodnot v masce a na jejich součet. Nechejme všechny hodnoty stejné a trvejme na podmínce jejich součtu, který musí být roven jedné. Dostaneme tedy pole $3*3$ kde v každé buňce bude $1/9$. Po aplikaci této masky na náš šedý obrázek, dostaneme zpět tentýž.</br> </br> Přidáme tedy k výpočtu intenzity jeden krok, kdy výslednou hodnotu vydělíme součtem hodnot v masce. Tomuto procesu se říká normalizace a budeme ho provádět při konvoluci vždy, když bude součet hodnot v masce větší než jedna. </br></br> <h3>Implementace</h3>Schématicky může implementace vypadat takto. <pre class="c++" name="code">vahy = 0;
for(i = -K; i <= K; i++) {
for(j = -K; j <= K; j++) {
vahy += maska[1+i][1+j];
}
}
if (vahy < 1) vahy = 1;
for(radek = 0; radek < VYSKA; radek++) {
for(sloupec = 0; sloupec < SIRKA; sloupec++) {
soucet = 0;
for(i = -K; i <= K; i++) {
for(j = -K; j <= K; j++) {
intenzita = vstupni(radek + i, sloupec + j);
soucet += intenzita * maska[1+i][1+j];
}
}
vystupni(radek, sloupec) = round(soucet/vahy);
}
}
</pre>V principu potřebujeme dostat součet všech násobků pixelů v masce <i>maska</i> spolu s odpovídajícími pixely ve vstupním obrázku <i>vstupni</i>. Vypočítanou hodnotu poté vydělíme součtem hodnot v masce (normalizace). Všimněte si, že nová hodnota je vložena do nového obrázku <i>vystupni</i>. Toto je velice důležité! Kdyby byla vložena do <i>vstupni</i> , každá další hodnota by v sobě zahrnovala výpočet s už zpracovaným pixelem. Počítáme tedy s hodnotami z původního obrázku a nové vkládáme do jiného. </br></br> <h3>Různé masky</h3>Na závěr článku se vraťme k obrázkům v první podkapitole a ukažme, jaké masky byly použity pro jejich vytvoření. </br></br> <table width="100%" border="0"><tbody>
<tr> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_NddVUS4z47vOHQrz1_U4OmG8vJXd4rREXiX4BN4uDDNdQQRpvqpIRr9xNaDGNW3bcXTqbk6b6tepYdfBKKU61FspCb-rfoop16MWUBA7LiiHd__kCe8Ny6MzHALCmSBCRB6VLQO-ViuZ/s1600/lena-gauss.png"></div></td> <td>\[\left( \begin{array}{ccc} 1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1 \end{array} \right)\]</td> <td> Gaussův filtr </td> </tr>
<tr> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH0uUUJyRzlOMpaB64L_Vbg4pzaMv7G_j_v3DXkwDHzEFLxmmx6mFPpgOZeG5PFTu3l5tI3NoD1GCB5iN37InVFEB2ux4F8t_O_qaiPyu3G_S7bqLiSCpL22bRz2Fj65AND3_RKluU_NuR/s1600/lena-hrany.png"></div></td> <td>\[\left( \begin{array}{ccc} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0 \end{array} \right)\]</td> <td> zvýraznění hran </td> </tr>
<tr> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHhWp8Wlj6fGLDQgTzvIR9bv8t9mO4H6iG-oiQeauuTry3PXUlg4r_vbS5QDfEUJ5IsL76MeiFie1jPoSR5L6PGSfTMZKsHcn59gMJyNxt0HPnwLE-lSZVkktL2dknJNC5T38Mm18e5Uh7/s1600/lena-detHran.png"></div></td> <td>\[\left( \begin{array}{ccc} 0 & -1 & 0 \\ -1 & 4 & -1 \\ 0 & -1 & 0 \end{array} \right)\]</td> <td> operátor Laplace </td> </tr>
<tr> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilijawzjih5i2yUxPxkjHMDSCLdBui-eW7AURygn5k1glG0hFEpmLRZ7B45DwZHWTX24z8wg4PJ_Ua40q_wknbByeNM7PrMUikeKv0WjzNPwx6tf4ljr7JLBlkdCMsta4YsJpJRJ7zwxt0/s1600/lena-svisle.png"></div></td> <td>\[\left( \begin{array}{ccc} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{array} \right)\]</td> <td> Sobelův operátor (svislé hrany) </td> </tr>
<tr> <td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGmBEE7Xc9MHMsD3MdSwdvpfbdHbiiiV7Xf7YzFB4QEroGmR1vbtlCg5Kqj8nZ8-X6tdfbDzSRLtTPMuj4g87H8Fi9V3wJw7vV_VI2cVBDHxkL_QZ4yiziD1tXtERYaBHDPIZkIKQ9GMc_/s1600/lena-vodo.png"></div></td> <td>\[\left( \begin{array}{ccc} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{array} \right)\]</td> <td> Sobelův operátor (vodorovné hrany) </td> </tr>
</tbody> </table></br> <strong>Poznámka</strong> </br> Na spodní tři obrázky byla použitá dodatečná úprava. K intenzitě každého pixelu byla v každém kanálu přidána hodnota 128. </br></br> <h3>Literatura a odkazy</h3>HLAVÁČ, V.; SEDLÁČEK, M. Zpracování signálu a obrazu. Vydavatelství CVUT, 2005.</br> KOLCUN, A. Základy počítačovej grafiky. Učební texty, Ostrava 2006.</br> ŽÁRA, J.; SOCHOR, J.; BENEŠ, B.; FELKEL, P. Moderní počítačová grafika. Computerpress, Brno 2004.</br> </br> <a href="http://cs.wikipedia.org/wiki/Konvoluce">http://cs.wikipedia.org/wiki/Konvoluce</a></br> <a href="http://bruxy.regnet.cz/fel/36ACS/konvoluce.pdf">http://bruxy.regnet.cz/fel/36ACS/konvoluce.pdf</a></br> <a href="http://www.songho.ca/dsp/convolution/convolution2d_example.html">http://www.songho.ca/dsp/convolution/convolution2d_example.html</a></br> </br> <a href="http://homepages.inf.ed.ac.uk/rbf/HIPR2/convolutiondemo.htm">http://homepages.inf.ed.ac.uk/rbf/HIPR2/convolutiondemo.htm</a> - appletAnonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-40569044829828769502013-11-21T09:26:00.000+01:002013-11-24T19:50:02.427+01:00Grafická hádankaPojďme vyzkoušet, co se stane se dvěma totožnými obrázky po aplikaci několika aritmetických operací.
</br></br>
<table width="100%" border="0">
<tbody>
<tr>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>=</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
</tr>
</tbody>
</table>
</br>
Řekněme, že chceme oba trochu prosvětlit. Vynásobme tedy každý z nich sebou samým.
</br></br>
<table width="100%" border="0">
<tbody>
<tr>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>$\cdot$</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>=</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>$\cdot$</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
</tr>
</tbody>
</table>
</br>
Vstupní obrázek vypadá z hlediska čísel takto
</br>
\[\left( \begin{array}{cccccccccc}
15 & 15 & 15 & 0 & 0 & 0 & 0 & 15 & 15 & 15 \\
15 & 15 & 0 & 15 & 15 & 15 & 15 & 0 & 15 & 15 \\
15 & 0 & 15 & 15 & 15 & 15 & 15 & 15 & 0 & 15 \\
0 & 15 & 0 & 0 & 15 & 15 & 0 & 0 & 15 & 0 \\
0 & 15 & 0 & 0 & 15 & 15 & 0 & 0 & 15 & 0 \\
0 & 15 & 15 & 15 & 15 & 15 & 15 & 15 & 15 & 0 \\
0 & 15 & 15 & 0 & 0 & 0 & 0 & 15 & 15 & 0 \\
15 & 0 & 15 & 15 & 15 & 15 & 15 & 15 & 0 & 15 \\
15 & 15 & 0 & 15 & 15 & 15 & 15 & 0 & 15 & 15 \\
15 & 15 & 15 & 0 & 0 & 0 & 0 & 15 & 15 & 15
\end{array} \right)\]
</br>
Pokud spolu vynásobím nuly, dostanu novou hodnotu pixelu rovnu 0. Pokud vynásobím patnáctky, dostanu 225.
</br></br>
<table width="100%" border="0">
<tbody>
<tr>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnvqNWbjZm2U9sn1MyKrTCq2pYhlt038T3aGUZaeY8jgLVy-aXPx-76Cg9rh_byXpEekO9KgLcs8jfwqx0gCvqyo-7-2A1XE8GpG5vVvmnVG0px7JXSKnSEUE96CjT4NbLv3vgU6LDNQSR/s1600/light.png" /></div></td>
<td>=</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnvqNWbjZm2U9sn1MyKrTCq2pYhlt038T3aGUZaeY8jgLVy-aXPx-76Cg9rh_byXpEekO9KgLcs8jfwqx0gCvqyo-7-2A1XE8GpG5vVvmnVG0px7JXSKnSEUE96CjT4NbLv3vgU6LDNQSR/s1600/light.png" /></div></td>
</tr>
</tbody>
</table>
</br>
Nový obrázek vypadá číselně takto
</br>
\[\left( \begin{array}{cccccccccc}
225 & 225 & 225 & 0 & 0 & 0 & 0 & 225 & 225 & 225 \\
225 & 225 & 0 & 225 & 225 & 225 & 225 & 0 & 225 & 225 \\
225 & 0 & 225 & 225 & 225 & 225 & 225 & 225 & 0 & 225 \\
0 & 225 & 0 & 0 & 225 & 225 & 0 & 0 & 225 & 0 \\
0 & 225 & 0 & 0 & 225 & 225 & 0 & 0 & 225 & 0 \\
0 & 225 & 225 & 225 & 225 & 225 & 225 & 225 & 225 & 0 \\
0 & 225 & 225 & 0 & 0 & 0 & 0 & 225 & 225 & 0 \\
225 & 0 & 225 & 225 & 225 & 225 & 225 & 225 & 0 & 225 \\
225 & 225 & 0 & 225 & 225 & 225 & 225 & 0 & 225 & 225 \\
225 & 225 & 225 & 0 & 0 & 0 & 0 & 225 & 225 & 225
\end{array} \right)\]
</br>
Teď ho na každé straně odečtěme.
</br></br>
<table width="100%" border="0">
<tbody>
<tr>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnvqNWbjZm2U9sn1MyKrTCq2pYhlt038T3aGUZaeY8jgLVy-aXPx-76Cg9rh_byXpEekO9KgLcs8jfwqx0gCvqyo-7-2A1XE8GpG5vVvmnVG0px7JXSKnSEUE96CjT4NbLv3vgU6LDNQSR/s1600/light.png" /></div></td>
<td>-</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnvqNWbjZm2U9sn1MyKrTCq2pYhlt038T3aGUZaeY8jgLVy-aXPx-76Cg9rh_byXpEekO9KgLcs8jfwqx0gCvqyo-7-2A1XE8GpG5vVvmnVG0px7JXSKnSEUE96CjT4NbLv3vgU6LDNQSR/s1600/light.png" /></div></td>
<td>=</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnvqNWbjZm2U9sn1MyKrTCq2pYhlt038T3aGUZaeY8jgLVy-aXPx-76Cg9rh_byXpEekO9KgLcs8jfwqx0gCvqyo-7-2A1XE8GpG5vVvmnVG0px7JXSKnSEUE96CjT4NbLv3vgU6LDNQSR/s1600/light.png" /></div></td>
<td>-</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnvqNWbjZm2U9sn1MyKrTCq2pYhlt038T3aGUZaeY8jgLVy-aXPx-76Cg9rh_byXpEekO9KgLcs8jfwqx0gCvqyo-7-2A1XE8GpG5vVvmnVG0px7JXSKnSEUE96CjT4NbLv3vgU6LDNQSR/s1600/light.png" /></div></td>
</tr>
</tbody>
</table>
</br>
Dostaneme nuly, což odpovídá černým plochám.</br>
</br>
Matematicky můžeme říct, že pokud je náš původní obrázek $A$, pak nový obrázek bude $A\cdot A$ tedy $A^2$. Znázorněný rozdíl tedy můžeme přepsat na
\[
A^2-A^2=A^2-A^2
\]
Aplikujme jeden ze základních vzorců
\[
A^2-B^2=(A-B)(A+B)
\]
a pravidlo vytýkání, pro dosažení výrazu
\[
A(A-A)=(A-A)(A+A)
\]
Vraťme se k obrázkům. Levá strana bude vypadat
</br></br>
<table width="100%" border="0">
<tbody>
<tr>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td><td>$\cdot$</td>
<td>(</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>-</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>)</td>
</tr>
</tbody>
</table>
</br>
a pravá strana
</br></br>
<table width="100%" border="0">
<tbody>
<tr>
<td>(</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>-</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>)</td>
<td>$\cdot$</td>
<td>(</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>+</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>)</td>
</tr>
</tbody>
</table>
</br>
Dostaneme po úpravách vlevo i vpravo černou plochu, což odpovídá. Protože máme na obou stranách stejné výrazy, vykraťme je.
</br></br>
<table width="100%" border="0">
<tbody>
<tr>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>=</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>+</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
</tr>
</tbody>
</table>
</br>
Sečteme členy na pravé straně a máme výsledek.
</br></br>
<table width="100%" border="0">
<tbody>
<tr>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJxYV4GBaNyTJZDLDBYoO-c8iElh0oOH5-JC0hdxSFTV7y66V-2XS8pFinHywjNn7F57ZhlpMdA-z0mWmc-Z7_dtlYbhaAMM_9WmmSL-fJCtLRkcg-PtHmWhCr_RDWzHYMlOatBQHry2o/s1600/dark.png" /></div></td>
<td>=</td>
<td><div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjenvFjZ1hvDJd0mg6V9I5Q7hLWL5kRO7NcPJyCnX4eNVBMM9XVYNXFTYDkIh7nC1gfUthunXAVye4IOCf5KutRnU_YAttfwDTMTKKEfBtKaebH0vg1qvOv9UujVV6u1CvKJWykjIwb0H7q/s1600/final.png" /></div></td>
</tr>
</tbody>
</table>
</br>
Na první pohled všechno sedí. Máme dva totožné obrázky, které se rovnají tak jako na začátku. Jak by taky ne, dělali jsme na obou stranách ty samé úpravy.</br>
</br>
<strong>Ovšem pozor!</strong> :)
</br></br>
Podívejme se pořádně na výsledný obrázek vpravo. I když vypadá stejně, součet na něm zanechal stopy. V číslech máme
</br>
\[\left( \begin{array}{cccccccccc}
30 & 30 & 30 & 0 & 0 & 0 & 0 & 30 & 30 & 30 \\
30 & 30 & 0 & 30 & 30 & 30 & 30 & 0 & 30 & 30 \\
30 & 0 & 30 & 30 & 30 & 30 & 30 & 30 & 0 & 30 \\
0 & 30 & 0 & 0 & 30 & 30 & 0 & 0 & 30 & 0 \\
0 & 30 & 0 & 0 & 30 & 30 & 0 & 0 & 30 & 0 \\
0 & 30 & 30 & 30 & 30 & 30 & 30 & 30 & 30 & 0 \\
0 & 30 & 30 & 0 & 0 & 0 & 0 & 30 & 30 & 0 \\
30 & 0 & 30 & 30 & 30 & 30 & 30 & 30 & 0 & 30 \\
30 & 30 & 0 & 30 & 30 & 30 & 30 & 0 & 30 & 30 \\
30 & 30 & 30 & 0 & 0 & 0 & 0 & 30 & 30 & 30
\end{array} \right)\]
</br>
Co se stalo a jak je to možné?
</br></br>
<h3>Otázka</h3>
<span style="color: red;">Kde máme ve výpočtu chybu? Pokud tam chyba není, proč se výsledný obrázek liší od původního?</span>Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-42363904034932348532013-11-21T08:47:00.000+01:002013-11-21T09:20:19.912+01:00Animal morph v GimpuUrčitě už jste viděli obrázky několika zvířat spojených v jedno.
</br></br>
<table width="100%" border="0" align="center"><tbody>
<tr><td>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2ZzzQ4XbRPB5fot59DZpuG6TSbffWqoZEVl-RqVWQJXQxTd6hYueVxsB9Ntsv2PfbEmVInwel8hRRukqMx0mVQQKp_oAcM1AxxCrTjrCGvggXtki_DPEFfJKQc7KDFsOBeEPPrmHRAIay/s1600/konuikentjejm2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2ZzzQ4XbRPB5fot59DZpuG6TSbffWqoZEVl-RqVWQJXQxTd6hYueVxsB9Ntsv2PfbEmVInwel8hRRukqMx0mVQQKp_oAcM1AxxCrTjrCGvggXtki_DPEFfJKQc7KDFsOBeEPPrmHRAIay/s200/konuikentjejm2.jpg" /></a></div>
</td>
<td>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghvUmnru0bSBGqQGfaCizKHdCqpQTCs7-PWno3iAwvQJQiffP20VfxUViu2xo-x1QdgQY7MzIAeouj4FjCkn1d0j-fmw9zE5IKEj7mwdsB6JvVZz8wm3Jiu7cGEPIYqyP_OcK3tWOXJ7S9/s1600/photoshop5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghvUmnru0bSBGqQGfaCizKHdCqpQTCs7-PWno3iAwvQJQiffP20VfxUViu2xo-x1QdgQY7MzIAeouj4FjCkn1d0j-fmw9zE5IKEj7mwdsB6JvVZz8wm3Jiu7cGEPIYqyP_OcK3tWOXJ7S9/s200/photoshop5.jpg" /></a></div>
</td>
</tr>
<tr><td>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_t5PWBwTPR8zhXrNp5FRL-XW4aXOi_Y-gBkvyCd4WYJbGq3YSrdzEnRjm74lIsG-OxQBmS5YftjvFTCVie_e66smgzrLtyWFSwzVmyZAz-hIEMBztzb0ctWfVctskWgK7C5Fyl62gIv1p/s1600/dog-bird.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_t5PWBwTPR8zhXrNp5FRL-XW4aXOi_Y-gBkvyCd4WYJbGq3YSrdzEnRjm74lIsG-OxQBmS5YftjvFTCVie_e66smgzrLtyWFSwzVmyZAz-hIEMBztzb0ctWfVctskWgK7C5Fyl62gIv1p/s200/dog-bird.jpg" /></a></div>
</td> <td>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiiGtX83LKmPlFLqBEMtr8Rytr4_uymsJEnK_zScMhjlII5QCKtVGpF8AGRB5aAtXY1lNWK5Bq1eH_yNoYgDpy-k6kusD6SAXby1-TkuC8UAfygugrgg28o_xMUS2bFui-ELyQDPOnO9g/s1600/catcow.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiiGtX83LKmPlFLqBEMtr8Rytr4_uymsJEnK_zScMhjlII5QCKtVGpF8AGRB5aAtXY1lNWK5Bq1eH_yNoYgDpy-k6kusD6SAXby1-TkuC8UAfygugrgg28o_xMUS2bFui-ELyQDPOnO9g/s200/catcow.jpg" /></a></div>
</td> </tr>
</tbody> </table>
</br>
Udělejme si také takové s použitím Gimpu.
</br></br>
<h3>Začínáme</h3>
Použijeme tyto obrázky
</br></br>
<table width="100%" border="0"><tbody>
<tr> <td>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWOV0gw7I1WX6tzM8icPxgrsT5RohcuyjHe2ZOzW_xWTmMLxJHzWGB5aO_sKlVdGDLS4C-7FM0omYgvKrVb59inV-jsBy-_hbow7MsY_be7XK7IR0RBvIshi4l_jLqr7leDfQIGpVCNkjP/s1600/brown-rabbit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWOV0gw7I1WX6tzM8icPxgrsT5RohcuyjHe2ZOzW_xWTmMLxJHzWGB5aO_sKlVdGDLS4C-7FM0omYgvKrVb59inV-jsBy-_hbow7MsY_be7XK7IR0RBvIshi4l_jLqr7leDfQIGpVCNkjP/s200/brown-rabbit.jpg" /></a></div>
</td> <td>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIT1ALWQUcYa15sM7vfBURlmvXFZ9slzs5_Mv0ye_5lF67XmDGrSHnuHStHvl278-m7f5NSL3zJaY-eiq0K_6HHhJqzawa8iM-ho25FfCKkQITd1pa9hweAplNVeVTzFSH5Awak4M7tL8F/s1600/fluffy_penguin.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIT1ALWQUcYa15sM7vfBURlmvXFZ9slzs5_Mv0ye_5lF67XmDGrSHnuHStHvl278-m7f5NSL3zJaY-eiq0K_6HHhJqzawa8iM-ho25FfCKkQITd1pa9hweAplNVeVTzFSH5Awak4M7tL8F/s200/fluffy_penguin.jpg" /></a></div>
</td> </tr>
</tbody> </table>
a <a href="http://www.gimp.org/downloads/">Gimp</a> ve verzi 2.6.11 (i v jiných verzích by se postup nemusel výrazně lišit).
Našim cílem bude dosáhnout spojení obou zvířat na použitých obrázcích.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWrbW70ocx8v2xPQ9ye_04lcDnhr_p_gTZ6qDx04AmhyDSR1SFUs3-s4aN1_UpM0kFhBfGgQboBPli-LotGxUn8hczsUAbH7BO8U4d6a3WIshTDPfav-tUChavFLG35qVAPiNYOfcZTftR/s1600/388358_2175522162126_1668997432_31682514_2075740294_n.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWrbW70ocx8v2xPQ9ye_04lcDnhr_p_gTZ6qDx04AmhyDSR1SFUs3-s4aN1_UpM0kFhBfGgQboBPli-LotGxUn8hczsUAbH7BO8U4d6a3WIshTDPfav-tUChavFLG35qVAPiNYOfcZTftR/s1600/388358_2175522162126_1668997432_31682514_2075740294_n.jpg" /></a></div>
</br>
<h3>Přípravy</h3>
V prvním kroku připravíme oba obrázky.
<ul>
<li>zkopírujeme do schránky obrázek tučňáka a vložíme do Gimpu</li>
<ul>
<li><i>Upravit -> Vložit jako -> Nový obrázek</i></li>
</ul>
<li>zkopírujeme do schránky obrázek králíka a vložíme jako novou vrstvu</li>
<ul>
<li><i>Upravit -> Vložit jako -> Nová vrstva</i></li>
</ul>
</ul>
Ujistěte se, že máte viditelný dialog "Vrstvy" - <i>Okno -> Připojitelné dialogy -> Vrstvy</i>. Výřez vaši pracovní plochy by teď měl vypadat nějak takto
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrxXujYOFggZpUTs8A7umYRvEgjk6DyHo_rCSOKvgmJWFvxq4kE-6Qsf652PaJNOdKoTLu2Wm47QQnthrBOAKxQoGkJpxgifi9SzMxsq3ZLXDyfkfEvhyphenhyphenAKUfz1La6Gv_9Y7pvnkP5uOIQ/s1600/first-step.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrxXujYOFggZpUTs8A7umYRvEgjk6DyHo_rCSOKvgmJWFvxq4kE-6Qsf652PaJNOdKoTLu2Wm47QQnthrBOAKxQoGkJpxgifi9SzMxsq3ZLXDyfkfEvhyphenhyphenAKUfz1La6Gv_9Y7pvnkP5uOIQ/s320/first-step.png" /></a></div>
</br>
Teď potřebujeme oříznout hlavu našeho králíka. Můžeme použít nástroj "Volný výběr" (klávesová zkratka <strong>F</strong>), nebo jako já "Výběr pomocí inteligentního hledání hran" (<strong>I</strong>). Až budete s výběrem spokojeni invertujte jej <i>Vybrat -> Invertovat</i> (<strong>Ctrl + I</strong>) a stiskněte klávesu <strong>Delete</strong>.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Q3cdN1KEIlC9ZMsYEVPxB6eyHDsMe4hsQF4wIyn-jfHJf42zjM0VPyycu3dhgzK2IvA0ARTI_BQbANUpU56w7dIWQ1cew8k8OGjTi_MfdnaVEW6zA-i5_IWEF_lU69tfp7h0xCSl_Tb0/s1600/second-step.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Q3cdN1KEIlC9ZMsYEVPxB6eyHDsMe4hsQF4wIyn-jfHJf42zjM0VPyycu3dhgzK2IvA0ARTI_BQbANUpU56w7dIWQ1cew8k8OGjTi_MfdnaVEW6zA-i5_IWEF_lU69tfp7h0xCSl_Tb0/s320/second-step.png" /></a></div>
</br>
V této chvíli musíme napasovat hlavu králíka na tělo tučňáka. Když se o to pokusíme, zjistíme, že nám uši zasahují mimo obrázek. Skryjeme tedy vrstvu s králíkem (ikonka oka) a vybereme vrstvu s tučňákem.
<ul>
<li>změníme velikost plátna</li>
<ul>
<li><i>Obrázek -> Velikost plátna... -> (klikněte na ikonku řetězu) -> Výška = 554</i></li>
</ul>
<li>vytvoříme místo nad tučňákem</li>
<ul>
<li><i>(v náhledovém okně chytíme obrázek a potáhneme tak dolů jak to jen půjde) -> Změnit velikost</i></li>
</ul>
<li>zaplníme místo nebem</li>
<ul>
<li><i>Vybereme klonovací razítko (<strong>C</strong>) a vyplníme novou plochu vzorem nad tučňákovou hlavou</i></li>
</ul>
</ul>
Výsledek by měl vypadat nějak takto
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMcZQ2Rh_PPpAZNsEkNs1BkIXVo354vDHgmxMBTn_3psMsRgCQoGYXnd1bKWA-1uCO21gV02jKwMNVbS0f664fjWG3ukLFMIupDLo4-5dc0aWRgRCsHzgneISSmeYRuy736u9Z5CcSbt2E/s1600/third-step.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMcZQ2Rh_PPpAZNsEkNs1BkIXVo354vDHgmxMBTn_3psMsRgCQoGYXnd1bKWA-1uCO21gV02jKwMNVbS0f664fjWG3ukLFMIupDLo4-5dc0aWRgRCsHzgneISSmeYRuy736u9Z5CcSbt2E/s320/third-step.png" /></a></div>
</br>
<h3>Úprava barev a sloučení</h3>
Pomocí nástrojů "Přesun" (<strong>M</strong>) a "Škálování" (<strong>Shift + T</strong>) posuneme hlavu králíka kam patří a změníme její velikost, aby zapadla.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1gb4Cxj202ZEwvaoWyto1PdG9-S4DX0YppinpuCohDWa4om7vknQjduafHsZg16Tm11_W4wVZkQQ93dJ4owtnjedJBcxBVhz-u0AliVjyrSgHbsquwk31BmODiZNXXHT6DlE678mm-Fbj/s1600/fourth-step.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1gb4Cxj202ZEwvaoWyto1PdG9-S4DX0YppinpuCohDWa4om7vknQjduafHsZg16Tm11_W4wVZkQQ93dJ4owtnjedJBcxBVhz-u0AliVjyrSgHbsquwk31BmODiZNXXHT6DlE678mm-Fbj/s320/fourth-step.png" /></a></div>
</br>
V této chvíli je třeba doladit barvy. Otevřeme si dialog <i>Barvy -> Odstín-sytost</i> a úpravou hodnot <i>Odstín, Světlost, Sytost</i> docílíme barevné shody. Nastavování je otázka cviku a ze začátku je třeba vyzkoušet, co bude vypadat nejlépe. Já vybral <i>180, 0, -84</i>. Dále se mi nezdála nepravidelnost kolem uší a pár detailů, které jsem upravil klonovacím razítkem a gumou. Výsledek vypadá takto
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigcDcqnKke-HWPmiCXoZ6zrLRWO2cWeP9QvABhJYH72DjuhlvwKRzRQEBx2Sxz6KVJswGzmoKDFYNFPTuoXFyWvp9-duh8FQEtaSC2mbK0nEOBQN2vGUiqhbQTvchivcZ-sBkZMEZU24Aq/s1600/fifth-step.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigcDcqnKke-HWPmiCXoZ6zrLRWO2cWeP9QvABhJYH72DjuhlvwKRzRQEBx2Sxz6KVJswGzmoKDFYNFPTuoXFyWvp9-duh8FQEtaSC2mbK0nEOBQN2vGUiqhbQTvchivcZ-sBkZMEZU24Aq/s320/fifth-step.png" /></a></div>
</br>
Dále jsem ručně vybral okraje a rozmazal je přes <i>Filtry -> Rozostření -> Gaussovské rozostření...</i> a poté roztřepil, abych jim dodal podobný feeling jako má tělo tučňáka <i>Filtry -> Šum -> Roztřepení...</i>.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5cq8fOqwfn_X-rrN8LaSSYWvyy4wWnhBEu0NWvXbr7l0FSifG263hxdYYEWgFcx6hpMSkxO95NnYEO_I2WSEjo7tcOgK9Uapgr8_uiTitGUzpOU-76PC4CXkMY_70J2eTWGYOhk0IRSMA/s1600/sixth-step.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5cq8fOqwfn_X-rrN8LaSSYWvyy4wWnhBEu0NWvXbr7l0FSifG263hxdYYEWgFcx6hpMSkxO95NnYEO_I2WSEjo7tcOgK9Uapgr8_uiTitGUzpOU-76PC4CXkMY_70J2eTWGYOhk0IRSMA/s320/sixth-step.png" /></a></div>
</br>
Sloučíme obě vrstvy <i>(pravým tlačítkem na vrstvu s hlavou králíka) -> Sloučit dolů</i> a přistoupíme k závěrečným úpravám.
</br></br>
<h3>Finální úpravy</h3>
Musíme hladce napojit hlavu na tělo. Pro tento účel jsem vybral nástroj "Léčení" (<strong>H</strong>) se štětcem <i>Circle fuzzy</i> a krytím 70. Jako vzor (<strong>Ctrl + levý klik</strong>) jsem vybral opeření pod krkem a několikrát poklepal na spojnici hlavy a těla, než jsem byl spokojen s výsledkem.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSmx20wu5GgP08cv9XHlHIKbbeAZXiduvgTZXnenZu2liivSQME1U2FQ_JjLlePWrDaHNZQ0z2BMX4UeDgWmLCCUKNP_i-mC-fyQUYWC5XM3sY0Gv5zTRgtGPXZFSpwbsnzeF5qSsRWBCg/s1600/seventh-step.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSmx20wu5GgP08cv9XHlHIKbbeAZXiduvgTZXnenZu2liivSQME1U2FQ_JjLlePWrDaHNZQ0z2BMX4UeDgWmLCCUKNP_i-mC-fyQUYWC5XM3sY0Gv5zTRgtGPXZFSpwbsnzeF5qSsRWBCg/s320/seventh-step.png" /></a></div>
</br>
Ještě pár úprav kontrastu, jasu, doladění několika míst "Léčením" a máme výsledek
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRK6fZZd3DVy78RXP3FH8pqMosY3Jv-MyVOZoMs4vYcJiXCi98IHxIo94AakumZck5zI-9ianjjfsazUQLSgcWMNAtgNbAjjaBAp-xfNbKl85urRwSEEhipuKbE1EA7DrzQioUgOj_5TdJ/s1600/result.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRK6fZZd3DVy78RXP3FH8pqMosY3Jv-MyVOZoMs4vYcJiXCi98IHxIo94AakumZck5zI-9ianjjfsazUQLSgcWMNAtgNbAjjaBAp-xfNbKl85urRwSEEhipuKbE1EA7DrzQioUgOj_5TdJ/s400/result.png" /></a></div>
</br>
<strong>Poznámka na závěr</strong>
</br>
Tučňákokrálíka nahoře jsem vytvořil už před nějakou dobou. Napsat tutoriál mě napadlo později kdy jsem neměl k dispozici jednotlivé kroky, takže jsem vše udělal znovu. To je důvod, proč se liší výsledný obrázek dole od obrázku nahoře. Do článku je dávám oba, aby šlo vidět, jak v podstatě stejným postupem můžeme dostat různé výsledky. Zároveň je třeba upozornit, že nejde o profesionální, ani jediný způsob, ale pouze o demonstraci jedné jednoduché cesty jak animal morphu dosáhnout.
</br></br>
<h3>Zdroje a literatura</h3>
<a href="http://www.zonnigforum.nl">http://www.zonnigforum.nl</a> - obrázky na začátku</br>
<a href ="http://www.instructables.com/id/How-to-morph-animals-using-GIMP-free-software">http://www.instructables.com/id/How-to-morph-animals-using-GIMP-free-software</a> - článek v angličtině na stejné témaAnonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-84271884843822142662013-11-14T14:44:00.000+01:002013-11-14T15:01:17.211+01:00Rasterizace úsečky algoritmem DDAAlgoritmus DDA (Digital Differential Analyzer) nám nabízí přímé vykreslení úsečky s použitím základního vzorce
\[
y=ax+b
\]
Více o přímce, či úsečce, najdete <a href="http://cg.tucna.net/2011/11/primka-a-derivace/" title="Přímka a derivace">zde</a>.
</br></br>
<h3>DDA</h3>
Mějme přímku
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEij1n14kw06CKAbA-XxOE94_VtwhxeMp1hz5hbhHyw56BpX0-XPEjaYboUoGzrS0qodCyVA7AgKFSd_jfqDpGqFrNodnW5MA515XL4ztBCw3jIkWc_zqCKFM3gKbVYDUs5dZI8dbQ7XKSnH/s1600/usecka.png" /></div>
</br>
pro kterou platí
\[
\Delta_y=y_B-y_A=1-0=1
\]
\[
\Delta_x=x_B-x_A=3-0=3
\]
tedy
\[
a=\frac{\Delta_y}{\Delta_x}=\frac{1}{3}
\]
Pro každý následující bod tedy musíme přidat jednu jednotku ve směru $y$ a tři ve směru $x$. Nezapomeňte, že pokud vykreslíte přímku jen mezi body $A$ a $B$ tak dostanete úsečku.
Všimněte si, že není důležitá přesná velikost $\Delta_y$ a $\Delta_x$, ale jejich vzájemný poměr. Pro tyto dvě směrnice
\[
a=\frac{2}{6}
\]
\[
a=\frac{0,5}{1,5}
\]
dostaneme úplně stejnou přímku, která prochází počátkem, jak můžete vidět na obrázku.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgro2s3_rkKn_WKaP23fe1_NrqUmOYj2KMAMl5WIV-um0aBZiBU0F3FLFaPD95RkBBh63dyv4d0tj6cPeaJlCcPKSexAdPTFETZG0H6KUiB5DrLCwAjEUxPZ3q5oDRN8gtQNc3hSbGY2kcy/s1600/usecka2.png" /></div>
</br>
Rasterizací dle DDA posuneme následující bod o jednu jednotku v jednom směru pevně a ve druhém směru pak v závislosti na směrnici.
</br></br>
<h3>Rasterizace úseček se sklonem <= 45°</h3>
Dle DDA posuneme následující bod pouze o jednu jednotku $x$ a tomu odpovídající $y$ dle směrnice. Zkusme pro přímku výše vypočítat $\Delta_y$ pokud bude $\Delta_x=1$.
\[
a=\frac{1/3}{3/3}\doteq\frac{0,333}{1}
\]
nebo prostě
\[
a=\frac{1}{3}\doteq0,333
\]
Obecně pak můžeme říct, že
\[
x_{i}=x_{i-1}+1; y_{i}=y_{i-1}+a
\]
Úsečku $AB$ bude rasterizovat pro $x=0..3$.
</br></br>
<table align="center" border="1" cellpadding="3" cellspacing="0">
<tbody>
<tr>
<td><strong>x</strong></td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td><strong>y</strong></td>
<td>0</td>
<td>0,3 (0)</td>
<td>0,6 (1)</td>
<td>0,9 (1)</td>
</tr>
</tbody>
</table>
</br>
Do rastru nemůžeme přímo zanést body na reálných souřadnicích, musíme tedy zaokrouhlovat. Finální rasterizovaná úsečka je na obrázku.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYkWGRWQnvejWiwQB9dFN4F9qKeu5VqJKgRwLuXQ1LFUuFQ9syw6ac_I_oZc4kN9SkYnZ_-2Uvv4RNwz0TPN9rAQLtzx5aiTp0_x7izgtzPcF7BMFq6W0myt9YbXw4bp8BMkX_-WcKgoio/s1600/usecka3.png" /></div>
</br>
<h4>Implementace</h4>
<pre class="c++" name="code">
smernice = (yB-yA) / (xB-xA);
y = yA;
for(x = xA; x <= xB; x++) {
putPixel(x,y);
y = y + smernice;
}
</pre>
Jednoduše kreslíme od počátečního <i>x</i> ke koncovému <i>x</i> a v každém kroku přičteme <i>smernice</i> k <i>y</i>. Je důležité dát pozor, aby <strong>první zadaný bod měl souřadnici $x$ menší než druhý</strong>. Pokud by tomu tak nebylo, cyklus by neproběhl! Je tedy na začátku nutné body případně prohodit. Pro úsečku jako takovou je v našem případě jedno, je-li zadána $AB$ nebo $BA$.
</br></br>
<h3>Rasterizace úseček s jiným sklonem</h3>
Pokud nám hodnota směrnice vyjde jedna, dostaneme úsečku se sklonem 45°. Ještě aby ne - pokud posuneme bod o jednu jednotku ve směru $x$, musíme ji posunout o jednu jednotku ve směru $y$. Co když nám směrnice vyjde větší než jedna? Mějme
\[
a=\frac{3}{1}
\]
tedy posun o jednu jednotku ve směru $x$ a o tři ve směru $y$. Pokud bychom použili pro vykreslení algoritmus uvedený výše, dostali bychom úsečku se spoustou děr. Pro první čtyři body by výpočet dopadl následovně
</br></br>
<table align="center" border="1" cellpadding="3" cellspacing="0">
<tbody>
<tr>
<td><strong>x</strong></td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td><strong>y</strong></td>
<td>0</td>
<td>3</td>
<td>6</td>
<td>9</td>
</tr>
</tbody>
</table>
</br>
což by při vykreslení vypadalo takto
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio_RkHEPG4qOAANcHR9_GOuq_dJ0GuGER1vLR_DXFeWktRdIfnwTa1kvpBE9XsWexa9E3pfEKIcli_-PnHE5zM07cTrjE43nifwaJ8dxoQxbEB-823YQf7X-ssmm2P7Ses_kr8arAYtiQx/s1600/diry.png" /></div>
</br>
Protože musíme při vykreslení zajistit rasterizaci úsečky bod po bodu a tedy bez mezer, otočíme v tomto případě význam proměnných. O jednu jednotku budeme přidávat ve směru $y$ a dopočítávat dle směrnice krok ve směru $x$. Nezapomeňte, že pokud přičítáme směrnici pro směr $x$, musíme použít její převrácenou hodnotu! Tedy
\[
\frac{1}{a}=\frac{1}{3}
\]
Vypočítáme prvních deset bodů.
</br></br>
<table align="center" border="1" cellpadding="3" cellspacing="0">
<tbody>
<tr>
<td><strong>x</strong></td>
<td>0</td>
<td>0,3 (0)</td>
<td>0,6 (1)</td>
<td>0,9 (1)</td>
<td>1,2 (1)</td>
<td>1,5 (2)</td>
<td>1,8 (2)</td>
<td>2,1 (2)</td>
<td>2,4 (2)</td>
<td>2,7 (3)</td>
</tr>
<tr>
<td><strong>y</strong></td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</tbody>
</table>
</br>
Úsečka (část přímky) je na obrázku.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizC71EgU42ywEq9h3jVZ0UhLVIRoME77-67VytyaD5VLBFuQchIwNZD4NXXbv2ZhI4mkPd_2NdYaYkUqyuIuSA0tvB9TpT4hY3dhgfls1PV4t70QDTtx8W8EcrS9Zui-eT1_fXRcNU4pi3/s1600/diry2.png" /></div>
</br>
Při vykreslování úsečky algoritmem DDA je tedy nutné rozhodnout, který ze směrů bude pevně posouván o jedničku a který počítán.
</br></br>
<h3>Literatura a odkazy</h3>
KOLCUN, A. Základy počítačovej grafiky. Učební texty, Ostrava 2006.</br>
</br>
<a href="http://www.netgraphics.sk/dda-algorithm">http://www.netgraphics.sk/dda-algorithm</a> - appletAnonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-19436030903739406042013-11-11T15:37:00.000+01:002013-11-11T15:46:47.763+01:00Výpočty v ExceluUkážeme si jak pracovat se vzorci, počítat soustavy rovnic a kreslit křivky. V článku je použita verze 2007 s českou lokalizací.
</br></br>
<h3>Jednodušší vzorce</h3>
Řekněme, že chceme vypočítat euklidovskou vzdálenost dvou bodů. Aplikujeme Pythagorovu větu
\[
c=\sqrt{a^2+b^2}
\]
V Excelu může zápis vypadat třeba takto
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiclJAFiNMCGvYLTwGF51D8WI5dH6Ubc5KxcGHF0jfBh4Zq1TDlZq3UyUOro8Ge2GVRXE68OcPE9MHxe79QziNueiSOEAVQHPZtMBo9DKD_hdGTi4M4WhQPYpPMpqUe05qnpoLKK1ZlIY7F/s1600/excel1.png" /></div>
</br>
Vidíme, že je použit vzorec
</br></br>
<i>=ODMOCNINA((C2-B2)*(C2-B2)+(C3-B3)*(C3-B3))</i>
</br></br>
Bereme tedy vzdálenost souřadnic $x$ obou bodů spolu se vzdáleností souřadnic $y$. Jejich součet umocníme a výsledek zobrazíme v buňce $E2$. Vpravo jsou pak pro názornost oba body vyneseny do grafu.
</br></br>
<h3>Práce s maticemi</h3>
Matice můžeme využít k výpočtu soustavy rovnic, což se nám hodí při transformacích, generování křivek, rekonstrukci obrazu, a dalších. Ukažme si výpočet bodů na křivce vygenerované pomocí <a href="http://cgtucna.blogspot.cz/2013/11/od-explicitne-zadanych-krivek-k_5.html">interpolačního polynomu</a>.
Mějme čtyři body
\begin{align*}
A=[3,2] \\
B=[5,4] \\
C=[6,3] \\
D=[9,8]
\end{align*}
ze kterých dostaneme soustavu rovnic
\begin{align*}
1a_0+3a_1+3^2a_2+3^3a_3=2 \\
1a_0+5a_1+5^2a_2+5^3a_3=4 \\
1a_0+6a_1+6^2a_2+6^3a_3=3 \\
1a_0+9a_1+9^2a_2+9^3a_3=8
\end{align*}
kterou můžeme jednoduše vypočítat použitím <a href="http://cs.wikipedia.org/wiki/Inverzn%C3%AD_matice">inverzní matice</a>.
Napíšeme koeficienty rovnice do buněk $A5:D8$. Poté je třeba vybrat oblast $A10:D13$ pro výslednou inverzní matici a do první buňky vepsat vzorec
</br></br>
<i>=INVERZE(A5:D8)</i>
</br></br>
List by měl u vás vypadat podobně jako na obrázku.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQwz0qzsKPpJv3hSRiGvkXreWAE_whUtF5Vq0NgPLkZgHBvlwO1JJYwab9QvBdifjggsrQvXE6sNQ3PpfGr4nnQiB5kmA0wYO3bmSYDJ65Jp836C8PGRQbFA0VqNSJ0dntfW6G2FjY9vEY/s1600/excel3.png" /></div>
</br>
Po stisku <strong>Ctrl + Shift + Enter</strong> dostaneme v označené oblasti výsledek. Pro další krok výpočtu potřebujeme vynásobit inverzní matici s vektorem pravých stran soustavy. Vybereme tedy oblast $B15:B18$ a do první buňky vložíme vzorec
</br></br>
<i>=SOUČIN.MATIC(A10:D13;F5:F8)</i>
</br></br>
Váš list by měl v této chvíli vypadat nějak takto
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIWWYpbAEndwS-bMWJRND71_T6_r56WBWO9w3l0AD-6yV0K7gqeLJSa7nz8IAc-KD10tJHKHcYs83vbwmvhjK3-1v-BIlWQMAyqX6u_vQjIRf_g5NC2lXmYT4ose3ISgifbb14Maw8gpRS/s1600/excel4.png" /></div>
</br>
Opět stiskneme <strong>Ctrl + Shift + Enter</strong> pro potvrzení maticové operace. Teď už nám jen chybí dopočítat ostatní body, takže si do buněk $H2:H11$ vložíme hodnoty $x$ v intervalu $<1,10>$. Do sloupce vedle pak vypočítáme $y$.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSi9cQOeNiB4xR7Yii0o0eq2cy8IctGzl26_OB4iJk41DXMOyeyAF54qgans0PwmO7AIbyAHh8vIhGngK_NqFoylfT6mRJtY-zJWFTJnnH97fYRx0cuKMP3ndQqkro19QMTZqVRzJzmuWU/s1600/excel5.png" /></div>
</br>
<h3>Grafy</h3>
Chcete vidět, jak vypadá geometrická reprezentace vašich dat? Ukažme výpočet <a href="http://cgtucna.blogspot.cz/2013/11/bezierova-krivka.html">Bézierova</a> splajnu složeného ze dvou kubik $P$ a $Q$. Do buněk $A2:A12$ zadáme hodnoty parametru $t$, ze kterých vypočítáme hodnoty váhových funkcí $w_0, w_1, w_2, w_3$. V oblasti $F2:I3$ jsou vstupní body pro křivku $P$ a v oblasti $F6:I7$ pro křivku $Q$. Buňky $J2:K22$ budou obsahovat vypočítané hodnoty $x$ a $y$.
Pro vynesení do grafu vybereme oblast $J2:K12$ a z karty <i>Vložení</i> volbu <i>Bodový -> Bodový pouze se značkami</i>.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnvQ18L0kUMtLMlQZADyUUqUdcVJ5Ck4TWV4G8oLUXVvrTCtiKG0CqLE0nyPZanjWZhRvg3xeEgn902gRG8swvoc2si4yzt0l2wtCYf4kQY0krj8Bhch46_9KKtaBnQ1zerCCzMnX_aR3d/s1600/excel6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnvQ18L0kUMtLMlQZADyUUqUdcVJ5Ck4TWV4G8oLUXVvrTCtiKG0CqLE0nyPZanjWZhRvg3xeEgn902gRG8swvoc2si4yzt0l2wtCYf4kQY0krj8Bhch46_9KKtaBnQ1zerCCzMnX_aR3d/s640/excel6.png" /></a></div>
</br>
Chceme přidat i body druhé křivky a to v jiné barvě. Klikneme pravým tlačítkem do zobrazované oblasti a zvolíme <i>Vybrat data... -> Přidat</i>. Do tabulky zadáme správné oblasti tak jako na obrázku
</br></br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRNk16Pl-NsPcoDKfmuVFjNk8vioP3YhZPgMfcWuZG3M9sO_dUVZUK6G6qOk9OFvgvdD7hgfjP0VA51sq1Mm3ObWSlsv-TXtW1DQeGBilm-qGIN2gjEe5tFXYfPiePZHZYDtu9uas8Oytc/s1600/excel7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRNk16Pl-NsPcoDKfmuVFjNk8vioP3YhZPgMfcWuZG3M9sO_dUVZUK6G6qOk9OFvgvdD7hgfjP0VA51sq1Mm3ObWSlsv-TXtW1DQeGBilm-qGIN2gjEe5tFXYfPiePZHZYDtu9uas8Oytc/s640/excel7.png" /></a></div>
</br>
Potvrdíme <i>OK -> OK</i> a máme hotovo.
</br></br>
<h3>Upozornění</h3>
Na začátku článku zmiňuji, že používáme Excel s českou lokalizací. Toto je velmi důležité dodržet, protože pro jinou jazykovou verzi vám uvedené vzorce nebudou fungovat! Názvy funkcí v ní budou přeloženy, což znamená, že v anglické musíme například místo <i>SOUČIN.MATIC</i> psát <i>MMULT</i>.Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com2tag:blogger.com,1999:blog-4298974035643126527.post-26259353444326870492013-11-11T15:34:00.000+01:002013-11-11T15:34:49.486+01:00Barvy a barevné viděníUveřejňuji svou přednášku do předmětu Principy a algoritmy počítačové grafiky (Ostravská univerzita v Ostravě) na téma Barvy a barevné vidění.
<a href="https://docs.google.com/open?id=0B5fXEQTqpkegZGU4NDE3ZTUtMWZjNC00OTk5LThiZTAtMWNkMjMyNTAyZTI3">Stáhnout</a>
</br></br>
<h3>Agenda</h3>
<ul>
<li>barevné vidění</li>
<li>barvy a světlo</li>
<li>formalizace barev</li>
<li>barevné modely</li>
<li>třešinky na závěr</li>
</ul>Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com1tag:blogger.com,1999:blog-4298974035643126527.post-7963069839039325302013-11-11T15:19:00.000+01:002013-11-11T15:31:37.774+01:00Bézierova křivkaPředstavme konkrétní parametrickou křivku, která vychází z předpisu
\[
P(t)=w_0(t)P_0+w_1(t)P_1+w_2(t)P_2+...+w_n(t)P_n
\]
kde $w$ jsou váhové funkce a $P$ vstupní body.
</br></br>
<h3>Ukázka a vlastnosti</h3>
Pro křivku definovanou čtyřmi body ve 2D, dostaneme
\[
P_x(t)=w_0(t)P_{0,x}+w_1(t)P_{1,x}+w_2(t)P_{2,x}+w_3(t)P_{3,x}
\]
\[
P_y(t)=w_0(t)P_{0,y}+w_1(t)P_{1,y}+w_2(t)P_{2,y}+w_3(t)P_{3,y}
\]
Křivka definovaná čtyřmi body se nazývá <i>křivka třetího stupně</i>. Připomeňme, že parametr $t$ nabývá hodnot $<0;1>$.
Bézierova křivka třetího stupně může vypadat třeba takto
</br></br>
<table align="center" border="0">
<tbody>
<tr>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha3ac3C8IueDk9Qz3nQNEHdDz08S5d9ORsdW8gZUbB3QF6oGQqJivF8pO6M3qXHTYp84GyQcJJegFg6xRxZhxHRy5ZESlbUBCW12BsfPrq6gQsdmP5xfcVgT4OcHdhYVVCHcWwvWjD6XEb/s1600/1.png" /></div></td>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijGuyFwZtOvTQ5Mk4MxgtqIXH2_cqnTrFO2xfBt0RxoUwD9mp0u9_jmc4XzgAT1D7RgXi-OQuBFf7hcjMUmwNm9OIZFqL0RJOYsbZn1BTBIG4cQyXdHVH1JBbkw-UcZf_7T2sgwtuYleRK/s1600/4.png" /></div></td>
</tr>
<tr>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtGHh3-Lq21RwAP-couFAJISuJ4e_SBsZsEQrXely_nTDpqg8XqnAjIZYjQYK35oZoNLlUHr_0Uh7NYNhuw3hsmP46DcPq-OnADGWS1IjLqaLXuFfTzUD6o1JJ3DcdKU_tFN8Z_VcYPRYn/s1600/3.png" /></div>
</td>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7xi5_5Vny7Rmwr65GbQBLIqGFk99qGAxZ6HDWZ-J3r8muAeEetot6uxSm8JcJHrj_cnNMoldTyX0Ean9VR1MnyrGbFn_9PmbYrlfj63skh_8-dhKgYD18PsUyxqOUH7hUMNqS4lh30VMR/s1600/2.png" /></div></td>
</tr>
</tbody>
</table>
</br>
Vstupní čtyři body zadává uživatel a jejich změnou je schopen docílit změny výsledné křivky. Při editaci je třeba mít na paměti tři základní vlastnosti
<ol>
<li>křivka nikdy neopustí konvexní obal definovaný vstupními body</li>
<li>křivka bude vždy procházet prvním a posledním bodem</li>
<li>směr křivky v koncových bodech je určen sousedními body</li>
</ol>
V článku se budu odkazovat na konkrétní vlastnost použitím jejího pořadí v seznamu výše.
</br></br>
<h3>Váhové funkce</h3>
Ze vzorců výše vyplývá, že krom zadaných vstupních bodů budeme potřebovat ještě funkce $w_i$. Tyto funkce jsou generovány z Bernsteinových polynomů, které jsou definovány jako
\[
w_k(t)=\binom{n}{k}(1-t)^{n-k}(t)^k
\]
kde $n$ je počet stupňů výsledné křivky. Počet stupňů se pak rovná počtu řídících bodů mínus jedna.
Vypočítejme tedy funkce $w_i$ pro křivku třetího stupně (čtyři řídící body)
\[\begin{array}{lcl}
w_0(t)&=&\binom{3}{0}(1-t)^{3-0}(t)^0= \\
&=&1(1-t)^3\cdot1= \\
&=&(1-t)^3 \\
\end{array}\]
\[\begin{array}{lcl}
w_1(t)&=&\binom{3}{1}(1-t)^{3-1}(t)^1= \\
&=&3(1-t)^2t^1= \\
&=&3(1-t)^2t \\
\end{array}\]
\[\begin{array}{lcl}
w_2(t)&=&\binom{3}{2}(1-t)^{3-2}(t)^2= \\
&=&3(1-t)^1t^2= \\
&=&3(1-t)t^2 \\
\end{array}\]
\[\begin{array}{lcl}
w_3(t)&=&\binom{3}{3}(1-t)^{3-3}(t)^3= \\
&=&1(1-t)^0t^3= \\
&=&1t^3= \\
&=&t^3 \\
\end{array}\]
a vynesme je pro názornost do grafu
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWLeJqpapllf2Pbqn_r7Klztu1b5Ku_-Upe38cSKWoGmQQdGuC1jMDhDt4VHVfEXIuwHNUPQiggwIx4wuz8Y6PVXsYrKvy7l0Z8p-GcRgDHIs6yDwTV_G2Eow-HZZWN-D4uc5JEvza9gSo/s1600/vahyB.png" /></div>
</br>
<h3>Příklad</h3>
Zkusme dle obecného vztahu výše, postupně vypočítat Bézierovu křivku pro následující čtyři body
</br></br>
<table align="center" border="1" width="30%" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><strong>P</strong></td>
<td><strong>x</strong></td>
<td><strong>y</strong></td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>30</td>
<td>50</td>
</tr>
<tr>
<td>2</td>
<td>60</td>
<td>50</td>
</tr>
<tr>
<td>3</td>
<td>90</td>
<td>0</td>
</tr>
</tbody>
</table>
</br>
Dosadíme pro $x$
\[
P_x(t)=(1-t)^3\cdot0+3(1-t)t^2\cdot30+3(1-t)^2t\cdot60+t^3\cdot90
\]
a pro $y$
\[
P_y(t)=(1-t)^3\cdot0+3(1-t)t^2\cdot50+3(1-t)^2t\cdot50+t^3\cdot0
\]
Po úpravách pak dostáváme
\begin{align*}
P_x(t)&=30\cdot3(1-t)t^2+60\cdot3(1-t)^2t+90t^3 \\
P_y(t)&=50\cdot3(1-t)t^2+50\cdot3(1-t)^2t
\end{align*}
Zkusme vypočítat hodnoty $x$ a $y$ pro bod v čase $t=0$
\[\begin{array}{lcl}
P_x(0)&=&30\cdot3(1-0)0^2+60\cdot3(1-0)^2\cdot0+90\cdot0^3= \\
&=&30\cdot3\cdot1\cdot0+60\cdot3\cdot1\cdot0+90\cdot0= \\
&=&0+0+0= \\
&=&0 \\
P_y(0)&=&50 \cdot 3(1-0)0^2+50\cdot3(1-0)^20= \\
&=&50\cdot3\cdot1 \cdot 0+50\cdot3\cdot1\cdot0= \\
&=&0+0= \\
&=&0 \\
\end{array}\]
a přidejme také výpočet pro čas $t=1$
\[\begin{array}{lcl}
P_x(1)&=&30 \cdot 3(1-1)1^2+60 \cdot 3(1-1)^2 \cdot 1+90 \cdot 1^3= \\
&=&30 \cdot 3\cdot0 \cdot 1+60 \cdot 3\cdot0+90\cdot1= \\
&=&0+0+90= \\
&=&90 \\
P_y(1)&=&50\cdot3(1-1)1^2+50 \cdot 3(1-1)^2 \cdot 1= \\
&=&50\cdot3 \cdot 0 \cdot 1+50\cdot3\cdot0\cdot1= \\
&=&0+0= \\
&=&0 \\
\end{array}\]
Jak vidíme, dostali jsme první bod výsledné křivky $[0,0]$ a poslední $[90,0]$. Toto koresponduje s 2. vlastností Bézierových křivek, tedy že první bod musí odpovídat bodu $P_0$ a poslední bodu $P_{n-1}$. Stejným způsobem vypočítáme hodnoty pro $x$ a $y$ na celém intervalu $t$.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9JbDTe728-NKiP-d2Jyf-I0hftze-fchih5eD2Fi1WGpDaPGTIfmIcBA_TpECLA2bp6heQf6fXcwAvvqV6rKlztyyqWyNEcIiWntVXVMpJHOdyG0Ku9_MneyijM30s3utzJtrkufKmxBT/s1600/t36.png" /></div>
</br>
<h3>Implementace</h3>
Algoritmus má pár zvláštností, které můžou být v rozporu s naší individuální představou. Pseudokód pro výpočet křivky třetího stupně může vypadat takto
<pre class="c++" name="code">
d = 0.01;
for(t = 0, t <= 1; t = t + d) {
w0 = (1-t)*(1-t)*(1-t)
w1 = 3*(1-t)*(1-t)*t
w2 = 3*(1-t)*t*t
w3 = t*t*t;
x = w0*P0x + w1*P1x + w2*P2x + w3*P3x;
y = w0*P0y + w1*P1y + w2*P2y + w3*P3y;
putPixel(x, y);
}
</pre>
Narážíme na problém - <strong>nejsme schopni spočítat všechny hodnoty na intervalu od 0 do 1</strong>! Pracujeme v diskrétním prostoru, což pro nás znamená použití určitého kroku. Vypočítáme tedy množinu bodů s krokem definovaným v proměnné <i>d</i> a ty vykreslíme na obrazovku. Nedostaneme krásnou křivku jako na obrázcích výše, ale více či méně separovaných bodů. Nabízí se řešení nastavit <i>d</i> dostatečně malé. Tento způsob nebude uspokojivě fungovat z několika důvodů. Pokud bude <i>d</i> příliš malé, budeme počítat hodnoty pro menší velikost, než je šířka pixelu na obrazovce. Pokud bude příliš velké, budou nám vznikat díry. Například pro <i>d=0.2</i> dostaneme hodnoty pro pouhých šest bodů ${0, 0.2, 0.4, 0.6, 0.8, 1}$.
Jako optimální řešení volíme spojení dvou bezprostředně za sebou následujících bodů úsečkou.
<pre class="c++" name="code">
d = 0.01;
predchozi_x = x0;
predchozi_y = y0;
for(t = 0, t <= 1; t = t + d) {
w0 = (1-t)*(1-t)*(1-t)
w1 = 3*(1-t)*(1-t)*t
w2 = 3*(1-t)*t*t
w3 = t*t*t;
x = w0*P0x + w1*P1x + w2*P2x + w3*P3x;
y = w0*P0y + w1*P1y + w2*P2y + w3*P3y;
line(predchozi_x, predchozi_y, x, y);
predchozi_x = x;
predchozi_y = y;
}
</pre>
Při zvolení vhodného <i>d</i> si tuto aproximaci můžeme dovolit, protože i oblouček můžeme diskrétně chápat jako spojení více krátkých úseček.
</br></br>
<h3>Literatura a odkazy</h3>
KOLCUN, A. Základy počítačovej grafiky. Učební texty, Ostrava 2006.</br>
ŽÁRA, J.; SOCHOR, J.; BENEŠ, B.; FELKEL, P. Moderní počítačová grafika. Computerpress, Brno 2004.</br>
</br>
<a href="http://lubovo.misto.cz/_MAIL_/curves/">http://lubovo.misto.cz/_MAIL_/curves/</a> - pěkné zpracování tématiky v češtině, včetně appletů</br>
<a href="http://herakles.zcu.cz/education/zpg/cviceni.php?no=11">http://herakles.zcu.cz/education/zpg/cviceni.php?no=11</a> - materiály ze Zápodočeské Univerzity v Plzni, také interaktivní</br>
<a href="http://processingjs.nihongoresources.com/bezierinfo/">http://processingjs.nihongoresources.com/bezierinfo/</a> - spousta dalších informací a detailů (anglicky)</br>
<a href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve">http://en.wikipedia.org/wiki/B%C3%A9zier_curve</a>Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-86413691060328073452013-11-11T15:01:00.000+01:002014-03-11T12:58:04.880+01:00Bézierova a Fergusonova kubikaOd pohledu tatáž křivka, může být určena více způsoby. Ukážeme si vztah mezi dvěma z nich a vzájemný převod z jedné do druhé.
</br></br>
<h3>Úvod</h3>
Mějme křivku
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfRcoUSXbHLcqHGNoyKIxJpGnVggnwXNVTs9U36GIHT1Mv9cR7a4i6QVZPyHYINxcutLUufvmM60xOFEENbwbjkrQ3tm1LiBquml94TkG7wEqVrlitSwyNQPacj2fHmJjUKbt5qhz1B8qa/s1600/orig.png" /></div>
</br>
kterou potřebujeme nějak definovat. Můžeme určit, že první a poslední body budou místa, kde začíná a končí. Nazvěme je $P_0$ a $P_3$. Dle vzhledu můžeme soudit, že půjde vyjádřit váhovými funkcemi třetího stupně. Potřebujeme tedy ještě další dva body, které nám jednoznačně definují tvar.
</br></br>
<h3>Fergusonova kubika</h3>
V jednom ze způsobů, můžeme určit směrové vektory v počátečním a koncovém bodě. Ty nám určí míru zvlnění křivky, takže jejich vhodnou volbou docílíme požadovaného tvaru.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYMkNCYZXDiaYvbMkKe3fKv_-W0qJEZV1MklCCmPUeiFeh0sZQo13RlsztLZDtHBvHoyRwQn-SLtOstshgsZWB-ROtYRtTpAEZ-x9M9McGv5xWv1WErfdKrqN935UByZi1Oq49s0riCQj3/s1600/ferguson1.png" /></div>
</br>
Křivku nám vygenerují následující váhové funkce označené pro přehlednost indexem $f$:
\begin{align*}
w_{0,f}(t)&=2t^3-3t^2+1 \\
w_{1,f}(t)&=-2t^3+3t^2 \\
w_{2,f}(t)&=t^3-2t^2+t \\
w_{3,f}(t)&=t^3-t^2
\end{align*}
Pro dosazení do vzorce ovšem nemůže použít přímo body $P_1$ a $P_2$, ale z nich vyjádřené směrové vektory. Tedy pokud nemáme místo bodů zadány vektory přímo. Dostaneme
\begin{align*}
\overrightarrow{u} = (P_1-P_0) \\
\overrightarrow{v} = (P_3-P_2)
\end{align*}
</br>
<h3>Bézierova kubika</h3>
Jako druhou možnost uvažujme použití řídícího polygonu. Nebudeme přímo určovat tečný vektor, ale vyhrazovat oblast, ve které se křivka nachází.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHXvviQu6FTmRbhfz7-hr4-CGqwf3ZmeHyyCcdN-o1mJ4TZNXBVMCQvFi8EN31yGk9t2UQKldH7fWdK4_d5HTUWpyM5TVqMk9apBWoyR89n93oMGwvXIZNmRXEYOZBoXQXKnIQo2tf9QSb/s1600/bezier1.png" /></div>
</br>
Váhové funkce označíme indexem $b$:
\begin{align*}
w_{0,b}(t)&=(1-t)^3 \\
w_{1,b}(t)&=3t(1-t)^2 \\
w_{2,b}(t)&=3t^2(1-t) \\
w_{3,b}(t)&=t^3
\end{align*}
Chceme ukázat, že jde tatáž křivka zadat jako <a href="http://cgtucna.blogspot.cz/2013/11/bezierova-krivka.html">Bézierova</a>, nebo i Fergusonova. Ferguson pracuje se směrovými vektory, které souvisejí s <a href="http://cgtucna.blogspot.cz/2013/11/primka-derivace.html">derivací</a> (derivace je směrnice tečny), takže zderivujme Bézierovy váhové funkce.
\begin{align*}
w_{0,b}(t)'&=(-t^3+3t^2-3t+1)'=-3t^2+6t-3 \\
w_{1,b}(t)'&=(3t^3-6t^2+3t)'=9t^2-12t+3 \\
w_{2,b}(t)'&=(-3t^3+3t^2)'=-9t^2+6t \\
w_{3,b}(t)'&=3t^2
\end{align*}
Zajímají nás směrové vektory v prvním a posledním bodě. To znamená v bodech s hodnotou $t=0$ a $t=1$.
Pro $t=0$:
\begin{align*}
w_{0,b}(0)'&=-3\cdot0^2+6\cdot0-3=-3 \\
w_{1,b}(0)'&=9\cdot0^2-12\cdot0+3=3 \\
w_{2,b}(0)'&=-9\cdot0^2+6\cdot0=0 \\
w_{3,b}(0)'&=3\cdot0^2=0
\end{align*}
\[
\overrightarrow{v_1} = -3P_0+3P_1=3(P_1-P_0)
\]
Pro $t=1$:
\begin{align*}
w_{0,b}(1)'&=-3\cdot1^2+6\cdot1-3=0 \\
w_{1,b}(1)'&=-9\cdot1^2+12\cdot1-3=0 \\
w_{2,b}(1)'&=-9\cdot1^2+6\cdot1=-3 \\
w_{3,b}(1)'&=3\cdot1^2=3
\end{align*}
\[
\overrightarrow{v_2} = -3P_2+3P_3=3(P_3-P_2)
\]
</br>
<h3>Srovnání obou přístupů</h3>
Zkusme teď dosadit body definující Bézierovu křivku do vzorce pro výpočet Fergusonovy. První a poslední budou shodné, lišit se u obou budou body definující směr. Bézierova kubika vypadá následovně:
\[
P_b(t)=w_{0,b}(t)P_0+w_{1,b}(t)P_1+w_{2,b}(t)P_2+w_{3,b}(t)P_3
\]
a Fergusonova takto:
\[
P_f(t)=w_{0,f}(t)P_0+w_{1,f}(t)P_3+w_{2,f}(t)3(P_1-P_0)+w_{3,f}(t)3(P_3-P_2)
\]
Roznásobme, ať můžeme dát dohromady všechny koeficienty.
\begin{align*}
P_f(t)&=w_{0,f}(t)P_0+w_{1,f}(t)P_3+w_{2,f}(t)3P_1-w_{2,f}(t)3P_0+w_{3,f}(t)3P_3-w_{3,f}(t)3P_2= \\
&=w_{0,f}(t)P_0-w_{2,f}(t)3P_0+w_{2,f}(t)3P_1-w_{3,f}(t)3P_2+w_{1,f}(t)P_3+w_{3,f}(t)3P_3= \\
&=(w_{0,f}(t)-3w_{2,f}(t))P_0+(3w_{2,f}(t))P_1+(-3w_{3,f}(t))P_2+(w_{1,f}(t)+3w_{3,f}(t))P_3
\end{align*}
Po vytknutí a seřazení členů dostáváme čtyři body a v závorkách pak váhové funkce. Ukážeme si, že se každá z nich rovná odpovídající funkci definujíci Bézierovu křivku.
Dosadíme v první závorce:
\begin{align*}
w_{0,f}(t)-3w_{2,f}(t)&=2t^3-3t^2+1-3(t^3-2t^2+t)=\\
&=2t^3-3t^2+1-3t^3+6t^2-3t=\\
&=1+3t^2-3t-t^3=\\
&=(1-t)^3
\end{align*}
Jak vidíme, vyšla nám pro bod $P_0$ stejná funkce jako je $w_{0,b}(t)$. Pokračujme s dalšími:
\begin{align*}
3w_{2,f}(t)&=3(t^3-2t^2+t)=\\
&=3t^3-6t^2+3t=\\
&=3t(t^2-2t+1)=\\
&=3t(1-t)^2 \\
-3w_{3,f}(t)&=-3(t^3-t^2)=\\
&=-3t^3+3t^2=\\
&=3t^2(-t+1)=\\
&=3t^2(1-t) \\
w_{1,f}(t)+3w_{3,f}(t)&=-2t^3+3t^2+3(t^3-t^2)=\\
&=-2t^3+3t^2+3t^3-3t^2=\\
&=t^3
\end{align*}
Pro závorku u každého bodu nám vyšla odpovídající váhová funkce $w_{i,b}$ po dosazení vah $w_{i,f}$. Můžeme tedy říct, že křivku zadanou jedním způsobem jsme schopni zadat i způsobem druhým. Na obrázku je pak vztah mezi řídícími body Fergusonovy a Bézierovy kubiky ukázán názorně.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnp3o3o7tDNk7MBnxRl6ML0DHDFHTg_Epcfazg0FqTK3qqXI2hPM92I9xT0bfdyCTw1N3W2ht8iviLnrSLfxs2HQeQ5icnVX504q_JAZ4esBetKvGQzbyYdQlfOPzr-acqQv0C7X1Bm54n/s1600/vypocet.png" /></div>
</br>
<h3>Literatura a odkazy</h3>
KOLCUN, A. Parametrické vyjadrenie kriviek a plôch. Učební texty, Ostrava 2008.</br>
</br>
<a href="http://herakles.zcu.cz/education/zpg/cviceni.php?no=11">http://herakles.zcu.cz/education/zpg/cviceni.php?no=11</a>Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-39153433873154317912013-11-11T14:57:00.000+01:002013-11-11T15:01:11.434+01:00Přímka a derivaceZaměřme se na to co je přímka a jaké pro ni můžeme najít uplatnění. Budeme pracovat s obecnou rovnicí ve tvaru
\[
y=ax+b
\]
kde $x$ je volené, $a$ je směrnice dané přímky a $b$ bod na ose $y$ ve kterém ji protíná.
</br></br>
<h3>Definice</h3>
V euklidovském prostoru je přímka jednoznačně definovaná dvěma body, kterými prochází. Je nekonečně dlouhá a pokud její délku omezíme z obou stran, dostáváme úsečku. Na obrázku máme pro příklad přímku
\[
y=2x+2
\]
</br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqMdfZJlOE6PWabdsZQSknv1dJ-38qWiq8ShEfdP2pL1GzMKYDXMe-JdroSujOp-hLTqNdGcu0QYa8LpkPpSunyOT7pZMX9MNCSsasNQ7CNDMj4JuKh_G_x-kEsvK2Lv6bbHp9lONOYmBP/s1600/primka2.png" /></div>
</br>
Přímka prochází na ose $y$ bodem 2, což vyplývá z $b=2$ a je dost strmá, což vyplývá z $a=2$. Můžeme zkontrolovat, že po dosazení bodů $Z$ a $K$ dává rovnice správný výsledek. Pro $Z=[0,2]$
\[
y_z=2x_z+2=2\cdot 0+2=2
\]
a pro $K=[1,4]$
\[
y_k=2x_k+2=2\cdot 1+2=4
\]
Teď si řekněme, jaký je význam směrnice $a$. Jednoduše - <i>o kolik jednotek na ose $y$ musím posunout bod $P_i$ pokud ho na ose $x$ posunu o jednu.</i> Směrnice se vypočítá následovně
\[
a=\frac{y_k-y_z}{x_k-x_z}=\frac{\Delta_y}{\Delta_x}
\]
</br></br>
<h3>Derivace</h3>
Hodnota derivace je <i>směrnice tečny v daném bodě funkce.</i> V příkladu výše máme směrnici rovnou dvěma. To znamená, že když hodnota na ose $x$ následujícího bodu vzroste o jedna, tak na ose $y$ vzroste o dva. Jakou směrnici má přímka vodorovná s osou $x$? Jinými slovy můžeme říct, o kolik mi musí vzrůst hodnota $y$, pokud zvětším $x$ o jedna? Správná odpověď je nula. Předpokládáme tedy, že směrnice přímky, která je vodorovná s osou $x$, bude 0. Podívejme se na následující obrázek.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoFkKAyi2uO6H08_srW_X03HWDa6cjVp23qI4Ov9GFJWPyvNe6WcGX5H1cpzTv3ICWgeAA_KHUqelj_DUus_hoDQb8_kM8kHnrILEBapvcjPGTmACqsGuUwopHSUKwIb8lKhyvdEd8P6hJ/s1600/der.png" /></div>
</br>
Směrnice červené přímky bude určitě 0 (je rovnoběžná s osou $x$). Co nám z toho plyne z hlediska funkce vykreslené modře? Přímka prochází bodem $B$ a je v daném bodě tečnou k funkci $f$. Tedy směrnice této přímky je rovna derivaci funkce $f$ v bodě $B$. Zároveň je zřejmé, že v bodě $B$ dosahuje funkce lokálního maxima. Můžeme tedy říct, že místo kde funkce dosahuje lokálního extrému (minima nebo maxima) je tečna rovnoběžná s osou $x$ a tudíž má směrnici (derivaci) rovnou nule.
</br></br>
<h3>Literatura a odkazy</h3>
DELVENTHAL, K. M.; Kissner, A.; Kulick M. Kompendium matematiky. Universum, 2004.</br>
VINCE, J. Mathematics for computer graphics (second edition). Springer, 2006.</br>
</br>
<a href="http://en.wikipedia.org/wiki/Derivative">http://en.wikipedia.org/wiki/Derivative</a></br>
</br>
<a href="http://edu.uhk.cz/~havigji1/zmat1/derivace.htm">http://edu.uhk.cz/~havigji1/zmat1/derivace.htm</a> - derivace interaktivněAnonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-63481130843328489982013-11-11T14:56:00.000+01:002013-11-11T14:56:03.233+01:00Od explicitně zadaných křivek k parametrickým – 2. část<a href="http://cg.tucna.net/2012/03/od-explicitne-zadanych-krivek-k-parametrickym-1-cast/">Minulý díl</a> jsme zakončili výpočtem souřadnic $x$ a $y$ ve tvaru
\begin{align*}
x(t)=a_{0,x}+a_{1,x}t+a_{2,x}t^2+a_{3,x}t^3 \\
y(t)=a_{0,y}+a_{1,y}t+a_{2,y}t^2+a_{3,y}t^3
\end{align*}
Rozebereme detailněji, co nám to přináší a propracujeme se až do srozumitelného zápisu. Po zbytek článku budeme používat křivky třetího stupně.
</br></br>
<h3>Parametrické zadání</h3>
Přepišme výrazy výše do maticového tvaru
\[
P(t)=TC=
\left[ \begin{array}{cccc}
1 & t & t^2 & t^3
\end{array} \right]
\left[ \begin{array}{cc}
a_{0,x} & a_{0,y} \\
a_{1,x} & a_{1,y} \\
a_{2,x} & a_{2,y} \\
a_{3,x} & a_{3,y}
\end{array} \right]
\]
kde $C$ určuje tvar a pozici křivky. Toto ovšem není ideální, protože nemůžeme jasně vidět, jaké vlastnosti bude mít, ani jakými body bude určena. Z uživatelského hlediska bude výhodné tyto charakteristiky oddělit.
Přepíšeme výpočet na
\[
P(t)=TMP=
\left[ \begin{array}{cccc}
1 & t & t^2 & t^3
\end{array} \right]
\left[ \begin{array}{cccc}
m_{0,0} & m_{0,1} & m_{0,2} & m_{0,3} \\
m_{1,0} & m_{1,1} & m_{1,2} & m_{1,3} \\
m_{2,0} & m_{2,1} & m_{2,2} & m_{2,3} \\
m_{3,0} & m_{3,1} & m_{3,2} & m_{3,3}
\end{array} \right]
\left[ \begin{array}{c}
P_0 \\
P_1 \\
P_2 \\
P_3
\end{array} \right]
\]
kde $M$ představuje druh křivky a $P$ vstupní body. Dostali jsme tedy rozklad $C=MP$ a zrušili nutnost definovat vlastnosti dohromady jednou maticí.
Po roznásobení uvidíme, že se nám původně nepřehledný tvar vyjasnil.
\[\begin{array}{ccc}
P(t)&=&(m_{0,0}+m_{1,0}t+m_{2,0}t^2+m_{3,0}t^3)P_0+ \\
&&(m_{0,1}+m_{1,1}t+m_{2,1}t^2+m_{3,1}t^3)P_1+ \\
&&(m_{0,2}+m_{1,2}t+m_{2,2}t^2+m_{3,2}t^3)P_2+ \\
&&(m_{0,3}+ m_{1,3}t+m_{2,3}t^2+m_{3,3}t^3)P_3
\end{array}\]
Každý bod má v konkrétním čase $t$ vliv na bod, který leží na křivce. Tento vliv je reprezentován polynomickou funkcí třetího stupně. Řekněme, že pro přehlednost nahradíme výpočet v závorce funkcí $w_i$ s parametrem $t$.
\[
P(t)=w_0(t)P_0+w_1(t)P_1+w_2(t)P_2+w_3(t)P_3
\]
Tento tvar už jasně a jednoduše popisuje křivku určenou body $P_i$ a váhovými funkcemi $w_i(t)$. Právě volba zmíněných funkcí, dokáže na těch samých bodech vykreslit různé druhy křivek jako třeba <a href="http://cg.tucna.net/2012/01/bezierova-krivka/">Bézierovu</a>, Fergusonovu (zde pozor, je třeba z bodů vyjádřit tečné vektory!), nebo Coonsovu.
</br></br>
<h3>Závěr</h3>
Ukázali jsme si, jak lze odvodit parametrické křivky i jejich výhody oproti explicitně zadaným funkcím. Uveďme jen pro úplnost výpočet souřadnic $x$ a $y$ ať ho můžeme porovnat s tvarem uvedeným na začátku.
\begin{align*}
P_x(t)=w_0(t)P_{0,x}+w_1(t)P_{1,x}+w_2(t)P_{2,x}+w_3(t)P_{3,x} \\
P_y(t)=w_0(t)P_{0,y}+w_1(t)P_{1,y}+w_2(t)P_{2,y}+w_3(t)P_{3,y}
\end{align*}
</br></br>
<h3>Literatura a odkazy</h3>
KOLCUN, A. Parametrické modelovanie kriviek a plôch. Učební texty, Ostrava 2008.</br>
KOLCUN, A. Parametrick é vyjadrenie kriviek a plôch. Učební texty, Ostrava 2008.</br>
ŽÁRA, J.; SOCHOR, J.; BENEŠ, B.; FELKEL, P. Moderní počítačová grafika. Computer press, Brno 2004.</br>
</br>
<a href="http://herakles.zcu.cz/education/zpg/cviceni.php?no=11">http://herakles.zcu.cz/education/zpg/cviceni.php?no=11</a> - interaktivní zadávání křivek včetně teorie Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-9093895381345376602013-11-11T14:43:00.000+01:002013-11-21T08:19:15.253+01:00Od explicitně zadaných křivek k parametrickým - 1. částTato série dvou článků ukáže důvod k použití parametrických křivek, a jak se k nim vlastně dojde. V prvním díle ukážeme přirozený způsob výpočtu a to přes explicitně zadané funkce.
</br></br>
<h3>Explicitní tvar</h3>
Křivku můžeme popsat funkcí ve tvaru
\[
y=f(x)
\]
Na následujících obrázcích je pro příklad uvedeno několik funkcí jedné proměnné.
</br></br>
<table border="0" align="center">
<tbody>
<tr>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAWR5YwDL-XMVooPy5GJl4P0G8n8tEm3TPfavA5y0npV0dqUyF_duo0OAexpvgPr6MDp1hhMNIBnay7xkCPzoQkaAZFlPMt8eVOeqwkMSTEaYxQoYUxHcgo8a3p7dHJCNN5nuxoH82Rm0a/s1600/gr4.png" /></div>
</td>
<td>
\[
y=4
\]
</td>
</tr>
<tr>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9UojeW2_EEHErxI1Zjmywus4fLcGvjgixCDio7GOPACpRGcZyOv0O67pL_rOrsglP4GDS2vj8MQO3aNFfqstKhuwCQPsvPmBif0k1Ymv_X8CE8vQmdYwekVRcMfmr3Z6KZpMiLedvo4LP/s1600/gr3.png" /></div>
</td>
<td>
\[
y=3x+2
\]
</td>
</tr>
<tr>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjltfyCfSG9IBVADiIDNS51GFii5DtJBkxCCo6phmVJMXP4I6YIMNlcOP90YAM7H73x2jicQCxBdpLA4Cm8DZk8T2sainQNQPsbVFblcg3Hki2KBJ0If6CAILZErlrZcwHXMSZBlxpbnh9E/s1600/gr1.png" /></div>
</td>
<td>
\[
y=x^2
\]
</td>
</tr>
<tr>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeKvpEFBaVBjf_F4qslzyW3i4Jd-FQUEeeSjjNk0W8TBp85bE12vmRMAUii3Vyt_nORNgEYyaF6QSB92Q9JMCf7aoaho4Ws7LwLls-QZgNGy_DFkHUlqa6Dot2Vrce2ejE-KRpI8NCJRNC/s1600/gr2.png" /></div>
</td>
<td>
\[
y=x^3-x^2-5x+4
\]
</td>
</tr>
</tbody>
</table>
</br>
Pokud omezíme hodnoty $x$ ořízneme graf zleva i zprava. Funkce výše lze přepsat do <i>polynomického tvaru</i>
\[
y=a_0+a_1x+a_2x^2+a_3x^3+...+a_nx^n
\]
Budeme používat polynomické funkce třetího stupně (maximální mocnina v polynomu bude tři)
\[
y=a_0+a_1x+a_2x^2+a_3x^3
\]
která nám poskytuje dostatečnou variabilitu.
K vypočtení neznámých koeficientů $a_i$ potřebujeme zavést soustavu čtyř rovnic
\begin{align*}
y_0=a_0+a_1x_0+a_2x_0^2+a_3x_0^3 \\
y_1=a_0+a_1x_1+a_2x_1^2+a_3x_1^3 \\
y_2=a_0+a_1x_2+a_2x_2^2+a_3x_2^3 \\
y_3=a_0+a_1x_3+a_2x_3^2+a_3x_3^3
\end{align*}
ze které vyplývá nutnost určení čtyř vstupních bodů o souřadnicích $[x_i,y_i]$.
</br></br>
<h4>Příklad</h4>
Mějme body
</br></br>
<table width="30%" border="1" cellspacing="0" cellpadding="0" align="center">
<tbody>
<tr>
<td><strong>x</strong></td>
<td>5</td>
<td>10</td>
<td>12</td>
<td>16</td>
</tr>
<tr>
<td><strong>y</strong></td>
<td>2</td>
<td>10</td>
<td>5</td>
<td>8</td>
</tr>
</tbody>
</table>
</br>
Z těch <a href="http://cgtucna.blogspot.cz/2013/11/vypocty-v-excelu.html">vypočteme</a> koeficienty $a_i$
\begin{align*}
a_0&=-96,77922078 \\
a_1&=33,95822511 \\
a_2&=-3,352922078 \\
a_3&=0,102489177
\end{align*}
které nám po dosazení určí křivku
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF0ZXuw3z4f17AgQ4zi-IaWPvhMO8eTRmePeMOl06LFGyLXnPiacUMCo5uW8qJOVzBmHFFfEhgGLK8f8ZeBeSTE-VVjMWGEPJ5G0JamTJnBgwFFX7u_X0OOMV3eHIcNADM2XjLEaiw3LIR/s1600/krivka1.png" /></div>
</br>
definovanou funkcí
\[
y=-96,7792+33,9582x-3,3529x^2+0,1025x^3
\]
což si můžeme <a href="https://www.google.cz/webhp?sourceid=chrome-instant&ix=sea&ie=UTF-8&ion=1#hl=cs&sugexp=llsin&gs_nf=1&pq=-96.78%2B33.96x-3.35x%5E2%2B0.10x%5E3&cp=36&gs_id=3u&xhr=t&q=-96.7792%2B33.9582*x-3.3529*x%5E2%2B0.1025*x%5E3&pf=p&sclient=psy-ab&oq=-96.7792%2B33.9582*x-3.3529*x%5E2%2B0.1025*x%5E3&aq=&aqi=&aql=&gs_l=&pbx=1&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.,cf.osb&fp=cb97e5cc3908c41d&ix=sea&ion=1&biw=1600&bih=1115">ověřit</a>.
</br></br>
<h3>Závěrem</h3>
Právě demonstrovaný postup nazýváme <i>generování křivky z interpolačního polynomu</i>. Pohodlné ztotožnění s funkcí nás ovšem dost limituje. Nejsme díky toho schopni definovat různě točené, nebo uzavřené tvary. Bylo by tedy velmi výhodné neodvozovat souřadnici $y$ ze souřadnice $x$, ale z nějaké nezávislé proměnné. Tou bude čas $t$ což nám změní výpočet souřadnic na
\begin{align*}
x(t)=a_{0,x}+a_{1,x}t+a_{2,x}t^2+a_{3,x}t^3 \\
y(t)=a_{0,y}+a_{1,y}t+a_{2,y}t^2+a_{3,y}t^3
\end{align*}
Křivku budeme v tomto zápisu geometricky chápat jako pohyb bodu v čase. Jak souřadnice $x$ tak $y$ je odvozena právě od něj, což nám umožní spojování, kroucení i protínání.
Pokračování článku najdete <a href="http://cgtucna.blogspot.cz/2013/11/od-explicitne-zadanych-krivek-k.html">zde</a>.
</br></br>
<h3>Literatura a odkazy</h3>
KOLCUN, A. Parametrické modelovanie kriviek a plôch. Učební texty, Ostrava 2008.</br>
KOLCUN, A. Parametrick é vyjadrenie kriviek a plôch. Učební texty, Ostrava 2008.</br>
ŽÁRA, J.; SOCHOR, J.; BENEŠ, B.; FELKEL, P. Moderní počítačová grafika. Computerpress, Brno 2004.</br>
</br>
<a href="http://herakles.zcu.cz/education/zpg/cviceni.php?no=11">http://herakles.zcu.cz/education/zpg/cviceni.php?no=11</a> - interaktivní zadávání křivek včetně teorie Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-83385131683370229262013-11-11T14:18:00.000+01:002014-04-03T15:18:56.839+02:00INFOGRAFIKA: Bézierův spline vs. B-Spline<div style="text-align: center;">
<span style="color: red;"><em>Pro větší verzi klikněte <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBXyzorbCkBgYijSFRgqKSxC_SsB7_CiF22kPTrc9EwLi3P8DuczOe2QE0QsEFHVQBtFv2VOFmpA2xtJm7m61hsZiywbKzBYEz4p4reSbJGbxZErw_zys9W23znKdDsgYgFZhkGX1THfBd/s0/bspline.png" target="_blank">sem</a>.</em>
</span></div>
<br />
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBXyzorbCkBgYijSFRgqKSxC_SsB7_CiF22kPTrc9EwLi3P8DuczOe2QE0QsEFHVQBtFv2VOFmpA2xtJm7m61hsZiywbKzBYEz4p4reSbJGbxZErw_zys9W23znKdDsgYgFZhkGX1THfBd/s4022/bspline.png" /></div>Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-72506504258570076742013-11-11T14:07:00.000+01:002013-12-01T18:34:00.405+01:00Grafická hádanka IIVe druhé hádance zkusíme na obrázek aplikovat myšlenku
\[
\frac{A}{B} \cdot B=\frac{A \cdot B}{B}=A
\]
Konkrétně použijeme
\[
\frac{1}{3}\cdot3=\frac{1\cdot3}{3}=1
\]
popřípadě
\[
\frac{100}{3}\cdot3=\frac{100\cdot3}{3}=100
\]
Mějme tedy dva obrázky spolu s jejich číselnou reprezentací
</br></br>
<table align="center" border="0" >
<tbody>
<tr>
<td>
A
</td>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnY57_OKW_83dTS4-JcjAr8EIAX4IGQJComkICNhigC75V7yy1802Eh6uB-bB7Em9zD-aSPDb-K2E7p1YEzRffLM3Plzm6xPs0I1IwoLpfTaiGDEYScOCQFoOdYi5CyZwH2vBIYJp5JVwM/s1600/1-100.png" /></div>
</td>
<td>
$(1,100,1,100,1,100,1,100)$
</td>
</tr>
<tr>
<td>
B
</td>
<td>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAQ3H3XLgMzSg2xBbh_zh71Yg4immBoi3C0ZGQLkczVbtcLdgpNEedg2TLFdqP2lXy4PYTIRQltR8_iwGN0lhrmymJqbCuc5iEJsXQlNayWhrTXi5Df1fmm4HteXV3UV7f-hdet81IgU-k/s1600/3.png" /></div>
</td>
<td>
$(3,3,3,3,3,3,3,3)$
</td>
</tr>
</tbody>
</table>
</br></br>
Po dělení
\[
\frac{A}{B}
\]
dostaneme hodnoty
\[
(0.33...,33.33...,0.33...,33.33...,0.33...,33.33...,0.33...,33.33...)
\]
Pro zobrazení čísla jako barvy nemůžeme použít desetinnou část. Uvažujme tedy pro vykreslení do rastru pouze s celou a navíc pro lepší viditelnost vynásobenou třemi. Dostaneme hodnoty 0 a 99.
</br></br>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPzMHCiryi3JmIvDCfRhJzL4oVrxmM-9qOHYh0aFDikO4HNfGvGZodRQDZnCkcfxdjdDXgHtrHA1IJwwvM6F2QboGnN0Iq4dOdS4Z16WddcJ7l3LCrb7qBhLPJ4Z04TmLwz-pJi2T5waHS/s320/0-99.png" />
</div>
</br></br>
Obrázek vypadá na první pohled stejně jako původní <strong>A</strong> ovšem, jak vidíme, číselně se liší. Tam kde je 100 máme ve výsledném 99 a tam kde je 1 máme 0.
</br></br>
<h3>Co se stalo?</h3>
<em>"Odpověď je samozřejmě jednoduchá"</em> říkáte si :) Chyba vznikla uříznutím desetinné části o čemž se můžeme přesvědčit použitím zaokrouhlení. Místo
\[
0.99...\doteq0
\]
\[
99.99...\doteq99
\]
dejme
\[
0.99...\doteq1
\]
\[
99.99...\doteq100
\]
Dostaneme tedy původní obrázek <strong>A</strong>, jak napovídá matematická reprezentace na začátku.
</br></br>
<h3>Ovšem opět zbystřete!</h3>
Podívejme se znovu na hodnoty před zaokrouhlením:
\[
(0.99...,99.99...,0.99...,99.99...,0.99...,99.99...,0.99...,99.99...)
\]
Jak je to možné? Proč má výsledný obrázek hodnoty $0.99...$ a $99.99...$, zatímco ten původní $1$ a $100$?
</br></br>
<h3>Otázka</h3>
<span style="color: red;">Kde máme chybu? Proč nám bez zaokrouhlení nevyšel číselně stejný obrázek jako <strong>A</strong>?</span>Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-32512066085470570922013-11-06T08:25:00.000+01:002013-11-06T14:45:31.376+01:00Oheň ve 2DV příspěvku si ukážeme dvě techniky, kterými můžeme docílit zajímavého efektu hoření. Přidáme též implementaci v C++ s použitím knihovny <a href="http://www.libsdl.org/">SDL</a> s nástavbou <a href="http://lodev.org/quickcg/">QuickCG</a>.
<br />
<h3>
Základní myšlenka</h3>
Na začátku je třeba vygenerovat paletu barev, kterou použijeme pro náš oheň. Vybereme 300 odstínů, které budou plynule přecházet od bílé přes oranžovou, červenou až do černé.
<br /><br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjubAjjQEr8JkRb7EIsg2cnhxJwiArQjplWYByjSWl-DDlvvjXwTsEQL0qGRSMceA0Tml0dMjrHqDT0YLp3VkszfoKzfuEU5kgQ5yrRABaF-HNJoqUtcggmJSMhUDHn_tXHCtpaxi9EOSmS/s1600/paleta1.png" /></div>
<br /><br />
Poté vyplníme spodní řádek obrázku náhodně černou a bílou barvou a odshora dolů začneme ostatní pixely počítat dle pravidel uvedených níže. Budeme používat následující pojmenování pixelů
<br /><br />
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDIMdNEqI6m-aNy1KEYekaUibTyDbU3D6vEawa55K1Wem4gtmvVFzTU8MIpabmxcNueEWoX3BTLzcw5cWLIT_6FN6PQMNyUe_fxavoAWOdrFRiJJb-xSJMIfmph2rZLJf6gAVR55FkI1c-/s1600/first.png" />
</div><br />
<br />
<h3>
Implementace</h3>
Na začátku deklarujeme proměnné a definujeme konstanty. Také vytvoříme okno.
<br />
<pre class="c++" name="code">#include <cmath>
#include "quickcg.h"
using namespace QuickCG;
const int POCET_BAREV = 300;
const int OBRAZOVKA_SIRKA = 400;
const int OBRAZOVKA_VYSKA = 400;
const int CERNA_R = 0;
const int CERNA_G = 0;
const int CENRA_B = 0;
const int CERVENA_R = 255;
const int CERVENA_G = 0;
const int CERVENA_B = 0;
const int ORANZOVA_R = 255;
const int ORANZOVA_G = 170;
const int ORANZOVA_B = 0;
const int BILA_R = 255;
const int BILA_G = 255;
const int BILA_B = 255;
const int PALIVO = 25;
int main(int argc, char *argv[])
{
ColorRGB barva;
Uint32 ohen[OBRAZOVKA_SIRKA][OBRAZOVKA_VYSKA];
Uint32 buffer[OBRAZOVKA_SIRKA][OBRAZOVKA_VYSKA];
Uint32 paleta[POCET_BAREV];
float inkrement1;
float inkrement2;
int novaBarva;
int nahodneCislo;
//inicializuj obrazovku
screen(OBRAZOVKA_SIRKA, OBRAZOVKA_VYSKA, 0, "ohen");
[/sourcecode]
Teď si vynulujeme pole s budoucími hodnotami ohně.
[sourcecode language='c++']
//nastav výchozí hodnoty pro oheň
for(int x = 0; x < w; x++)
{
for(int y = 0; y < h; y++)
{
ohen[x][y] = 0;
}
}
</pre>
Čas na definování palety. První třetina bude přechod od černé do červené, druhá od červené do oranžové a třetí od oranžové do bílé.
<br />
<pre class="c++" name="code"> //barvy 0 - 99
barva.g = CERVENA_G;
barva.b = CERVENA_B;
inkrement1 = (float)CERVENA_R / (float)99;
for(int i = 0; i < 100; i++)
{
barva.r = ceil(inkrement1 * i);
paleta[i] = RGBtoINT(barva);
}
//barvy 100 - 199
barva.r = ORANZOVA_R;
barva.b = ORANZOVA_B;
inkrement1 = (float)ORANZOVA_G / (float)99;
for(int i = 100; i < 200; i++)
{
barva.g = ceil(inkrement1 * (i - 99));
paleta[i] = RGBtoINT(barva);
}
//barvy 200 - 299
barva.r = BILA_R;
inkrement1 = (float)(BILA_G - ORANZOVA_G) / (float)99;
inkrement2 = (float)(BILA_B) / (float)99;
for(int i = 200; i < 300 - 1; i++)
{
barva.g = ORANZOVA_G + ceil(inkrement1 * (i - 199));
barva.b = ceil(inkrement2 * (i - 199));
paleta[i] = RGBtoINT(barva);
}
</pre>
Vše je připraveno pro spuštění animace. Pokračujme tedy smyčkou a spouštěcím mechanismem. Na začátku musíme vygenerovat první řádek dle jednoduchého předpisu. Pokud náhodné číslo v intervalu <0> bude 0, pak na dané pozici dáme černý pixel. Pokud 1 tak bílý a pokud cokoliv jiného necháme ho beze změny.
<br />
<pre class="c++" name="code"> while(!done())
{
//nastav palivo
for(int x = 0; x < w; x++)
{
nahodneCislo = rand() % PALIVO;
if (nahodneCislo == 1)
{
ohen[x][h - 1] = 299;
}
else if (nahodneCislo == 0)
{
ohen[x][h - 1] = 0;
}
}
</pre>
Následující část představuje samotný výpočet. Vložte kód jedné z následujících technik.
<pre class="c++" name="code">...
</pre>
Zbývá už jen definování bufferu a jeho vykreslení na obrazovku.
<pre class="c++" name="code"> //nastav buffer pro vykreslení
for(int x = 0; x < w; x++)
{
for(int y = 0; y < h - 1; y++)
{
buffer[x][y] = paleta[ohen[x][y]];
}
}
//vykresli buffer
drawBuffer(buffer[0]);
redraw();
}
return 0;
}
</pre>
<h3>
Technika první</h3>
Pro každý pixel vezmeme tři, které leží bezprostředně pod ním. Z těchto tří uděláme aritmetický průměr a výslednou hodnotu uložíme do počítaného pixelu.
\[
I_n=(I_a + I_b + I_c)/3
\]
<br /><br />
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8Wg4h0s9jFXJasimbxs8_vMqY1Gq0F_SSbJuFyDPgLfX96WU4juH6m8BYLvj73p_NdsL8ny9s5hFf-6dW3kdMCrKgZKcDInUAjmQtKM0Rj5WgiTU_la5jHjYOTTyiUCZuROws7xT60fEU/s1600/ohen1.png" /></div>
<br /><br />
Následuje kód této techniky.
<pre class="c++" name="code"> //vypočítej hodnoty pixelů na obrazovce
for(int y = 0; y < h - 1; y++)
{
for(int x = 1; x < w - 1; x++)
{
novaBarva = (ohen[x-1][y+1] + ohen[x][y+1] + ohen[x+1][y+1]) / 3;
if (novaBarva > 0)
{
novaBarva = novaBarva - 1;
}
ohen[x][y] = novaBarva;
}
}
</pre>
<h3>
Technika druhá</h3>
Pro každý pixel vezmeme hodnotu tří, které leží pod ním, stejně jako v předchozím případě a přidáme i původní hodnotu počítaného. Vydělíme čtyřmi a výsledek použijeme.
\[
I_n=(I_a + I_b + I_c + I_n)/4
\]
<br /><br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAYTFH1CuaByDs2mINuNChFJdT2tg60EoLXhlNhvNsjXu3cS6xS0_qGy_zXRHtub8MvTPG5AgIimCR7yt3J5V_6fOEAy8FnjfULCbMPtdml_kcWG4QGvKSGLnMurl2DzW4JZwENa6qWdHV/s1600/ohen2.png" /></div>
<br /><br />
<pre class="c++" name="code"> //vypočítej hodnoty pixelů na obrazovce
for(int y = 0; y < h - 1; y++)
{
for(int x = 1; x < w - 1; x++)
{
novaBarva = (ohen[x-1][y+1] + ohen[x][y+1] + ohen[x+1][y+1] + ohen[x][y]) / 4;
if (novaBarva > 0)
{
novaBarva = novaBarva - 1;
}
ohen[x][y] = novaBarva;
}
}
</pre>
<h3>
Dodatek</h3>
Všimněte si, že je nutné odečíst z indexu barvy 1, pokud je to možné. Tímto simulujeme postupné slábnutí plamenů, protože čím menší hodnotu barva má, tím jde více do černa. Můžete zkusit co se stane, když jedničku odečítat nebudete.
<br /><br />
<h3>Literatura a odkazy</h3>
<strong>Videa a článek co mě inspirovaly</strong>
<br />
<a href="http://www.youtube.com/watch?v=NSI4KKjYS_w">http://www.youtube.com/watch?v=NSI4KKjYS_w</a> - porovnání obou přístupů<br />
<a href="http://www.youtube.com/watch?v=_SzpMBOp1mE">http://www.youtube.com/watch?v=_SzpMBOp1mE</a> - jednoduchá implementace spolu s mluveným komentářem, appletem a zdrojovými kódy<br />
<a href="http://www.youtube.com/watch?v=iezD8B1ym3w">http://www.youtube.com/watch?v=iezD8B1ym3w</a> - vylepšení implementace z předchozího videa<br />
<a href="http://www.academictutorials.com/graphics/graphics-fire-effect.asp">http://www.academictutorials.com/graphics/graphics-fire-effect.asp</a> - další z možností jak naprogramovat oheň<br />
<br />
<strong>Zdrojový kód</strong>
<br />
Stahujte <a href="https://docs.google.com/open?id=0B5fXEQTqpkegNWZjMTBhZGYtZDRlYy00NjE5LWJmZmUtNzk1MDNlMDhhZjNh">zde</a>.<!--0-->Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-6853960018551917422013-11-06T07:35:00.000+01:002013-11-06T14:53:41.035+01:00Interpolační splajnV článku rozebereme na příkladu aplikaci <a href="http://cgtucna.blogspot.cz/2013/11/od-explicitne-zadanych-krivek-k_5.html">interpolačního</a> splajnu složeného ze dvou parabol. Mějme vstupní body
\begin{align*}
P_0&=[-2;-8] \\
P_1&=[0;0] \\
P_2&=[3;12] \\
P_3&=[4;40]
\end{align*}
První parabola nechť je definována body $P_1,P_2,P_3$
\begin{align*}
0&=a_0+0a_1+0a_2 \\
12&=a_0+3a_1+9a_2 \\
40&=a_0+4a_1+16a_2
\end{align*}
<a href="http://cgtucna.blogspot.cz/2013/11/vypocty-v-excelu.html">Řešením</a> této soustavy bude
\begin{align*}
a_0&=0 \\
a_1&=-14 \\
a_2&=6
\end{align*}
a grafické znázornění
</br></br>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVQARvaaJ_6DxDlaJU_4ooHNf5Hvx8B5Q6FRavxps4W5-7SfW9ZgOa6-HWYOsgcNtA9oM9oeLgI9qWDuIhpaTNLqVxKd1s-jCqbhBFxel2TOjp6FdoulrUa27melgoAUIAPbp_D_pwkPMf/s1600/a.png" /></div>
</br></br>
Druhá parabola definována body $P_0,P_1$ bude zapsána následovně
\begin{align*}
-8&=b_0-2b_1+4b_2 \\
0&=b_0+0b_1+0b_2
\end{align*}
Jak je vidět, máme dvě rovnice a tři neznámé $b_0,b_1,b_2$. Potřebujeme pro vyřešení zavést další a tou bude podmínka pro hladké napojení. Derivace funkcí první a druhé paraboly musí být rovny, tedy
\begin{align*}
(a_0+a_1x+a_2x^2)'&=(b_0+b_1x+b_2x^2)' \\
a_1+2a_2x&=b_1+2b_2x
\end{align*}
Křivky budeme chtít napojit v bodě $P_1$. Zjistíme hodnotu derivace funkce v jeho x-ové souřadnici
\begin{align*}
y_a'(0)=a_1+2a_2\cdot0=a_1=-14
\end{align*}
Protože druhá parabola musí mít v bodě $P_1$ stejnou směrnici $-14$ dostaneme pro její derivaci
\begin{align*}
-14&=y_b'(0) \\
-14&=b_1+2b_2\cdot0 \\
b_1&=-14
\end{align*}
Dosaďme $b_1$ do rovnic pro druhou parabolu
\begin{align*}
-8&=b_0-2\cdot(-14)+4b_2 \\
0&=b_0+0\cdot(-14)+0b_2
\end{align*}
Po převedení číselných konstant doleva dostáváme
\begin{align*}
-36&=b_0+4b_2 \\
0&=b_0+0b_2
\end{align*}
Výsledkem jsou hodnoty
\begin{align*}
b_0&=0 \\
b_1&=-14 \\
b_2&=-9
\end{align*}
a obrázek
</br></br>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh18_vLoqCVzFvRE0LUDR0EJ2aEzVdN01pZsTlc_5rBw61bKwGh9lbAe8gYz6XkJMoBC6GtUjVyiuPIQUb1gdRFImS1m9RSV71gfkpbomhSasJMD_XkEpgJAxT31baQtXuIqEW-_0RwD_CT/s1600/b.png" /></div></br></br>
Výsledný splajn složený ze dvou pabarol bude vypadat následovně
</br></br>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQh_KjKrGQjZPbr1k1pMmM_MbqWWpvEOg80pkCTjUl-Ty9pmXa3g7rZA2rbzhrSBfShhgvp48U45bJXy_OZq51QXjcIXCnYOjnwF1tDypyCJQM5ziKpch64SC7uIFCuZCshVBASh8GnCnZ/s1600/final.png" /></div>
</br></br>
</br>
<h3>Literatura a odkazy</h3>
KOLCUN, A. Parametrické modelovanie kriviek. Učební texty, Ostrava 2012.Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0tag:blogger.com,1999:blog-4298974035643126527.post-71120429942228292172013-11-06T07:02:00.000+01:002014-01-23T14:42:48.574+01:00Operace s vektoryNedílnou součástí matematických znalostí pro práci s počítačovou grafikou tvoří operace s vektory. V článku si některé ukážeme spolu s jejich geometrickou reprezentací.
Budeme pracovat se dvěma vektory ve 2D $u=(u_1,u_2)$ a $v=(v_1,v_2)$.
<br/><br/>
<h3>Součet vektorů</h3>
Součet $u$ a $v$ dostaneme následovně
\[
u+v=(u_1+v_1,u_2+v_2)
\]
Jak vidíme, výsledkem je vektor.
<br/><br/>
<strong>Příklad</strong><br />
Nechť jsou vektory
\begin{align*}
u&=(2,1)\\
v&=(3,3)
\end{align*}
Pak jejich součet bude
\[
{\color{OliveGreen}u+v}=(2+3,1+3)=(5,4)
\]
Při geometrickém vyjádření vyneseme kopii vektorů vždy do vrcholu vektoru druhého. Výsledný součet je pak úhlopříčkou vzniklého čtyřúhelníku.
<br/><br/>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL9LadfJeGgLWOVuC2QL3Inmf9dAKBpXnXTTkl6XNR1NSZLyTTAY2Npm3wDV6pY5K9EyIDbF0Co82v210LbYnB-n1g3I5MSupgqM9Q_eszebfctMp3YMKGrkW8msM22Wz1GLpfQKydCawZ/s1600/1.png" /></div><br />
<h3>Rozdíl vektorů</h3>
Rozdíl $u$ a $v$ lze zapsat jako
\[
u-v=u+(-v)
\]
kde $-v$ nazýváme opačným vektorem k vektoru $v$.
<br/><br/>
<strong>Příklad</strong>
<br/>
Nechť jsou vektory
\begin{align*}
u&=(5,4)\\
v&=(3,2)
\end{align*}
Pak jejich rozdíl bude
\[
u-v=(5-3,4-2)=(2,2)
\]
Při geometrickém znázornění otočíme směr vektoru $v$ (světle modrý) a přesuneme jej do vrcholu vektoru $u$.
</br></br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxr_rbn31TdACRoWeQ26103lzqocv-6yUJP5K_B5QA89YaTiwAGIhXw1bFKj_HfTnewXzWcRdTKONCPRDy7U8ld3Z7UhDjp77ud5GQZ3Jf1WgzyO-LFleErpsJGp1fFyegGmtpEQxFipw6/s1600/2.png" /></div>
<br />
<h3>Násobení vektoru číslem</h3>
Vynásobení vektoru číslem $k$ probíhá násobením všech jeho složek
\[
u\cdot k = (u_1k,u_2k)
\]
<br/>
<strong>Příklad</strong>
<br/>
Nechť je na vstupu
\begin{align*}
u&=(2,1) \\
k&=2 \\
\end{align*}
Výsledkem pak bude
\[
u\cdot k = (2\cdot 2,1\cdot 2)=(4,2)
\]
</br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3sCeiDrOQAHTS2yYTz9x2_NHf1xtr_4iYXHWo0-thpbyVC5Nr5Yxv89GQVDm-2iLD3Cv4PquvymSqKjTZ4oTkJdkxkfBBl2qKAXG_-cTRj6A1cpv7xRvrbNVFsKrZPP5HFGvEm7HGQiMn/s1600/3.png" /></div>
<br />
<h3>Skalární součin</h3>
Skalární součin značíme klasicky $\cdot$ a počítáme jako
\[
u\cdot v=u_1 v_1 + u_2 v_2
\]
Jeho míra odráží úhel mezi vektory a jejich velikost.
<br/><br/>
<h3>Úhel mezi vektory</h3>
Pro výpočet použijeme skalární součin.
\[
cos\alpha=\frac{u\cdot v}{|u||v|}
\]
Velikost vektorů $u$ a $v$ vypočítáme jednoduše z Pythagorovy věty.
<br/><br/>
<strong>Příklad</strong>
<br/>
Nechť jsou zadány vektory
\begin{align*}
u&=(1,0)\\
v&=(2,2)
\end{align*}
Jejich skalární součin bude
\[
u\cdot v=1\cdot 2 + 0\cdot 2=2
\]
a délky vektorů
\begin{align*}
|u|&=\sqrt[]{1^2+0^2}=1 \\
|v|&=\sqrt[]{2^2+2^2}=\sqrt{8}\doteq 2,83
\end{align*}
</br>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBiMQsY84glC_G7CJG-5esjl8XT5646u5aaaHa0Kgmn_GQMjMfJulLLCcyZ_WpG1D14EJ7Su3qWu32cbav61KxCNo4QT4vjbbvWMValyrKqdQ0NAZM3MC5ldIzG8vZPHt28cy1s_kWoH1v/s1600/4.png" /></div>
</br>
Výsledkem je tedy
\begin{align*}
cos\alpha&=\frac{2}{\sqrt{8}}\doteq 0,354 \\
\alpha&=arccos(\frac{2}{\sqrt{8}})=45^{\circ}
\end{align*}
<br />
<h3>Vektorový součin</h3>
Pro vektorový součin používáme znamenénko $\times$. Operace se používá ve 3D, takže rozšíříme vektory o jednu složku $u=(u_1,u_2,u_3)$ a $v=(v_1,v_2,v_3)$.
\[
u\times v=(u_2 v_3 - v_2 u_3, u_3 v_1 - v_3 u_1, u_1 v_2 - v_1 u_2)
\]
Výsledkem nechť je vektor $w$, který se bude rovnat
\[
|w|=|u||v|sin\alpha
\]
a který bude kolmý k oběma vektorům.
<br/><br/>
<strong>Příklad</strong>
Nechť jsou vektory
\begin{align*}
u&=(4,0,0)\\
v&=(0,0,-1)
\end{align*}
Pak se vektorový součin rovná
\[
u\times v=(0 - 0, 0 - (-4), 0 - 0)=(0,4,0)
\]
<br/>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5AbX9MBwrrsLgp4ItPw_f5Z3aktBrhE2tzjqYn0g9yKWCX7wYRRsvNgPykXCDoE2GoCcAMNoQIMVWcl-GR4hoaNKkWvkcjR4sI6Mtvj3u747u1B2dmGujyDNxZFr9hrVmQFQA9z7OfVr7/s1600/5.png" /></div>
</br>
Můžeme ještě ověřit, zda sedí vztah výše.
\[
|w|=\sqrt{0^2+4^2+0^2}=\sqrt{16}=4
\]
Vektory $u$ a $v$ svírají úhel $90^{\circ}$. Pravá strana bude tedy vypadat
\[
|u||v|sin\alpha=\sqrt{4^2+0^2+0^2}\cdot \sqrt{0^2+0^2+(-1)^2}\cdot sin(90)=\sqrt{16}\cdot \sqrt{1}\cdot 1=4
\]
<br />
<h3>Literatura a odkazy</h3>
<a href="http://www.matweb.cz/vektory-operace#gsc.tab=0">http://www.matweb.cz/vektory-operace#gsc.tab=0</a>Anonymoushttp://www.blogger.com/profile/03897622400482861161noreply@blogger.com0