Macbook Pro piirrettynä Sharpening filterin läpi

Reaaliaikaista kuvankäsittelyä OpenGL ES 2.0:lla

Näytönohjaimen (GPU) shader prosessorit tarjoavat hyvän mahdollisuuden tehdä tehokasta – ja toteutuksesta riippuen rinnakkaista – laskentaa CPUn ohella. Nykyisten mobiililaitteidenkin shaderit ovat huomattavan tehokkaita; niiden on kyettävä pyörittämään 3D-pelejä ~30fps jotta käyttökokemus ei kärsi, ja tämä puolestaan tarkoittaa hurjaa määrää laskutoimituksia sekunnissa. Kuten edeltävässä postauksessani mainitsin, signaalinkäsittely on yksi luonnollinen sovelluskohde. Tässä postauksessa katsotaan hieman miten valjastaa GPU reaaliaikaisen kuvankäsittelyn käyttöön ja toteutetaan geneerinen konvoluutiomatriisi shaderilla. Toteutus on iPhone-spesifinen mutta helposti portattavissa muille alustoille.

Esimerkkiämme varten kuvadata haetaan laitteen kameralta; aina kun saadaan uusi kuva, se uploadataan OpenGL:lle tekstuuriksi. Tämä tekstuuri sitten renderöidään konvoluutioshaderin läpi toiseen tekstuuriin. Tämän uuden tekstuurin data luetaan ulos OpenGL:ltä ja käytetään – esimerkin vuoksi vain näytetään ruudulla. Pelkästään tähän käyttöön tuloksen kierrättäminen tekstuurin / UIImage kautta on tietysti kamalan tehotonta, kun se voitaisiin suoraan piirtää näyttömuistiin.  Tämänkaltainen toteutus kuitenkin mahdollistaisi monenlaista käsittelyä tulosdatalle. Lisäksi koodiesimerkki näyttää kuinka OpenGL ES 2.0:lla renderöidään tekstuuriin. Katso prosessin kuvaava tilakaavio alla:

Konvoluutiofiltterit

Konvoluutio ja kuvankäsittelyyn käytetyt matriisit (“kernel”) ovat tämän artikkelin laajuuden ulkopuolista asiaa – katso linkit postauksen lopussa – mutta esittelen toimintaperiaatteen nopeasti niin shaderin koodi aukeaa ehkä paremmin.

Käytän tässä 3×3 kerneleitä suorituskyvyn ja koodin selkeyden vuoksi; 5×5 kernelillä saadaan aikaan huomattavasti parempia tuloksia. Otetaan käsittelyyn helppotajuisin käytetyistä kerneleista, blur kerneli:

|  1/9     1/9     1/9   |
|  1/9     1/9     1/9   |
|  1/9     1/9     1/9   |

Tehdessä muunnosta tälläisellä matriisilla, jokainen kuvan pikseli käsitellään asettamalla matriisin keskimmäinen alkio sen kohdalle, jolloin matriisin muut alkiot asettuvat ympäröivien pikselien “kohdalle”; sitten keskipikselille lasketaan uusi arvo kertomalla jokainen pikseli arvolla joka matriisissa on sen kohdalla ja laskemalla näiden kertolaskujen tulokset yhteen. Blur-matriisin tapauksessa pikseli ja kaikki sen naapurit kerrotaan 1/9:llä, jolloin pikselin arvoksi tulee 9 pikselin keskiarvo. Konvoluutiokerneleillä voi toteuttaa vaikkapa viivantunnistusta, blurreja ja sharpenointia.

Esimerkkitoteutus

Toteutus sisältää geneerisen convolution kernel shaderin (Convolution.fsh) ja neljä eri kerneliä: emboss, blur, gradient, sharpen. Käytettyä kerneliä voi vaihtaa lennosta täppäämällä ruutua. Sovellus syöttää kuvia iPhonen pääkameralta GLSLn läpi ja piirtää tuloksen ruudulle. Ohessa muutama screenshot:

Macbook Pro piirrettynä Embossinging filterin läpi
Macbook Pro piirrettynä Embossinging filterin läpi
Macbook Pro piirrettynä Sharpening filterin läpi
Macbook Pro piirrettynä Sharpening filterin läpi

Siinäpä tämänkertainen anti, ensi episodissa sitten taas jotain aivan muuta!

Lisää luettavaa

Esimerkkitoteutuksen koodi (36kB)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>