Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2018:raspberry-video

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
2018:raspberry-video [2019/01/13 16:35]
Tomáš Bravenec [Filtr Sobel]
2018:raspberry-video [2019/01/14 13:45] (aktuální)
Tomáš Bravenec
Řádek 155: Řádek 155:
  
 ==== Filtr Sobel ==== ==== Filtr Sobel ====
-Detekce hran pomocí filtru sobel je tvořena výpočtem dvou gradientů pomocí 2D konvoluce ​iltrů s obrazem v odstínech šedi, každý z nich vyjadřuje sílu hrany v horizontálním nebo vertikálním směru. Pro získání jednoho obrazu z těchto gradientů, se využívá odmocniny ze součtu druhých mocnin obou gradientů, a to pro každý pixel. Jelikož je ale odmocnina výpočetně náročná, lze tento výpočet nahradit přibližnou aproximací pomocí součtu absolutních hodnot gradientů. Takto zkombinované horizontální a vertikální hrany poté stačí jen prohnat prahováním pro dosžení výsledku.+Detekce hran pomocí filtru sobel je tvořena výpočtem dvou gradientů pomocí 2D konvoluce ​filtrů s obrazem v odstínech šedi, každý z nich vyjadřuje sílu hrany v horizontálním nebo vertikálním směru. Pro získání jednoho obrazu z těchto gradientů, se využívá odmocniny ze součtu druhých mocnin obou gradientů, a to pro každý pixel. Jelikož je ale odmocnina výpočetně náročná, lze tento výpočet nahradit přibližnou aproximací pomocí součtu absolutních hodnot gradientů. Takto zkombinované horizontální a vertikální hrany poté stačí jen prohnat prahováním pro dosžení výsledku. 
  
 ==== Detektor hran - Canny ==== ==== Detektor hran - Canny ====
Řádek 162: Řádek 163:
 ==== Srovnání fitru Sobel a Cannyho detektoru ==== ==== Srovnání fitru Sobel a Cannyho detektoru ====
 Při porovnání obou přístupů,​ si lze všimnout, silnějších čar, které nebyly utlumeny ani při použití vysokého prahu, na rozdíl od toho, při použití Cannyho detektoru a velmi nízkého prahu jsou v obraze lépe viditelné hrany, a výstup vypadá celkově lépe, ale za cenu náročnějšího zpracování. Při porovnání obou přístupů,​ si lze všimnout, silnějších čar, které nebyly utlumeny ani při použití vysokého prahu, na rozdíl od toho, při použití Cannyho detektoru a velmi nízkého prahu jsou v obraze lépe viditelné hrany, a výstup vypadá celkově lépe, ale za cenu náročnějšího zpracování.
-^ Vstupní obraz ^ Filtr Sobel, Práh = 1.0 ^ Cannyho detektor, Práh = 0.15 ^+ 
 +^ Vstupní obraz ^ Filtr Sobel, Práh = 1.0 ^ Cannyho detektor, Práh = 0.^
 |{{ :​2018:​raspberry-video:​sparrow.jpg?​250 |}}|{{ :​2018:​raspberry-video:​sparrow_edge_sobel_1.png?​250 |}}|{{ :​2018:​raspberry-video:​sparrow_edge_canny.png?​250 |}}| |{{ :​2018:​raspberry-video:​sparrow.jpg?​250 |}}|{{ :​2018:​raspberry-video:​sparrow_edge_sobel_1.png?​250 |}}|{{ :​2018:​raspberry-video:​sparrow_edge_canny.png?​250 |}}|
 |{{ :​2018:​raspberry-video:​lenna.jpg?​250 |}}|{{ :​2018:​raspberry-video:​lena_sobel.png?​250 |}}|{{ :​2018:​raspberry-video:​lena_canny.png?​250 |}}| |{{ :​2018:​raspberry-video:​lenna.jpg?​250 |}}|{{ :​2018:​raspberry-video:​lena_sobel.png?​250 |}}|{{ :​2018:​raspberry-video:​lena_canny.png?​250 |}}|
Řádek 170: Řádek 172:
  
 Pro snadné pochopení jak K-Means funguje v případě obrazů, si lze představit trojrozměrné pole se všemi stranami o délce 256 prvků (každá z os představuje jednu z barevných složek RGB). Pro začátek se náhodně zvolí K bodů (clusterů) z tohoto pole, načež se pro každý pixel vstupního obrazu vypočítá euklidovská vzdálenost ke každému z těchto bodů. Následně se zprůměrují hodnoty barevných složek které jsou nejblíže k jednomu z bodů a tento průměr se nastaví jako nový bod do další iterace. Toto se provede pro všech K bodů, a poté stále dokola v dalších iteracích dokud se body budou v daném trojrozměrném poli posouvat (barva všech bodů nebude stejná, jako v předchozí iteraci). Pro snadné pochopení jak K-Means funguje v případě obrazů, si lze představit trojrozměrné pole se všemi stranami o délce 256 prvků (každá z os představuje jednu z barevných složek RGB). Pro začátek se náhodně zvolí K bodů (clusterů) z tohoto pole, načež se pro každý pixel vstupního obrazu vypočítá euklidovská vzdálenost ke každému z těchto bodů. Následně se zprůměrují hodnoty barevných složek které jsou nejblíže k jednomu z bodů a tento průměr se nastaví jako nový bod do další iterace. Toto se provede pro všech K bodů, a poté stále dokola v dalších iteracích dokud se body budou v daném trojrozměrném poli posouvat (barva všech bodů nebude stejná, jako v předchozí iteraci).
 +
 +Kód provádějící jednu iteraci je níže. Z kódu je opět vidět nastavení OpenMP, následované opět **for** cykly procházející každý řádek a sloupec, tentokrát ovšem obraz není v odstínech šedi, je proto nutné krokovat vždy po třech bytech (RGB), dále je potřeba při indexaci místo počtu sloupců využít **step**, cž je počet Bytů v jednom řádku, který je často o jeden až 3 Byty větší než počet sloupců * 3, jedná se o zarovnání řádků na násobek 32 bitů. Euklidovská vzdálenost je počítána bez odmocniny, která nemá vliv na srovnání vzdálenosti,​ a sníží se tak výpočetní náročnost. Vzdálenost pixelu k prvnímu bodu je vždy nejkratší,​ proto není potřeba žádná další kontrola. Pro následující body je již nutné vzdálenost zkontrolovat a pokud bude pixel blíž jinému než prvnímu bodu, změní se jeho přidělení. Pro přepočet bodů se poté přičtou jednotlivé barevné složky do bodu a zvedne se počítadlo pixelů které k tomuto bodu patří. Posledním krokem je nastavení pixelů výstupního obrazu na barvy bodů pro případ, že by již nedošlo k další iteraci. ​
 +
 +<code cpp>
 +void KMeans::​iterate()
 +{
 +    omp_set_dynamic(0);​
 +    omp_set_num_threads(threadCount);​
 +
 +    unsigned char *imageData = image.data;
 +    unsigned char *clusteredData = clustered.data;​
 +
 +#pragma omp parallel for
 +    for (int i = 0; i < image.rows; i++)
 +    {
 +        for (int j = 0; j < image.cols * 3; j += 3)
 +        {
 +            int shortestDist = 0, shortestCluster = 0;
 +            for (int k = 0; k < clusterCount;​ k++)
 +            {
 +                if (k == 0)
 +                {
 +                    shortestDist = (pow(imageData[i * image.step + j + 0] - newCluster[k].centroidRed,​ 2) +
 +                                    pow(imageData[i * image.step + j + 1] - newCluster[k].centroidGreen,​ 2) +
 +                                    pow(imageData[i * image.step + j + 2] - newCluster[k].centroidBlue,​ 2));
 +                    shortestCluster = k;
 +                }
 +                if ((pow(imageData[i * image.step + j + 0] - newCluster[k].centroidRed,​ 2) +
 +                     ​pow(imageData[i * image.step + j + 1] - newCluster[k].centroidGreen,​ 2) +
 +                     ​pow(imageData[i * image.step + j + 2] - newCluster[k].centroidBlue,​ 2)) < shortestDist)
 +                {
 +                    shortestDist = (pow(imageData[i * image.step + j + 0] - newCluster[k].centroidRed,​ 2) +
 +                                    pow(imageData[i * image.step + j + 1] - newCluster[k].centroidGreen,​ 2) +
 +                                    pow(imageData[i * image.step + j + 2] - newCluster[k].centroidBlue,​ 2));
 +                    shortestCluster = k;
 +                }
 +            }
 +
 +            newCluster[shortestCluster].addRedValue(imageData[i * image.step + j + 0]);
 +            newCluster[shortestCluster].addGreenValue(imageData[i * image.step + j + 1]);
 +            newCluster[shortestCluster].addBlueValue(imageData[i * image.step + j + 2]);
 +            newCluster[shortestCluster].increaseCount();​
 +
 +            clusteredData[i * image.step + j + 0] = newCluster[shortestCluster].centroidRed;​
 +            clusteredData[i * image.step + j + 1] = newCluster[shortestCluster].centroidGreen;​
 +            clusteredData[i * image.step + j + 2] = newCluster[shortestCluster].centroidBlue;​
 +        }
 +    }
 +}
 +</​code>​
  
 Výstupem metody K-Means Clustering může být například:​ Výstupem metody K-Means Clustering může být například:​
Řádek 190: Řádek 242:
  
 https://​gitlab.com/​tbravenec/​image_processing_on_rpi https://​gitlab.com/​tbravenec/​image_processing_on_rpi
 +
 +Nebo poslední verze git repozitáře před odevzdáním:​
 +
 +{{ :​2018:​raspberry-video:​image_processing_on_rpi-master.zip |}}
  
 ====== Závěr ====== ====== Závěr ======
2018/raspberry-video.1547393739.txt.gz · Poslední úprava: 2019/01/13 16:35 autor: Tomáš Bravenec