Algoritmo para verificar la similitud de colores

Estoy buscando un algoritmo que compare dos colores RGB y genere un valor de similitud (donde similitud significa “similar con respecto a la percepción humana promedio”).

¿Algunas ideas?

EDITAR :

Como ya no puedo responder, decidí poner mi “solución” como una edición de la pregunta.

Decidí ir con un subconjunto (muy) pequeño de color verdadero en mi aplicación, para poder manejar la comparación de colores por mi cuenta. Trabajo con alrededor de 30 colores y uso distancias difíciles entre ellos.

Como era una aplicación de iPhone, trabajé con el objective C y la implementación es más o menos una matriz que representa la tabla siguiente, que muestra las distancias entre los colores.

enter image description here

La distancia RGB en el espacio euclidiano no es muy “similar a la percepción humana promedio”

Puede usar el espacio de color YUV , tiene en cuenta este factor:

enter image description here

También puede usar el espacio de color CIE para este propósito.

EDITAR:

Mencionaré que el espacio de color YUV es una aproximación económica que se puede calcular a través de fórmulas simples. Pero no es perceptualmente uniforme. Perceptualmente uniforme significa que un cambio de la misma cantidad en un valor de color debería producir un cambio de aproximadamente la misma importancia visual. Si necesita una métrica más precisa y rigurosa, debe considerar definitivamente el espacio de color CIELAB u otro espacio perceptualmente uniforme (incluso si no hay fórmulas simples para la conversión).

Recomendaría usar CIE94 (DeltaE-1994), se dice que es una representación decente de la percepción del color humano. Lo he usado bastante en mis aplicaciones relacionadas con la visión de la computadora, y estoy bastante contento con el resultado.

Sin embargo, es bastante costoso computacional realizar tal comparación:

  1. RGB to XYZ para ambos colores
  2. XYZ to LAB para ambos colores
  3. Diff = DeltaE94(LABColor1,LABColor2)

Fórmulas (pseudocódigo):

La percepción humana es más débil en croma que intensidad.

Por ejemplo, en video comercial, los espacios de color YCbCr / YPbPr (también llamados Y’UV) reducen la resolución de la información de croma pero conservan la luma (Y). En la compresión de video digital, como 4: 2: 0 y 4: 2: 2, reduce la tasa de bits de croma debido a una percepción relativamente más débil.

Creo que se puede calcular una función de distancia dando mayor prioridad sobre luma (Y) y menos prioridad sobre croma.

Además, en baja intensidad, la visión humana es prácticamente en blanco y negro. Por lo tanto, la función de prioridad no es lineal ya que para baja luma (Y) pones cada vez menos peso en croma.

Fórmulas más científicas: http://en.wikipedia.org/wiki/Color_difference

La percepción del color no es euclidiana. Cualquier fórmula de distancia será lo suficientemente buena y terrible al mismo tiempo. Cualquier medida basada en la distancia euclidiana (RGB, HSV, Luv, Lab, …) será lo suficientemente buena para colores similares, mostrando que el aqua está cerca de la cerceta. Pero para los valores no cercanos llega a ser arbitrario. Por ejemplo, ¿el rojo está más cerca del verde o del azul?

De las preguntas frecuentes sobre el color de Charles Poynton:

Los sistemas XYZ y RGB están lejos de exhibir uniformidad perceptiva. Encontrar una transformación de XYZ en un espacio razonablemente perceptualmente uniforme consumió una década o más en el CIE y, al final, no se pudo acordar ningún sistema único.

Hay una excelente redacción sobre el tema de las distancias de color aquí: http://www.compuphase.com/cmetric.htm

En caso de que ese recurso desaparezca, la conclusión del autor es que se puede lograr la mejor aproximación de bajo costo a la distancia entre dos colores RGB usando esta fórmula (en código).

 typedef struct { unsigned char r, g, b; } RGB; double ColourDistance(RGB e1, RGB e2) { long rmean = ( (long)e1.r + (long)e2.r ) / 2; long r = (long)e1.r - (long)e2.r; long g = (long)e1.g - (long)e2.g; long b = (long)e1.b - (long)e2.b; return sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8)); } 

La similitud de color en el cubo RGB se mide por la distancia euclidiana (use la fórmula de pythagoras).

EDITAR: Pensándolo bien, esto debería ser cierto para la mayoría de los otros espacios de color también.