Extracción de Colores de Imágenes en Python.

La extracción de colores de una imagen es una técnica fundamental en el procesamiento digital que permite identificar, cuantificar y analizar los tonos predominantes en una fotografía o en cualquier recurso gráfico. En un mundo cada vez más orientado al análisis visual —desde el diseño hasta la visión por computadora— comprender la paleta cromática de una imagen se ha vuelto una herramienta indispensable para múltiples disciplinas. Así, en nuestro artículo de esta semana, nos proponemos a realizar la extracción de los colores principales de la siguiente imagen:

En esta ocasión haremos uso de google colab, para nuestra practica, donde, como es natural, comenzaremos realizando las importaciones pertinentes:

Como se ve, realizamos la importación de varias librerías y recursos: ‘from PIL import Image‘ (Para cargar la imagen), ‘import numpy as np‘ (para manipular arrays y hacer reshape), ‘import matplotlib.pyplot as plt‘ (para mostrar la imagen y paleta resultante) y ‘from sklearn.cluster import KMeans‘ (que nos permitirá emplear el algoritmo K-Means de scikit-learn, para agrupa píxeles por similitud de color).

A continuación, pasaremos a abrir la imagen con image.open() y la convertimos inmediatamente a un array con np.array():

El resultado es un array de forma (ancho, alto, canales) (normalmente (w, h, 3) para RGB. Usar Pillow y convert(RGB) es recomendable si hay posibilidad de canal alfa; en ese caso conviene forzar Image.open(file_name).convert(«RGB») para garantizar 3 canales.

Tras ello, pasaremos a convertir nuestra imagen en una matriz de 2 dimensiones en donde cada fila es un pixel y cada columna viene representada por los canales (R. G . B.). De este modo, teniendo nuestra imagen 501 x 501 pixeles y 3 canales, el formato que pasaremos al algoritmo KMeans, será (251001, 3) que es el formato que espera para realizar la agrupación por colores.

El paso siguiente será el de seleccionar el número de colores dominantes que queremos extraer. Número que almacenaremos en la variable n_colors y que en nuestro caso será 15:

Por fin, en este paso se crea y entrena el modelo K-Means que identificará los colores dominantes de la imagen. Instanciando, primero, el algoritmo con KMeans(n_clusters=n_colors, random_state=42), donde n_clusters es el número de colores que queremos extraer (definidos antes) y random_state garantiza resultados reproducibles. Finalmente, con .fit(pixels), el modelo agrupa todos los píxeles de la imagen en clusters según la similitud de sus valores RGB; cada iteración ajusta los centroides para minimizar la distancia entre los píxeles y el centro del grupo al que pertenecen. Al finalizar, el modelo queda entrenado y listo para proporcionar los colores representativos de la imagen:

Una vez entrenado el modelo, K-Means almacena en kmeans.cluster_centers_ los centroides de cada grupo, que representan los colores dominantes encontrados en la imagen. Estos valores se obtienen como arreglos de tipo float, por lo que primero se convierten a enteros de 0 a 255 mediante np.uint8, generando así colores válidos en formato RGB. El resultado es un arreglo llamado palette, donde cada fila es un color característico detectado por el algoritmo. Esta paleta condensada es una representación compacta de los tonos predominantes de la imagen original y servirá para su visualización o para cualquier aplicación posterior, como diseño gráfico, clasificación o análisis cromático:

Obtenida nuestra paleta de colores principales, simplemente nos restará representarla con nuestra librería matplotlib, mediante el procedimiento habitual:

ORDENANDO COLORES POR IMPORTANCIA.

Como hemos dicho, tras todo el proceso hemos obtenido los 15 colores más representativos de nuestra imagen. No obstante, tal y como está presentado el resultado, quizás no nos diga gran cosa, al no estar estos ordenados ni contar con el porcentaje que cada uno representa en el conjunto. Por ello, vamos a añadir algunas líneas justo después de la definición de la paleta extraída (variable palette):

Aquí, partiendo del resultado antes obtenido por K-Means, cada píxel de la imagen recibe una etiqueta numérica que indica a qué cluster (o color) pertenece. Etiqueta, la cual, se almacena una a una en kmeans.labels_. Para saber qué colores aparecen más en la imagen, primero contamos cuántas veces aparece cada etiqueta usando np.unique(labels, return_counts=True), lo que devuelve los identificadores de los clusters y cuántos píxeles corresponden a cada uno. Luego, para convertir esas cantidades absolutas en proporciones, dividimos cada conteo entre el número total de píxeles (len(labels)) y lo multiplicamos por 100 para obtener el porcentaje que representa cada color sobre el total.

Una vez obtenidas las proporciones, podemos ordenar los colores según su presencia en la imagen. Para ello usamos np.argsort(-frequencies), que devuelve los índices que ordenarían el array de frecuencias de mayor a menor; el signo negativo se usa para invertir el orden, ya que argsort normalmente ordena de menor a mayor:

Así, al aplicar estos índices tanto al array de colores (palette) como al array de frecuencias, generamos una paleta reordenada (palette_sorted) donde el primer color es el más predominante y el último el menos frecuente. Esta ordenación es especialmente útil para representar la paleta de manera más intuitiva, ya que los colores principales aparecen primero.

Ahora ya lo único que deberemos hacer es volver a la parte del código que usamos para mostrar la paleta. Solo que usando en esta ocasión, la variable palette_sorted para la representación:

Finalmente, si lo deseamos, podemos mostrar el porcentaje de cada color (esta vez redondeado a dos decimales con .2f) valiéndonos de un ciclo for que recorra la paleta y frecuencias ordenadas:

Así, lo que esta salida nos está diciendo es que el 23,13% de los pixeles de la imagen tienen un color que vendría determinado por los valores RGB, 12 para el canal rojo, 4 para el verde y 11 para el azul y así con el resto de la salida.

CONCLUSIÓN:

En conjunto, calcular y ordenar las frecuencias de color permite obtener una paleta no solo representativa, sino también informativa sobre la estructura cromática de una imagen. Este proceso facilita identificar los tonos predominantes y comprender mejor la composición visual, lo que resulta especialmente útil en tareas de diseño, análisis estético, clasificación de imágenes y generación de estilos visuales coherentes.

Saludos.