Pregunta

Cómo calcular la similitud entre dos colores en el espacio de color RGBA? (donde el color de fondo es desconocida por supuesto)

Necesito volver a asignar una imagen RGBA a una paleta de colores RGBA encontrando el mejor entrada de la paleta para cada píxel de la imagen *.

En el espacio de color RGB el color más similar puede suponerse que es el que tiene la distancia euclidiana más pequeña. Sin embargo, este enfoque no funciona en RGBA, por ejemplo, la distancia euclídea de rgba(0,0,0,0) a rgba(0,0,0,50%) es menor que a rgba(100%,100%,100%,1%), pero este último se ve mucho mejor.

Estoy usando el espacio de color RGBA premultiplicado:

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

y he probado esta fórmula ( editar Véase la respuesta a continuación para una mejor fórmula ):

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

pero no mirada óptima - en imágenes con gradientes semitransparentes que encuentra colores incorrectos que causan discontinuidades / bordes afilados. proporciones lineales entre colores opacos y alfa parecen a pescado.

¿Cuál es la fórmula óptima?


*) para la simplicidad de esta pregunta que estoy haciendo caso omiso de difusión de errores, espacios de color y gamma psicovisual.


Muy poco relacionado: si usted quiere encontrar el color más cercano en este euclidiana no-espacio RGBA, vp-árboles son los mejores.

¿Fue útil?

Solución

Finalmente, lo he encontrado! Después de exhaustivas pruebas y experimentación mis conclusiones son:

  • La forma correcta es calcular máxima posible diferencia entre los dos colores.
    Las fórmulas con cualquier tipo de diferencia promedio / típica estimada tuvieron lugar a discontinuidades.

  • No he podido encontrar una fórmula de trabajo que calcula la distancia sin mezclar colores RGBA con algunos fondos.

  • No hay necesidad de tomar cada posible color de fondo en cuenta. Se puede simplificarse hasta el máximo de mezcla y el mínimo por separado para cada uno de los canales R / G / B:

    1. mezclar el canal en ambos colores con canal = 0 como el fondo, medir la diferencia al cuadrado
    2. mezcla del canal en ambos colores con canal = máx como el fondo, medir la diferencia al cuadrado
    3. lleve más alto de los dos.

Afortunadamente mezcla con "blanco" y "negro" es trivial cuando se utiliza alfa premultiplicado (r = r×a).

La fórmula completa es:

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

C Fuente incluyendo SSE2 aplicación .

Otros consejos

Several principles:

  1. When two colors have same alpha, rgbaDistance = rgbDistance * ( alpha / 255). Compatible with RGB color distance algorithm when both alpha are 255.
  2. All Colors with very low alpha are similar.
  3. The rgbaDistance between two colors with same RGB is linearly dependent on 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);
}

My idea is integrating once over all possible background colors and averaging the square error.

i.e. for each component calculate(using red channel as example here)

Integral from 0 to 1 ((r1*a1+rB*(1-a1))-(r2*a2+rB*(1-a2)))^2*drB

which if I calculated correctly evaluates to:

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

And then sum these over R, G and B.

First of all, a very interesting problem :)
I don't have a full solution (at least not yet), but there are 2 obvious extreme cases we should consider:
When Δa==0 the problem is similiar to RGB space
When Δa==1 the problem is only on the alpha 1-dim space
So the formula (which is very similar to the one you stated) that would satisfy that is:
(Δr² + Δg² + Δb²) × (1-(1-Δa)²) + Δa² or (Δr² + Δg² + Δb²) × (1-Δa²) + Δa²

In any case, it would probably be something like (Δr² + Δg² + Δb²) × f(Δa) + Δa²

If I were you, I would try to simulate it with various RGBA pairs and various background colors to find the best f(Δa) function. Not very mathematic, but will give you a close enough answer

I've never done it, but theory and practice say that converting the RGB values in the image and the palette to luminance–chrominance will help you find the best matches. I'd leave the alpha channel alone, as transparency should have little to nothing to do with the 'looking better' part.

This xmass I made some photomosaics for presents using open-source software that matches fragments of the original image to a collection of images. That seems like a harder problem than the one you're trying to solve. One of them programs was metapixel.

Lastly, the best option should be to use an existing library to convert the image to a format, like PNG, in which you can control the palette.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top