2009-12-04 9 views
18

Tengo un valor rgb y si no existe en la tabla de colores en mi base de datos necesito encontrar el color más cercano. Estaba pensando en comparar todos los valores y encontrar la diferencia (en rojo, verde y azul) y luego tomar el promedio. La desviación promedio más baja debe ser el color más cercano. Me parece que debería haber una mejor manera. ¿Algunas ideas?Dado un valor RGB, ¿cuál sería la mejor manera de encontrar la coincidencia más cercana en la base de datos?

+0

¿Cuál es la estructura de su mesa donde almacena los colores? – Ryan

+3

Aunque cada respuesta individual sugiere distancia euclidiana en el espacio RGB, ¡no lo haga! HSV es mucho más adecuado para modelar la distancia perceptual que RGB, por lo que debe convertir primero su espacio de color. –

Respuesta

52

Considera un color como vector en el espacio tridimensional, a continuación, puede calcular fácilmente la diferencia mediante el uso de Pitágoras 3d:

d = sqrt((r2-r1)^2 + (g2-g1)^2 + (b2-b1)^2) 

sin embargo, tenga en cuenta que debido a los colores que son objeto de interpretación por parte de los ojos no tan perfectas, es posible que desee ajustar los colores para evitar que tengan el mismo importancia.

Por ejemplo, el uso de a typical weighted approach:

d = sqrt(((r2-r1)*0.3)^2 + ((g2-g1)*0.59)^2 + ((b2-b1)*0.11)^2) 

Dado que los ojos son más sensibles al verde, y menos sensible al azul, dos colores que se diferencian sólo en el componente azul debe por lo tanto tienen una diferencia numérica grande para ser considerado "más diferente" que uno que es la misma diferencia numérica en el componente verde.

También hay varias formas de optimizar este cálculo. Por ejemplo, ya que no está realmente interesado en el valor real d, se puede prescindir de la raíz cuadrada:

d = ((r2-r1)*0.30)^2 
    + ((g2-g1)*0.59)^2 
    + ((b2-b1)*0.11)^2 

señalar aquí que en muchos lenguajes de programación basados ​​en C-sintaxis (como C#), ^ hace no significa "elevar al poder de", sino más bien "exclusivo binario o".

Así que si esto fuera C#, usaría Math.Pow para calcular esa parte, o simplemente expandir y hacer la multiplicación.

Agregado: A juzgar por la página en Color difference on Wikipedia, existen varias normas que tratan de manejar las diferencias de percepción. Por ejemplo, el llamado CIE94 usa una fórmula diferente, en el modelo de color L*C*h, que parece que vale la pena investigar, pero depende de qué tan preciso sea el resultado.

+0

Probablemente mucho mejor que mi idea ... – nfechner

+2

Una respuesta como esta siempre es una delicia para leer. –

+0

+1. Esto parece cercano a mí, excepto que el ojo también es más sensible al brillo que al color, por lo que una diferencia óptima también debe tener en cuenta el ángulo entre los vectores de color, así como su longitud y la distancia desde la punta hasta -propina. – RickNZ

0

Calcula tanto la media y la distancia así:

(r + g + b)/3 = average 
(r - average) + (g - average) + (b - average) = distance 

Esto debe darle una buena idea del valor más cercano.

3

A continuación se hace exactamente lo que usted describe:

select (abs(my_R - t.r) + abs(my_G - t.g) + abs(my_B - t.b))/3 as difference, t.* 
from RGBtable t 
order by difference desc; 

Sin embargo, es posible obtener mejores resultados con algo que no fue lineal. En el enfoque de "tomar promedios", si el color del objetivo es (25, 25, 25) el color (45, 25, 25) estaría más cerca que (35, 35, 35). Sin embargo, apuesto a que el segundo realmente se miraría más cerca, ya que también sería gris.

Algunas ideas vienen a la mente: podría tratar de cuadrar las diferencias antes de promediarlas. O podría hacer algo complicado al encontrar el color con la relación más cercana entre los diferentes valores. Encontrar las proporciones más cercanas te acercaría más al matiz correcto, pero no explicará la saturación (si recuerdo bien los términos ...)

1

Al mirar the Wikipedia page on Color difference, la idea es tratar los colores RGB como puntos en tres dimensiones. La diferencia entre los dos colores es la misma que la distancia entre dos puntos:

difference = sqrt((red1 - red2)^2 + (green1 - green2)^2 + (blue1 - blue2)^2) 
2

Vamos la base de datos lo haga por usted:

select top 1 
    c.r, 
    c.b, 
    c.g 
from 
    color c 
order by 
    (square(c.r - @r) + square(c.g - @g) + square(c.b - @b)) 

Dónde @r, @g y @b son el r, g, b valores del color que está buscando (sintaxis del parámetro SQL Server, ya que no especificó una base de datos). Tenga en cuenta que esto todavía tendrá que hacer un escaneo de tabla ya que el order by tiene una llamada de función en él.

Tenga en cuenta que la llamada de raíz cuadrada extra no es necesaria ya que es una función monótona. No es probable que sea demasiado importante, pero aún así.

+0

La base de datos no es una varita mágica. Hacer esto requerirá tanto trabajo como hacerlo usted mismo; solo está descargando el trabajo a la base de datos. –

+1

Bueno, dado que la información está casi en una base de datos, tiene más sentido para mí simplemente obtener las filas que necesita en lugar de buscarlas todas para calcular las distancias usted mismo. – Donnie

1

Un paso mejor que el promedio es cercano raíz cuadrada:

((delta red)^2 + (delta green)^2 + (delta blue)^2)^0.5 

Esto reduce al mínimo la distancia en el espacio de color 3D.

Dado que una raíz está aumentando estrictamente, puede buscar el máximo del cuadrado en su lugar. La forma de expresar esto en SQL dependería de qué RDBMS esté utilizando.

3

El Euclidean distancedifference = sqrt(sqr(red1 - red2) + sqr(green1 - green2) + sqr(blue1 - blue2)) es el standard way para determinar la similitud de dos colores.

Sin embargo, si tiene los colores en una lista simple, para encontrar el color más cercano es necesario calcular la distancia del nuevo color con cada color de la lista. Esta es una operación O (n).

La sqrt() es una operación costosa, y si solo está comparando dos distancias, simplemente puede omitir sqrt().

Si tiene una paleta de colores muy grande, es potencialmente más rápido organizar los colores en un kd tree (o uno de los alternatives) para reducir el número de diffreences que requieren computación.

Cuestiones relacionadas