Ripropongo quanto ho cercato di proporre altrove... sperando di attrarre interessati. 🙂 Spero di non aver sbagliato Tag, ma non ne ho visti di più opportuni.
Anni fa era comune sui forum (più piccoli in particolare, forse) una sezione, o sottosezione, dedicata agli esercizi di programmazione, dove gli utenti meno esperti potevano imparare qualcosa, e quelli un pò più navigati diertirsi scoprendo qualcosa di interessante.
L'esercizio che ho scelto di proporre mi fece interessare all'image processing circa una decina di anni fa (ed appartenevo senza dubbio al gruppo dei meno esperti 😛); lo trovo interessante ancora ora, anche per chi ha qualche annetto di programmazione alle/sulle spalle.
Le camere digitali sono dotati di 3 sensori, ciascuno dei quali si occupa di un particolare canale primario. Questi sensori sono noti come CCD (oppure altri, CMOS, ma eviterei dettagli): in buona sostanza ciascun CCD si occupa di un colore (red, green, blue).
Tuttavia, se non siete fotografi professionisti e/o non utilizzate macchine di alto livello, è molto probabile che abbiate utilizzato o stiate utilizzando una macchina dotata di un singolo CCD. In questo caso il filtro viene "coperto" da un CFA (Color Filter Array) il quale farà passare ed imprimere sul px solo uno dei colori primari.
Per ottenere un'immagine completa a colori è necessaria un'elaborazione successiva, nota come demosaicizzazione, che va a ricostruire (stimandoli) i due colori mancanti per ciascun px.
I possibili CFA sono molti, così ne ho scelto uno semplice, il Bayer filter. Si presenta come una griglia (3x3) con il presente pattern:
Spostandosi sull'asse delle ascisse (orizzontale) il pattern sarà ovviamente:
Come funziona?
Immaginatevi di posizionare sull'immagine (che troverete più sotto, in questo post) la griglia iniziale (CFA con la combinazione RGR, GBG, RGR). Con una matrice così composta il px da stimare è quello centrale (blu). L'operazione la si esegue facendo la media dei canali dei px confinanti.
Per essere chiaro, inizialmente avremo:
R G R
G [B] G
R G R
la stima del px centrale blu è data dalle 3 componenti (r, g, b) calcolate in questo modo (l'angolo in alto a sinistra è (0,0)):
b = getBlue(1,1);
r = (getRed(0,0) + getRed(0, 2) + getRed(2, 0) + getRed(2, 2)) / 4;
g = (getGreen(0, 1) + getGreen(1, 0) + getGreen(1, 2) + getGreen(2, 1)) / 4;
I 3 canali separati appena calcolati saranno il nuovo colore del px.
Nella seconda immagine (la seconda iterazione) la griglia viene spostata sull'asse delle ascisse, diventando:
G R G
B [G] B
G R G
come sopra, si avrà (questa volta il px considerato è verde):
g = (getGreen(0,0) + getGreen(0, 2) + getGreen(1,1) + getGreen(2, 0) + getGreen(2, 2)) / 4;
r = (getRed(0, 1) + getRed(2, 1)) / 2;
b = (getBlue(1, 0) + getBlue(1, 2)) / 2;
I 3 canali separati appena calcolati saranno il nuovo colore del px.
Input ed output
L'immagine dovrà essere uguale o molto simile a quella mostrata in output (le dimensioni non sono originali).
Per evitare eventuali problemi di compressione dell'immagine o altro, utilizzate quella zippata in allegato.
Non vi sono limitazioni particolari a parte non utilizzare funzioni built-in proprie del linguaggio o di un'API.
Buon divertimento! 😃