Procesarea de imagini este un proces foarte costisitor, deoarece trebuie procesat fiecare pixel din imagine. Acest lucru este inaceptabil in ziua de azi, cand asteptam ca totul sa fie facut in timp real. M-am gandit ca o serie de tutoriale de procesare de imagini s-ar putea sa prinda bine comunitatii. O sa incep cu ceva foarte simplu si s-ar putea sa continui cu chestii din ce in ce mai avansate (blur, bloom, dithering, poate chiar sa facem propria aplicatie asemanatoare pentru procesare de imagini - slabe sanse sa fac tutoriale despre asa ceva, pentru ca ar interveni mult mai multe lucruri decat procesare de imagini). In aceasta serie voi folosi prorpiul framework(care initial a fost gandit pentru a fi engine pentru un posibil joc) si HLSL pentru 'GPU Work', voi puteti folosi propriul framework, CUDA, OpenCL sau orice doriti voi, eu voi incerca sa explic doar principiile generale.
Grayscale
V-ati gandit vreodata cum se face un simplu GrayScale?
Nu este foarte complicat. Trebuie doar sa adunam toate culorile si sa le impartim la numarul lor ( (R + G + B) / 3 ).
Aceasta ar fi una dintre cele mai simple metode, existand insa si metode mai complicate.
Texture2D ObjTexture : register( t0 ); // Textura din care vom citi
RWTexture2D<float4> ObjResult : register( u0 ); // Textura in care vom scrie (RW = Read Write)
SamplerState ObjWrapSampler : register( s0 ); // Obiectul care ne va ajuta sa luam 'mostre' din textura
[numthreads(32, 32, 1)] // Cate threaduri va avea un grup (X = 32, Y = 32, Z = 1), X * Y * Z = 1024; Este recomandat ca acest numar sa fie divizibil cu 64 pe placile video AMD si divizibil cu 32 pe placile video nVidia (64 va merge si pentru nVidia si pentru AMD)
void main( uint3 DTid : SV_DispatchThreadID ) // DTid = Coordonatele (x,y,z) ale threadului
// Ca sa fie mai usor de inteles DTid.x = [0,width], DTid.y = [0,height] si DTId.z = 0
// Aceste valori au de-aface cu numarul de grupuri alocate de CPU
{
float width, height;
ObjTexture.GetDimensions( width, height );
float2 uv = float2( float( DTid.x ) / width, float( DTid.y ) / height ); // Convertim coordonatele [0,width], respectiv [0,height] in coordonate [0,1]
float4 color = ObjTexture.SampleLevel( ObjWrapSampler, uv, 0 ); // O sa 'mostre' din cea mai detaliata textura (MipMapLevel = 0)
float finalColor = ( color.r + color.g + color.b ) / 3.0f; // calculul efectiv al culorii
ObjResult[ DTid.xy ] = float4( finalColor, finalColor, finalColor, 1.0f ); // scriera pe textura finala
}
Rezultatul final ar trebui sa arate cam asa:
In cazul in care aveti probleme cu intelegerea coordonatelor UV, asta si asta ar trebui sa va ajute.
Toate tutorialele din aceasta serie vor fi postate aici. Acesta fiind locul din care puteti incarca framerwork-ul si rula exemplele folosind framework-ul facut de mine. Daca intampinati probleme clonand repository-ul
In aceasta serie ma voi ocupa in special de partea de procesare de imagini, n-o sa intru in detaliile framework-ului. Singurul lucru pe care trebuie sa-l stiti despre framework este faptul ca face ce trebuie sa faca.