2010-01-11 9 views
9

Deseo desarrollar una herramienta básica como la de featured here. Tomaré capturas de pantalla de varias páginas web y de allí deseo tomar los primeros cinco colores más populares y de allí decidir de alguna manera si los colores son una buena combinación.Obtención de un esquema de color a partir de una imagen

Quiero escribir esta herramienta en C# y después de un poco de investigación descubrí ceros. Mi primera idea fue tomar una imagen y luego obtener el color de cada píxel, pero no estoy seguro de si esto me dará los resultados que deseo y cómo hacer seis listas de los colores más populares.

¿Puede alguien aquí dar consejos sobre cómo crearía un programa para hacer algo similar al programa anterior, que tomará una imagen y seleccionará los cinco primeros colores utilizados en la imagen?

+2

serhio hizo un excelente punto sobre el uso de una imagen en miniatura. De esta forma, el tiempo necesario para evaluar una imagen se mejoraría rápidamente. +1 – Finglas

Respuesta

16

Bueno .. utilizarla como imagen miniatura (16x16, 32x32, etc.) y seleccione de que los colores como

código actualizado:

private void button1_Click(object sender, EventArgs e) 
    { 
     int thumbSize = 32; 
     Dictionary<Color, int> colors = new Dictionary<Color, int>(); 

     Bitmap thumbBmp = 
      new Bitmap(pictureBox1.BackgroundImage.GetThumbnailImage(
       thumbSize, thumbSize, ThumbnailCallback, IntPtr.Zero)); 

     //just for test 
     pictureBox2.Image = thumbBmp;    

     for (int i = 0; i < thumbSize; i++) 
     { 
      for (int j = 0; j < thumbSize; j++) 
      { 
       Color col = thumbBmp.GetPixel(i, j); 
       if (colors.ContainsKey(col)) 
        colors[col]++; 
       else 
        colors.Add(col, 1); 
      }     
     } 

     List<KeyValuePair<Color, int>> keyValueList = 
      new List<KeyValuePair<Color, int>>(colors); 

     keyValueList.Sort(
      delegate(KeyValuePair<Color, int> firstPair, 
      KeyValuePair<Color, int> nextPair) 
      { 
       return nextPair.Value.CompareTo(firstPair.Value); 
      }); 

     string top10Colors = ""; 
     for (int i = 0; i < 10; i++) 
     { 
      top10Colors += string.Format("\n {0}. {1} > {2}", 
       i, keyValueList[i].Key.ToString(), keyValueList[i].Value); 
      flowLayoutPanel1.Controls[i].BackColor = keyValueList[i].Key; 
     } 
     MessageBox.Show("Top 10 Colors: " + top10Colors); 
    } 

    public bool ThumbnailCallback() { return false; } 

alt text http://lh3.ggpht.com/_1TPOP7DzY1E/S0uZ6GGD4oI/AAAAAAAAC5k/3Psp1cOCELY/s800/colors.png

+1

No consideré usar una miniatura, cosas buenas. – Finglas

+2

¡Eso es genio! Nunca hubiera pensado en hacer eso. Todavía no puedo probar el código porque mi computadora portátil está rota pero aceptaré la respuesta de cualquier forma. ¡Muchas gracias! –

+0

Ummm, ¿el blog en el que se alojó la imagen se bajó? La imagen ya no parece existir. Si aún lo tiene, debería considerar cargarlo con el botón de imagen en el editor. –

2

La forma más fácil, como usted ha dicho es:

  • Leer en cada píxel y almacenarlos en una colección .

  • Los primeros cinco colores utilizados serían los valores que ocurren más.

Así es como lo habría hecho al principio intentando algo como esto.

Para realizar este trabajo, puede tomar los rangos de color, por lo que al usar RGB valores (Red, Green, Blue) asigne un color a una determinada aproximación de color.

Por ejemplo, supongamos que la misma imagen se usó, los valores de color azul claro se almacenan juntos, luego se podría tomar una media de estos para dar el azul claro más común (aunque promedio) en la escena.

Repita para los otros píxeles.

En cuanto a la escala, el sitio web de ejemplo utiliza valores aburridos/brillantes. Se podría usar un valor de escala simple. Considere un rojo medio en RGB:

0.7, 0.0, 0.0 

Puede escalar esto agregando/multiplicando un valor. Sin embargo, mantenga los valores dentro del límite de 0 a 1. En cuanto a lo que debería ser el valor de escala, experimant. Cuanto más alto sea, más opaco/brillante será el color.

+0

Debo agregar, que cuando se usan imágenes en formato bmp, leer en un solo píxel y procesarlo es bastante sencillo, por lo que conviene poder generar un prototipo usando algunas de las sugerencias que se obtienen en este. – Finglas

+0

@Dockers, la plataforma es C# /. NET. Debido a esto, todos los archivos comunes tienen una única API, GetPixel/SetPixel con X/Y. – Dykam

+0

GetPixel/SetPixel es lento. Prefiero solo recorrer el conjunto de datos de respaldo. – Nyerguds

2

This es una ejemplo de cómo crear un histograma (o una tabla de frecuencias en otras palabras) donde puede echar un vistazo a los detalles sobre cómo procesar el i mago

Pero mi principal recomendación es no utilizar RGB (a menos que el sitio web que está buscando tenga colores casi planos), pero use HSB en su lugar. El componente "H" (tono) le dará una mejor indicación de los colores utilizados, sin importar qué tan brillantes u oscuros sean.

+0

muestras de código o enlaces para obtener valores HSB? –

+0

el marco proporciona el .GetHue(), .GetSaturation() y .GetBrightness() para cualquier objeto Color determinado. Hay una publicación muy buena por aquí explicando con detalles: http://stackoverflow.com/questions/2942/hsl-in-net –

Cuestiones relacionadas