2011-03-02 14 views
13

Necesito saber el color medio de una imagen cuando subo a mi Ruby on Rails aplicación. ¿Es posible obtener el valor de color promedio en HEX o en RGB para usar este color más adelante en la vista que va a mostrar esta imagen?¿Es posible obtener el color de imagen promedio con RMagick?

Algo así como:

img = Magick::Image.read(path).first 
hexVal = img.getHexValue 
+0

Como le pregunté en su [pregunta relacionada usando JavaScript] (http://stackoverflow.com/questions/ 5162828/how-to-get-the-average-or-main-color-from-an-image-with-javascript): "¿Desea solamente el color exacto del píxel o dentro de un rango de HSV en particular? Sugiera que este último le servirá mejor.) " – Phrogz

Respuesta

19

creo que no se puede pedir una imagen RMagick por su color medio directamente, sino calculando tal cosa no es tan difícil.

Creo que la manera más fácil sería para extraer el color histogram y luego utilizar eso para calcular el promedio. Usted probablemente querrá quantize la imagen primero sin embargo, calcular el histograma de una imagen con una gran cantidad de colores no es trabajo ocupado barato y probablemente inútil si sólo está interesado en un promedio:

total = 0 
avg = { :r => 0.0, :g => 0.0, :b => 0.0 } 
img.quantize.color_histogram.each { |c, n| 
    avg[:r] += n * c.red 
    avg[:g] += n * c.green 
    avg[:b] += n * c.blue 
    total += n 
} 
[:r, :g, :b].each { |comp| avg[comp] /= total } 

Eso ll darle el color promedio en avg. Sin embargo, el color será en formato interno de ImageMagick (es decir, los componentes van desde cero a Magick::QuantumRange) por lo que tendrá que escalar hacia abajo a 0-255:

[:r, :g, :b].each { |comp| avg[comp] = (avg[comp]/Magick::QuantumRange * 255).to_i } 

Y, finalmente, tener los componentes RGB en avg como enteros entre cero y 255 y obtener el color promedio en formato hexadecimal debe ser trivial. Podría combinar fácilmente esto en el paso de promediado si así lo desea.

probablemente podría ser más inteligente con los iteradores, pero .each es agradable y claro y la claridad es más importante que la inteligencia.

También puede probar con y sin la etapa de cuantificación y usar en cada uno funciona mejor para las imágenes que se está trabajando.

+7

@zarazan: Ese blog está fechado el 5 de julio de 2011, mi respuesta fue publicada el 2 de marzo de 2011. –

+1

@muistooshort Si todo lo que hace la función de cuantización es hacer una imagen menos compleja tomando promedios de colores de píxeles (asumiendo), no sería más simple si solo cuantizas la imagen a color como: – sfkaos

+0

@sfkaos: supongo que la parte que falta de tu comentario es sobre cuantificar la imagen a un color. Eso podría funcionar y supongo que tendría el mismo efecto que el enfoque [stef's] (http://stackoverflow.com/a/5164917/479863) de "reducirlo a un píxel". Aunque no estoy seguro de lo que los algoritmos subyacentes harían con la paleta, me gustaría realizar algunas pruebas para ver qué sucede con las imágenes reales. Buena idea, sin embargo. –

21

redimensionar la imagen de un píxel y que sea de color?

img = Magick::Image.read(path).first 
pix = img.scale(1, 1) 
averageColor = pix.pixel_color(0,0) 
+1

Una prueba (muy) rápida demostró que esto es mucho más rápido que usar 'color_histogram'. – joost

+1

¡Solución realmente inteligente! +1 – bodacious

+0

Obtenemos un objeto "Magick :: Pixel", pero si queremos el rgb en formato hexadecimal "como css usa (por ejemplo, # f0a1b2)" ¿cómo podemos hacerlo? Lo responde tingel2k debajo de – Aleksandrus

1

Según @muistooshort - Si toda la función de cuantización no es hacer una imagen de menor complejidad mediante la adopción de las medias de colores de los píxeles (suponiendo) - no sería aún más simple si sólo la imagen cuantificados a color como:

img.quantize(1,Magick::RGBColorspace).color_histogram 

Y sólo tiene que utilizar el color resultante?

3

He encontrado mi solución (here), después de probar todas las posibilidades que se presentan aquí.

def maincolor() 
    img = Magick::Image.read(self.url).first 
    pix = img.scale(1, 1) 
    avg_color_hex = pix.to_color(pix.pixel_color(0,0)) 
    return avg_color_hex 
end 

Espero que esto ayude. Agregué la conversión al color hexadecimal por rmagick, porque es una pita con rubí (de lo contrario utilicé la conversión de sprintf a hex)

+0

Desafortunadamente, este método a veces devuelve colores hexadecimales no válidos. Ejemplo: "# AAC5C3F1". –

+0

¿Estás seguro, tu foto tiene la profundidad de color adecuada? – tingel2k

+0

Hum ... No estoy seguro. ¿Cómo puedo saber eso? ¿O cómo puedo convertir la imagen? –

Cuestiones relacionadas