Qual è il modo migliore per calcolare la media di due colori che definiscono un gradiente lineare?

StackOverflow https://stackoverflow.com/questions/649454

  •  19-08-2019
  •  | 
  •  

Domanda

Se ho due colori definiti dai loro valori RGB, posso fare una media dei valori di Rosso, Verde e Blu e quindi combinarli per definire un terzo colore che assomigli a una media visiva dei due?

ovvero NewColor = (R1 + R2) / 2, (G1 + G2) / 2, (B1 + B2) / 2

EDIT1: grazie per tutte le risposte. Per le mie esigenze attuali, ho a che fare solo con coppie di colori che sono sfumature dello stesso colore, quindi penso che la media funzionerà. Tuttavia, proverò a convertirmi in Lab Space per assicurarmi che il presupposto sia vero e che la tecnica sarà utile in futuro.

EDIT2: ecco i miei risultati FWIW. Color1 e Color2 sono i miei due colori e le due colonne centrali sono il risultato della media nello spazio L a b e della media RGB rispettivamente. In questo caso non c'è molta differenza tra i due colori e quindi le differenze nell'output rispetto alle tecniche di calcolo della media sono sottili.

confronto visivo delle tecniche di media dei colori

È stato utile?

Soluzione

Dai un'occhiata alle risposte a questa domanda .

Fondamentalmente, vuoi convertire i colori in qualcosa chiamato Lab space e trovare il loro spazio media in quello spazio.

Lo spazio di laboratorio è un modo di rappresentare i colori in cui i punti vicini tra loro sono quelli che sembrano simili tra loro agli umani.

Altri suggerimenti

Diverse risposte suggeriscono la conversione nello spazio colore Lab - che è probabilmente un buon approccio per una manipolazione del colore più complessa.

Ma se hai semplicemente bisogno di un modo rapido per prendere la media di due colori, questo può essere fatto nello spazio RGB. Devi solo fare attenzione: devi quadrare i valori RGB prima di farne la media, quindi prendere la radice del risultato. (Se prendi semplicemente la media, il risultato tenderà ad essere troppo scuro.)

In questo modo:

NewColor = sqrt((R1^2+R2^2)/2),sqrt((G1^2+G2^2)/2),sqrt((B1^2+B2^2)/2)

Ecco un ottimo video che spiega perché questo metodo è efficiente: https://www.youtube.com/watch?v = LKnqECcg6Gw

La media nello spazio colore HSL potrebbe produrre risultati migliori.

Non so se prendere una media semplice dei componenti sia il "migliore" da un punto di vista percettivo (sembra una domanda per uno psicologo), ma qui ci sono un paio di esempi che usano la media dei componenti semplici.

alt text

Quello rosso senape è brutto ma l'interpolazione sembra abbastanza ragionevole.

Sì. Puoi fare una media di due colori insieme in questo modo. È l'approccio utilizzato da OpenGL per fondere insieme i colori (ad esempio, nella creazione di mappe mip per il rendering di oggetti distanti o il rendering di una trama trasparente al 50%). È veloce, semplice e "abbastanza buono" per molte situazioni. Non è del tutto realistico, tuttavia, e probabilmente non verrebbe utilizzato su immagini di qualità fotografica.

Questo è difficile. Innanzitutto, un insieme di valori RGB non definisce un colore. Devono essere interpretati alla luce delle primarie di colore a cui si riferiscono (lo spazio colore), come sRGB, Rec.709, Rec.2020, Adobe RGB (1998), ecc.

Inoltre, i valori RGB così come li incontriamo normalmente non sono proporzionali alla luce lineare: sono "codificati" utilizzando una funzione non lineare (gamma). E a volte (soprattutto nelle applicazioni video) il valore di "nero" non è zero, ma è sfalsato da zero, generalmente 16 per valori a 8 bit. E "bianco" non è 255 ma 235. sRGB e Rec.709 condividono le primarie RGB, ma le loro funzioni gamma sono diverse.

La conversione dello spazio colore inizia con la rimozione di qualsiasi offset nero in modo che il nero sia zero. Se la funzione gamma ha un punto di interruzione (come fanno sRGB e Rec.709), dovrai ridimensionare attentamente i valori RGB in modo che "bianco" è 1.0.

Quindi, " decodifica " la gamma facendo l'inverso della funzione gamma originale. (Una risposta suggeriva di quadrare i valori, che è un'approssimazione della decodifica gamma.) Ora hai dei valori RGB a luce lineare in uno spazio di colore. A questo punto puoi convertire da quello spazio colore allo spazio Lab. La maggior parte delle conversioni da RGB a Lab passa attraverso uno spazio colore intermedio chiamato XYZ.

I passaggi come la funzione nidificata chiama:

Lab = XYZ2Lab (RGB2XYZ (gamma_decode (offset_and_scale (RGB), gammaFunzione ), spazio colore RGB ))

(Lab space è stato sviluppato nel 1976 come un tentativo di creare una deformazione percettiva uniforme dello spazio CIE XYZ standard. (Luv è stato un altro tentativo.) L'idea è che la distanza euclidea (linea retta) tra due colori che erano evidentemente differenti (1 "JND") sarebbero la stessa distanza per due colori qualsiasi. La distanza tra due colori in Lab è conosciuta come "delta-E". La semplice formula della distanza euclidea delta è ora chiamata dE76. Vedi https://en.wikipedia.org/wiki/Color_difference )

Nel tuo caso, potresti ottenere la media dei due colori Lab per ottenere un nuovo colore Lab, quindi invertire tutte le conversioni per tornare a RGB nello spazio colore scelto.

Questo ti avvicinerà, ma non è garantito, semplicemente perché " color " è una percezione umana, non una quantità fisica, ed è notoriamente difficile da caratterizzare in modo affidabile. Lab non ha funzionato così bene per essere percettivamente uniforme. Quindi, piuttosto che aggiustare Lab, hanno proposto una nuova, più complessa funzione delta-E con un altro ordito incorporato: DE94. Era meglio, ma non perfetto, quindi nel 2000 è emersa un'altra proposta: DE2000. Anche meglio ma non perfetto. Vedi quella pagina Wiki sopra per maggiori informazioni.

Se DE2000 non è abbastanza buono (o troppo complesso!) potresti dare un'occhiata a un'alternativa a Lab chiamata ICtCp che si afferma sia più percettivamente uniforme di Lab.

Penso che la risposta di arntjw vada nella giusta direzione e riconosca la base logaritmica, come menzionato da Dan W. Tuttavia, la media geometrica corretta non è sqrt ((C1 ^ 2 + C2 ^ 2) / 2) , ma sqrt (C1 * C2). Quindi il colore medio sarebbe:

NewColor = sqrt(R1*R2),sqrt(G1*G2),sqrt(B1*B2)

I colori risultanti sono più vicini a ciò che ci aspettiamo. Puoi generalizzare a più colori usando radici di ordine superiore e ponderare ogni colore aggiungendo un esponente ai suoi componenti.

In realtà c'è un modo molto più semplice.

  • Ridimensiona l'immagine di 1 pixel per 1 pixel.

    Il colore di 1px è il colore medio di tutto ciò che hai ridimensionato

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top