Domanda

Come calcolare somiglianza tra due colori in Rgba? (dove il colore di sfondo è sconosciuta ovviamente)

Ho bisogno di rimappare un'immagine RGBA ad una tavolozza di colori RGBA trovando il migliore voce della tavolozza per ogni pixel dell'immagine *.

Nel spazio colore RGB il colore più simile può essere considerata quella con la più piccola distanza euclidea. Tuttavia, questo approccio non funziona in RGBA, per esempio, distanza euclidea da rgba(0,0,0,0) a rgba(0,0,0,50%) è più piccolo di rgba(100%,100%,100%,1%), ma quest'ultimo sembra molto meglio.

Sto usando premoltiplicato Rgba:

r = r×a
g = g×a
b = b×a

e ho provato questa formula ( Modifica: vedere la risposta qui sotto per una migliore formula ):

Δr² + Δg² + Δb² + 3 × Δa²

ma non aspetto ottimale - in immagini con pendenze semitrasparenti che trova colori sbagliati che causano discontinuità / spigoli vivi. proporzioni lineari tra colori opachi e alfa sembrano pesce.

Qual è la formula ottimale?


*) per semplicità di questa domanda che mi sto ignorando diffusione dell'errore, spazi gamma e colore psicovisuale.


Un po 'correlato: se si vuole trovare il colore più vicino in questo non euclidea spazio RGBA, VP-alberi sono i migliori.

È stato utile?

Soluzione

Infine, ho trovato! Dopo la prova completa e sperimentazione le mie conclusioni sono:

  • Il modo corretto è quello di calcolare massima eventuale differenza tra i due colori.
    Formule con qualsiasi tipo di stima differenza media / tipico avevano spazio per discontinuità.

  • Non sono riuscito a trovare una formula di lavoro che calcola la distanza senza miscelazione dei colori RGBA con alcuni sfondi.

  • Non c'è bisogno di prendere tutti i colori di sfondo possibile in considerazione. Può essere semplificata fino al massimo e minimo miscelazione separatamente per ciascuno dei canali R / G / B:

    1. fondere il canale in entrambi i colori con canale = 0 come sfondo, misurare la differenza al quadrato
    2. fondono il canale in entrambi i colori con canale = max come sfondo, misurare la differenza al quadrato
    3. porti più in alto dei due.

Per fortuna la miscelazione con "bianco" e "nero" è banale quando si utilizza alpha premoltiplicato (r = r×a).

La formula completa è:

max((r₁-r₂)², (r₁-r₂ - a₁+a₂)²) +
max((g₁-g₂)², (g₁-g₂ - a₁+a₂)²) +
max((b₁-b₂)², (b₁-b₂ - a₁+a₂)²)

C Fonte compreso SSE2 implementazione .

Altri suggerimenti

Alcuni principi:

  1. Quando due colori hanno lo stesso alfa, rgbaDistance = rgbDistance * (alpha / 255). Compatibile con RGB algoritmo di distanza di colore quando entrambi alfa sono 255.
  2. tutti i colori con bassissima alfa sono simili.
  3. Il rgbaDistance tra due colori con stesso RGB è linearmente dipendente delta Alpha.
double DistanceSquared(Color a, Color b)
{
    int deltaR = a.R - b.R;
    int deltaG = a.G - b.G;
    int deltaB = a.B - b.B;
    int deltaAlpha = a.A - B.A;
    double rgbDistanceSquared = (deltaR * deltaR + deltaG * deltaG + deltaB * deltaB) / 3;
    return deltaAlpha * deltaAlpha / 2.0 + rgbDistanceSquared * a.A * b.A / (255 * 255);
}

La mia idea sta integrando una volta su tutte le possibili colori di sfondo e in media l'errore quadratico.

vale a dire. per ciascun componente calcolare (utilizzando il canale rosso come ad esempio qui)

integrale da 0 a 1 ((r1 * a1 + rB * (1-a1)) - (r2 * a2 + rB * (1-a2))) ^ 2 * DRB

che se ho calcolato correttamente restituisce:

dA=a1-a2
dRA=r1*a1-r2*a2
errorR=dRA^2+dA*dRA+dA^2/3

E poi riassumere questi oltre R, G e B.

Prima di tutto, un problema molto interessante :)
Non ho una soluzione completa (almeno non ancora), ma ci sono 2 casi estremi ovvi dovremmo prendere in considerazione:
Quando Δa==0 il problema è simile a RGB spazio
Quando Δa==1 il problema è solo l'alfa 1-dim spazio
Così la formula (che è molto simile a quella che si indicato) che soddisfacesse che è:
(Δr² + Δg² + Δb²) × (1-(1-Δa)²) + Δa² o (Δr² + Δg² + Δb²) × (1-Δa²) + Δa²

In ogni caso, sarebbe probabilmente qualcosa come (Δr² + Δg² + Δb²) × f(Δa) + Δa²

Se fossi in te, vorrei cercare di simulare con varie coppie RGBA e di sfondo vari colori per trovare la migliore funzione di f(Δa). Non molto matematica, ma vi darà una risposta abbastanza vicino

Non ho mai fatto, ma la teoria e la pratica diciamo che la conversione dei valori RGB dell'immagine e la tavolozza su luminanza-crominanza ti aiuterà a trovare le migliori corrispondenze. Mi piacerebbe lasciare il canale alfa da solo, come la trasparenza dovrebbe avere poco o nulla a che fare con il 'più bello' parte.

Questa xmass ho fatto alcuni fotomosaici per regali che utilizzano il software open-source che corrisponde frammenti dell'immagine originale ad una raccolta di immagini. Che sembra un problema più difficile di quello che si sta cercando di risolvere. Uno di loro programmi era metapixel .

Infine, l'opzione migliore dovrebbe essere quello di utilizzare una libreria esistente per convertire l'immagine in un formato, come PNG, in cui è possibile controllare la tavolozza.

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