Quali sono le differenze pratiche quando si lavora con i colori in uno spazio RGB lineare rispetto a uno non lineare?


91

Qual è la proprietà fondamentale di uno spazio RGB lineare e qual è la proprietà fondamentale di uno spazio non lineare? Quando si parla dei valori all'interno di ogni canale in quegli 8 (o più) bit, cosa cambia?

In OpenGL, i colori sono valori 3 + 1, e con questo intendo RGB + alpha, con 8 bit riservati a ciascun canale, e questa è la parte che ottengo chiaramente.

Ma quando si tratta di correzione gamma non capisco quale sia l'effetto di lavorare in uno spazio RGB non lineare.

Dato che so come usare una curva in un software grafico per il fotoritocco, la mia spiegazione è che in uno spazio RGB lineare si prendono i valori così come sono, senza manipolazione e senza funzione matematica collegata, invece quando non è lineare ciascuno il canale di solito si evolve seguendo un comportamento classico della funzione di potenza.

Anche se prendo questa spiegazione come quella reale, non riesco ancora a capire cos'è uno spazio lineare reale, perché dopo il calcolo tutti gli spazi RGB non lineari diventano lineari e, soprattutto, non ottengo la parte in cui un non -Lo spazio colore lineare è più adatto all'occhio umano perché alla fine tutti gli spazi RGB sono lineari per quello che ho capito.


In pratica, puoi specificare RGB lineare o standard come spazio colore in SVG e non ho idea di quale sia l'effetto, a parte il fatto che questo sembra essere importante :-)
Michael Mullany

@MichaelMullany questa cosa lineare sembra più un suggerimento per l'utente che una vera qualità distintiva.
Ken

Qualcosa che mi ha aiutato: penso che sia stato un insegnante di matematica che mi ha detto "pensa alla linea quando senti lineare". Non sono sicuro che questo possa aiutare, ma per me è stato un "Oh yeah!" momento
Joe Plante

Risposte:


236

Supponiamo che tu stia lavorando con i colori RGB: ogni colore è rappresentato con tre intensità o luminosità. Devi scegliere tra "RGB lineare" e "sRGB". Per ora, semplificheremo le cose ignorando le tre diverse intensità e assumendo che tu abbia solo un'intensità: cioè, hai a che fare solo con sfumature di grigio.

In uno spazio colore lineare, la relazione tra i numeri memorizzati e le intensità che rappresentano è lineare. In pratica, questo significa che se raddoppi il numero, raddoppi l'intensità (la luminosità del grigio). Se vuoi aggiungere due intensità insieme (perché stai calcolando un'intensità in base ai contributi di due sorgenti luminose, o perché stai aggiungendo un oggetto trasparente sopra un oggetto opaco), puoi farlo semplicemente aggiungendo il due numeri insieme. Se stai eseguendo qualsiasi tipo di fusione 2D o ombreggiatura 3D, o quasi qualsiasi elaborazione delle immagini, allora vuoi le tue intensità in uno spazio colore lineare, quindi puoi semplicemente aggiungere, sottrarre, moltiplicare e dividere i numeri per avere lo stesso effetto sulle intensità. La maggior parte degli algoritmi di elaborazione e rendering del colore fornisce risultati corretti solo con RGB lineare, a meno che non si aggiungano pesi extra a tutto.

Sembra davvero facile, ma c'è un problema. La sensibilità dell'occhio umano alla luce è più fine a basse intensità rispetto alle alte intensità. Vale a dire, se fai un elenco di tutte le intensità che puoi distinguere, ce ne sono più di quelle scure di quelle chiare. Per dirla in un altro modo, puoi distinguere le sfumature scure del grigio meglio di quanto puoi fare con le tonalità chiare del grigio. In particolare, se stai usando 8 bit per rappresentare la tua intensità, e lo fai in uno spazio colore lineare, ti ritroverai con troppe tonalità chiare e non abbastanza tonalità scure. Ottieni bande nelle tue aree scure, mentre nelle tue aree chiare, stai sprecando bit su diverse tonalità di quasi bianco che l'utente non può distinguere.

Per evitare questo problema e fare il miglior uso di questi 8 bit, tendiamo a usare sRGB . Lo standard sRGB ti dice una curva da usare per rendere i tuoi colori non lineari. La curva è meno profonda nella parte inferiore, quindi puoi avere più grigi scuri e più ripida nella parte superiore, in modo da avere meno grigi chiari. Se raddoppi il numero, raddoppi più che l'intensità. Ciò significa che se aggiungi i colori sRGB insieme, ottieni un risultato più chiaro di quanto dovrebbe essere. Oggigiorno, la maggior parte dei monitor interpreta i colori di input come sRGB. Quindi, quando metti un colore sullo schermo o lo memorizzi in una texture a 8 bit per canale, memorizzalo come sRGB , in modo da sfruttare al meglio quegli 8 bit.

Noterai che ora abbiamo un problema: vogliamo che i nostri colori vengano elaborati in uno spazio lineare, ma memorizzati in sRGB. Ciò significa che si finisce per eseguire la conversione da sRGB a lineare in lettura e la conversione da lineare a sRGB in scrittura. Come abbiamo già detto, le intensità lineari a 8 bit non hanno abbastanza scuri, questo causerebbe problemi, quindi c'è un'altra regola pratica: non usare colori lineari a 8 bit se puoi evitarlo. Sta diventando convenzionale seguire la regola secondo cui i colori a 8 bit sono sempre sRGB, quindi esegui la conversione da sRGB a lineare contemporaneamente allargando l'intensità da 8 a 16 bit o da intero a virgola mobile; allo stesso modo, quando hai terminato l'elaborazione in virgola mobile, riduci a 8 bit contemporaneamente alla conversione in sRGB. Se segui queste regole,

Quando leggi un'immagine sRGB e desideri intensità lineari, applica questa formula a ciascuna intensità:

float s = read_channel();
float linear;
if (s <= 0.04045) linear = s / 12.92;
else linear = pow((s + 0.055) / 1.055, 2.4);

Andando dall'altra parte, quando vuoi scrivere un'immagine come sRGB, applica questa formula a ciascuna intensità lineare:

float linear = do_processing();
float s;
if (linear <= 0.0031308) s = linear * 12.92;
else s = 1.055 * pow(linear, 1.0/2.4) - 0.055; ( Edited: The previous version is -0.55 )

In entrambi i casi, il valore in virgola mobile va da 0 a 1, quindi se stai leggendo interi a 8 bit devi prima dividere per 255 e se stai scrivendo interi a 8 bit vuoi moltiplicare per 255 Infine, come faresti normalmente. Questo è tutto ciò che devi sapere per lavorare con sRGB.

Finora ho affrontato una sola intensità, ma ci sono cose più intelligenti da fare con i colori. L'occhio umano può distinguere le diverse luminosità meglio di diverse tinte (più tecnicamente, ha una risoluzione della luminanza migliore della crominanza), quindi puoi fare un uso ancora migliore dei tuoi 24 bit memorizzando la luminosità separatamente dalla tinta. Questo è ciò che cercano di fare le rappresentazioni YUV, YCrCb, ecc. Il canale Y è la luminosità complessiva del colore e utilizza più bit (o ha una risoluzione spaziale maggiore) rispetto agli altri due canali. In questo modo, non è (sempre) necessario applicare una curva come si fa con le intensità RGB. YUV è uno spazio colore lineare, quindi se raddoppi il numero nel canale Y, raddoppi la luminosità del colore, ma non puoi aggiungere o moltiplicare i colori YUV insieme come puoi con i colori RGB, quindi '

Penso che questo risponda alla tua domanda, quindi concludo con una breve nota storica. Prima di sRGB, i vecchi CRT avevano una non linearità incorporata. Se raddoppi la tensione di un pixel, raddoppi più che l'intensità. Quanto di più era diverso per ogni monitor e questo parametro era chiamato gamma . Questo comportamento era utile perché significava che si potevano ottenere più ombre che luci, ma significava anche che non si poteva dire quanto sarebbero brillanti i colori sul CRT dell'utente, a meno che non lo si calibrasse prima. Correzione gammasignifica trasformare i colori con cui si inizia (probabilmente lineare) e trasformarli per la gamma del CRT dell'utente. OpenGL proviene da questa era, motivo per cui il suo comportamento sRGB a volte è un po 'confuso. Ma i fornitori di GPU ora tendono a lavorare con la convenzione che ho descritto sopra: che quando memorizzi un'intensità a 8 bit in una texture o framebuffer, è sRGB e quando stai elaborando i colori, è lineare. Ad esempio, un OpenGL ES 3.0, ogni framebuffer e texture ha un "flag sRGB" che puoi attivare per abilitare la conversione automatica durante la lettura e la scrittura. Non è necessario eseguire esplicitamente la conversione sRGB o la correzione gamma.


6
risposta incredibile, grazie, è sempre fantastico vedere le cose spiegate, chiederei solo un libro o una risorsa che secondo te sarà abbastanza buona per questo argomento, gli spazi colore e quali sono le formule usate per fare la conversione sRGB <-> lineare o qual è la funzione che può approssimare questo comportamento.
Ken

Temo di non conoscere nessun buon libro o risorsa. La pagina di Wikipedia è completa e include tutte le informazioni sul punto di bianco e su quanto sia piccola la gamma (cosa che non ho menzionato, poiché la maggior parte delle persone non ha bisogno di saperlo), ma questo lo rende un po 'impenetrabile .
Dan Hulme



1

Non sono un "esperto di rilevamento del colore umano", ma ho riscontrato cose simili nella conversione YUV-> RGB. Ci sono pesi diversi per i canali R / G / B, quindi se cambi il colore di origine di x, i valori RGB cambiano quantità diverse.

Come detto, non sono un esperto, comunque, penso, se vuoi fare una trasformazione con colore corretto, dovresti farlo nello spazio YUV, quindi convertirlo in RGB (o fare l'operazione matematicamente equivalente su RGB, attenzione perdita di dati). Inoltre, non sono sicuro che YUV sia la migliore rappresentazione nativa dei colori, ma le videocamere forniscono quel formato, è lì che ho incontrato il problema.

Ecco la formula magica YUV-> RGB con numeri segreti inclusi: http://www.fourcc.org/fccyvrgb.php


1
Fai attenzione alle conversioni RGB <-> YUV e viceversa. Non sono sicuro se questo sia in ogni caso, ma lo spazio colore YUV a volte viene convertito in un intervallo di 16-235 invece dello 0-255 in RGB a 24 bit. Quindi, puoi perdere dati ogni volta che esegui una conversione dello spazio colore. La maggior parte delle persone tende a dire di rimanere nello stesso spazio colore se puoi evitarlo.
Joe Plante
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.