Introduzione
Terminato l'articolo sul confronto tra CameraRaw e DCRaw, decido di scrivere una mail a Dave Coffin, l'autore di DCraw. Voglio complimentarmi per il suo ottimo lavoro che ha voluto condividere con il resto del mondo. Già che ci sono provo anche ad illustrargli la mia piccola modifica al suo codice, necessaria all' utilizzo dei profili ICC, sperando magari di convincerlo ad adottarla per le successive versioni del programma. Nelle poche righe che gli scrivo faccio anche riferimento al mio articolo, citando solo le foto, senza tradurlo in inglese. E il giorno dopo mi risponde così:
Ciao Alberto,
Fortunately, my house-guest Gianluca is from Italy, and he
read your article to me. I agree, setting the black point is a
useful feature, so I added it to dcraw v7.60, just released.
There's a more important change in v7.60: Dcraw no longer
uses VNG interpolation for three-color cameras. It now uses the
Adaptive Homogeneity-Directed Demosaicing Algorithm developed by
Keigo Hirakawa and Thomas Parks. ahd_interpolate() takes 2.25
times longer than vng_interpolate(), but the difference in detail
is astounding.
Enjoy!
Dave Coffin 8/30/2005
Non posso certo nascondere di essermi sentito lusingato nel leggere questa mail. L' esperto (forse il più esperto) dei formati RAW ha accettato il mio consiglio .
La mia soddisfazione è superata solo dalla curiosità di scoprire questo nuovo metodo d' interpolazione, che, a quanto pare, fornisce risultati di qualità sorprendente. Così scarico la versione 7.60, la compilo e la provo immediatamente.
Adaptive Homogeneity-Directed interpolation (AHD)
E' un metodo piuttosto complesso che cercherò di semplificare il più possibile. Chi volesse un approfondimento maggiore e una spiegazione più matematica e rigorosa, può scaricare un documento in inglese scritto proprio dagli autori di questo innovativo metodo, Keigo Hirakawa e Thomas Parks : hirakawa03adaptive.pdf
Nell'articolo precedente abbiamo visto come l'algoritmo dei gradienti a numero variabile (VNG) sia in grado di estrarre molte più informazioni rispetto agli altri metodi considerati. Abbiamo anche potuto notare che lungo le linee di discontinuità orizzontali o verticali nascono degli artefatti di colore molto evidenti e fastidiosi. Anche gli algoritmi "adattativi", cioè quelli che variano la direzione di interpolazione in modo intelligente (come quello dei gradienti) non riescono ad eliminare questo inconveniente che prende il nome di zippering (effetto cerniera lampo). Ciò avviene perchè in queste zone, critiche per la struttura stessa della matrice di bayer, la direzione di interpolazione commuta continuamente, dando luogo al un pattern di questo tipo:
Esempio di zippering
Nello studio sui diversi metodi di interpolazione citato nell'articolo precedente compare un algoritmo abbastanza semplice chiamato edge-sensing che funziona così:
Interpolazione per i pixel verdi (per esempio di G8) :
Si definiscono due gradienti
DeltaOrizz = |G7-G9|
DeltaVert = |G3-G13|
e una soglia S.
Se DeltaOrizz < S e DeltaVert > S allora G8 = (G7+G9)/2
Se DeltaOrizz > S e DeltaVert < S allora G8 = (G3+G13)/2
Altrimenti, se entrambi i gradienti sono < S allora G8 = (G7+G9+G3+G13)/4
Interpolazione per i pixel rossi e blu:
Non si può applicare lo stesso metodo anche per i pixel rossi e blu, perchè l'unico colore che compare su tutte le righe e le colonne è il verde. Quindi si deve utilizzare un altro metodo: in genere si usa il metodo Smooth Hue Transition Interpolation in Logarithmic Exposure Space , che non starò a descrivere. In pratica, si basa anche sui valori verdi interpolati in precedenza in modo da non perdere troppo le informazioni sulla direzione corretta di interpolazione.
Una ricostruzione di questo tipo evita l'effetto zippering, in quanto, quando viene rilevata una forte discontinuità nella direzione orizzontale viene utilizzata la direzione di interpolazione verticale e viceversa. Il risultato generale, però, non è esaltante. Il nuovo algoritmo (AHD) concettualmente assomiglia al metodo edge-sensing, però è sviluppato in modo più raffinato e produce risultati decisamente superiori. Vediamo come funziona.
In una transizione da un colore scuro ad uno chiaro, in una situazione reale, il passaggio di colore è graduale, cioè due pixel vicini, nella direzione della transizione, avranno colori "visivamente" simili. Se utilizzassimo le coordinate Lab, vedremmo che lungo la transizione, i pixel adiacenti, a due a due, avrebbero un deltaE piccolo, che diventerebbe ancora più piccolo se riducessimo le dimensioni dei pixel. Quindi, nell'operazione di demosaicizzazione, se dovessimo scegliere tra una direzione di interpolazione che determina un deltaE grande e una direzione che ne determina uno piccolo, sceglieremmo quest'ultima perchè molto più probabile.
Nell' algoritmo edge-sensing, per scegliere la direzione di interpolazione nel quadro verde, considero solo i pixel verdi, e non i rossi e i blu che stanno nelle posizioni da interpolare. Ma in questo modo butto via delle informazioni preziose. Cioè, nella realtà, potrei verificare facilmente che se il canale verde varia rapidamente, anche i canali rosso e blu in quei punti variano rapidamente, in modo da rendere graduale (sempre in senso visivo) la transizione (in altre parole i tre canali RGB risultano fortemente correlati).
Il nuovo algoritmo si basa sul concetto di "omogeneità". Un pixel avrà un grado di omogeneità alto se rispetto ai pixel circostanti il deltaE è piccolo, mentre avrà un valore di omogeneità basso nel caso contrario. Per una data immagine è possibile costruire una mappa di omogeneità, assegnando ad ogni pixel il suo grado di omogeneità. Lo spazio Lab risulta particolarmente adatto a questo scopo per la sua proprietà di uniformità, in quanto il concetto di omogeneità risulta strettamente legato al concetto di deltaE, parametro facilmente calcolabile e indice della differenza visiva fra due colori.
Il metodo di interpolazione AHD consiste in questi tre passi:
Il terzo punto significa:
Poi passo al secondo pixel e così via.
In generale l'operazione di interpolazione soffre di due tipi di artefatti: uno dovuto alla scelta della direzione di interpolazione (che questo sofisticato metodo risolve nel modo migliore) e uno dovuto alla limitazione nell'interpolazione stessa. Per esempio, supponendo di aver scelto la direzione di interpolazione perfetta, per ricavare il valore di un pixel mancante potrei, per esempio, mediare tra i due pixel adiacenti, oppure potrei considerare anche quelli più lontani, oppure potrei usare tecniche ancora più sofisticate. Ovviamente il risultato finale cambierebbe molto.
DCRaw, in questa prima release con l' AHD, ha scelto di utilizzare un' interpolazione abbastanza semplice nelle due direzioni orizzontale e verticale (quella bilineare), e di aggiungere una terza immagine ottenuta con l'algoritmo di edge-sensing (con relativa mappa di omogeneità) da utilizzare nel confronto finale (per i pixel rossi e blu utilizza l'algoritmo di Smooth Hue Transition Interpolation in Logarithmic Exposure Space). Quest'ultima immagine risulta una combinazione delle due precedenti, però porta comunque delle informazioni aggiuntive, grazie alla sua mappa di omogeneità (perchè la "combinazione" è in RGB e la mappa di omogeneità è in Lab).
Nel documento di Keigo Hirakawa e Thomas Parks è spiegata una tecnica più sofisticata di interpolazione orizzontale/verticale, basata su una tecnica ricorsiva a "banco di filtri", che dovrebbe ridurre in modo significativo l'effetto di aliasing e gli artefatti di colore. Sarà questo il prossimo step di DCRaw, a quanto dice l'autore, ma intanto vediamo qualche esempio della versione attuale. Al solito a tutte le immagini è stato applicato un filtro di smart sharpen con Photoshop CS2 (quantità 150, raggio 0.8, more accurate, remove gaussian blur)
Ho inserito anche il metodo di interpolazione bilineare (non adattativo) che produce ovviamente i risultati più scarsi.
Si può notare come le linee orizzontali e verticali siano decisamente migliorate col nuovo metodo (AHD) rispetto a quello dei gradienti (VNG) e senza perdita di dettagli. Anche Camera Raw riesce ad evitare artefatti lungo queste direzioni, con un livello di dettagli, però, decisamente inferiore.
Qui la superiorità del metodo AHD è più che evidente: è l'unico caso in cui si riescono ad intravedere i numeri della targa. Solo il metodo VNG riesce ad avvicinarsi, a scapito, però, di un forte effetto zippering.
Se osservate la linea obliqua tra la sella ed il serbatoio potete notare una leggera superiorità del metodo VNG su quello AHD. L'interpolazione "solo orizzontale" o "solo verticale" di AHD ha il suo punto debole nelle linee di discontinuità a +/- 45° e negli angoli a 90°, anche se è veramente molto lieve. In compenso evita l'effetto "zucchero filato" del cavo elettrico.
Qui si nota in AHD uno strano pattern nel cielo dovuto al rumore. I cambiamenti di direzione orizzontale-verticale hanno disegnato quella specie di labirinto che in VNG non c'è, grazie alla variazione di direzione di interpolazione molto più casuale. Camera Raw elimina molto rumore , ma anche molti dettagli. Una prossima versione di DCRaw potrebbe ridurre in maniera rilevante questo effetto .
Qui il labirinto è molto più evidente, tant'è che si nota anche in Camera Raw (un po' si vedeva anche nell'esempio precedente). Da questa osservazione mi è nato il sospetto che l'algoritmo di interpolazione di Camera Raw si basi su quello di edge-sensing, oltre al fatto che non sono presenti effetti di zippering. Ho provato a chiederlo a Dave Coffin, che mi ha girato uno stralcio di una sua mail in cui chiedeva, per curiosità, a Thomas Knoll quale fosse l'algoritmo che aveva usato per Camera Raw. La risposta è stata: -Nella prima versione ho utilizzato uno degli algoritmi pubblicati, poi l'ho più volte ritoccato, così ora Photoshop utilizza un algoritmo esclusivo.- Allora Dave ha chiesto:- Qual'era l'algoritmo iniziale?- Thomas:- Non so se posso darti quest'informazione riservata se non sei un affiliato Adobe. Vuoi diventarlo?- E Dave non ha voluto.
Nell'articolo precedente, parlando di conversione da 12 a 16 bit, avevo detto che occorre moltiplicare i valori letti dal sensore (e interpolati) per un coefficiente uguale a 216-12=24=16 . Quando facciamo una conversione con DCRaw abbiamo questa videata :
I valori chiamati pre_mul[] sono proprio i coefficienti moltiplicativi utilizzati per trasformare l'immagine da 12 a 16 bit, nei tre canali RGB.
Come si può notare tali coefficienti risultano maggiori o uguali a 16. Questo perchè DCRaw fa un bilanciamento del bianco (fisso e un po' approssimativo) che viene calcolato a seconda del modello della fotocamera. Questi valori , quindi, non cambiano da foto a foto, ma sono caratteristici della macchina utilizzata. Si possono dunque creare profili ICC senza problemi. I programmi che li creano (come Profilemaker, Monaco Profiler ecc), danno dei messaggi di warning se i valori RGB di certe tacche non rientrano in intervalli stabiliti. Per esempio, se la tacca bianca non rientra nell'intervallo RGB 210-245 il programma ci informa che la foto è sottoesposta o sovraesposta. Se le tacche grigie hanno valori RGB non uguali ci informa che il bilanciamento del bianco non è perfetto. Questo perchè sono stati programmati per creare profili su immagini già bilanciate. Se gli diamo in pasto un'immagine per loro troppo scalibrata non riescono a creare profili accurati. In genere il bilanciamento fatto da DCRaw è sufficiente per creare profili di buona qualità (non ad eliminare i messaggi di warning), però è un bilanciamento che introduce della distorsione. Infatti utilizzare coefficienti moltiplicativi maggiori di 16 (per una fotocamera a 12 bit) significa "clippare" le alte luci, come si può facilmente verificare dagli istogrammi:
Istogrammi originali (pre_mul[] = 16,16,16)
|
Istogrammi clippati (pre_mul[] = 42,16,22)
|
|
|
Moltiplicare i valori a 12 bit per 42.37 significa che saranno clippati tutti i pixel di valore 216/42.37=1146, che riportato alla scala di 8 bit diventerebbe 1146/16=96.6. Moltiplicarli per 21.7 vuol dire clippare tutti i pixel con valore, in scala a 8 bit, di 188.7. Ovvero sarebbe come applicare le seguenti curve:
|
|
|
Non è una conversione ottimale. Arrivati a questo punto vorrei avere il controllo completo del procedimento, cioè vorrei ottenere esattamente quello che la fotocamera vede per poi intervenire manualmente . Quindi mi sono preso anche questa volta la libertà di modificare un po' il codice sorgente di DCRaw, e il risultato è quello sotto:
Innanzi tutto notiamo l'opzione integrata da Dave sul punto del nero; rispetto alla mia modifica ha introdotto la possibilità di settare k ad un valore qualunque, non solo zero. Sotto a quest'opzione troviamo la mia aggiunta: -x. Attivandola, i coefficienti pre_mul[] saranno uguali a 16 per le fotocamere a 12 bit, a 64 per le fotocamere a 10 bit ecc.
Quest'opzione non è da attivare con le fotocamere che hanno sensori a quattro colori (tipo RGBE o CMYW), perchè il risultato sarebbe imprevedibile.
Va utilizzata solo con le fotocamere RGB, che poi sono la stragrande maggioranza. Non credo che Dave Coffin abbia intenzione di integrare anche questo cambiamento nella versione ufficiale di DCRaw, proprio perchè non può essere applicato indistintamente a tutte le fotocamere. Per ora è una peculiarità delle versioni distribuite da me. Vediamo come si presenta un target a 24 tacche esposto correttamente alla luce del sole (circa 5000°K). Gli ho assegnato il profilo sRGB, che sicuramente non è appropriato, ma occorre sceglierne uno come punto di partenza.
Conversione con pre_mul[] = 16 16 16
|
|
E' molto scuro e con una forte dominante blu/ciano. Se provo a dare in pasto quest'immagine ai programmi che creano i profili ICC per le fotocamere, esce un profilo inutilizzabile perchè è troppo scalibrata . Per aggiustarla uso le curve di Photoshop.
|
|
|
Conversione con pre_mul[] = 16 16 16 + Curve di Photoshop
|
|
Come si vede le curve sono molto più dolci e non introducono clipping . La calibrazione è stata veloce e un po' grossolana, cioè ho portato la tacca bianca dentro l'intervallo di valori corretti e ho bilanciato una tacca grigia, ma comunque è più che sufficiente per creare un profilo di buona qualità.
In realtà non è ancora il metodo migliore, come è spiegato in un prossimo articolo. La cosa importante, comunque, è impedire a DCRaw di fare un bilanciamento del bianco fisso, per una situazione diversa dalla nostra, che ci porterebbe un clipping inutile delle alte luci.
Le curve utilizzate per creare il profilo vanno salvate perchè sono necessarie ad ogni utilizzo del profilo. Ovvero la procedura sarà:
Download
DCRaw 7.60 per Windows
Questa versione supporta tutte le fotocamere attualmente esistenti (10/09/2005), compreso il formato DNG della Adobe (Adobe Digital Negative) .
Per cui è possibile convertire, con il software Adobe, un qualunque formato raw (anche posteriore a questa data) al formato DNG senza perdita di informazione, e successivamente utilizzare DCRaw.
Profilo ICC per Pentax *ist DS da usare direttamente sull'immagine convertita senza attivare l'opzione -x
Profilo ICC per Nikon D70 da usare direttamente sull'immagine convertita senza attivare l'opzione -x
Esempio di un immagine convertita con DCRaw e successivamente elaborata (in particolare è stato applicato un filtro di smart sharpen con Photoshop CS2, quantità 150, raggio 0.8, more accurate, remove gaussian blur)
IMGP0542.jpg (5 MB !!)
IMGP0542.PEF (10.6 MB !!) Immagine originale Raw
E' disponibile una versione gratuita di UFRaw che non è altro che un' interfaccia grafica per DCRaw. E' un plug-in di Gimp, che è un programma freeware di fotoritocco. GIMP è un acronimo per GNU Image Manipulation Program. E' disponibile sia per Windows che per Mac e rende più user-friendly l'utilizzo di DCRaw. Ovviamente non comprende le opzioni -x e -k da me introdotte, però permette anche a chi non può o non vuole fare profili per la propria fotocamera, di provare l'algoritmo VNG di DCRaw.
Per semplificare ho scaricato e resi disponibili su PhotoActivity i files necessari per Windows. In ordine le operazioni da fare: