Creación de un motor de búsqueda de imágenes basado en colores en Ruby

Publicado: 2022-03-11

Se dice que una imagen vale más que mil palabras. Y en muchos sentidos, las palabras en las imágenes son colores. Los colores son una parte integral de nuestra vida, y no podemos negar su importancia.

Al mirar una imagen, a menudo hemos tratado de identificar el color en una parte de ella. Todos hemos intentado hacerlo pero nunca lo hicimos en detalle. Cuando se nos pide que identifiquemos los colores de una imagen, tendemos a etiquetarlos usando nombres de colores específicos, como rojo, azul y verde. Sin embargo, si se nos pide que extraigamos los 30 colores más destacados de una imagen, nuestro ojo no podrá detectarlos ni identificarlos con la misma facilidad. Camalian se trata de esto. Te ayuda a extraer colores de las imágenes y luego jugar con ellos.

Camalian: Selector de color definitivo para Ruby

En este artículo, veremos de qué se tratan los espacios de color, qué tiene para ofrecer la gema Ruby Camalian y cómo se puede usar para crear un motor de búsqueda de imágenes simple que use colores para identificarlos y distinguirlos.

Espacio de colores

Antes de comenzar, primero comprendamos algunos conceptos básicos sobre los colores. Las imágenes presentadas en nuestras pantallas se representan utilizando una matriz bidimensional de píxeles. Aunque los archivos de imágenes se pueden codificar de diferentes maneras, la representación cruda después de descomprimir y decodificar los datos es la misma. En esta representación basada en matrices 2D, cada píxel de una imagen en color tiene tres componentes: rojo, verde y azul. Aunque las imágenes impresas en un papel también son una superficie bidimensional de puntos, los puntos mismos suelen ser una mezcla de tintas de cuatro componentes: cian, magenta, amarillo y negro. Estas, entre algunas otras técnicas diferentes, se utilizan para representar los colores y se denominan espacios de color. Algunos de los espacios de color más utilizados son RGB, CMYK, HSL y HSV. CMYK se usa principalmente en la industria de la impresión, mientras que todos los demás se usan en medios digitales.

Espacio de color RGB

Cualquier medio electrónico físico como pantallas CRT, LCD o teléfonos que transmiten luz produce color utilizando tres componentes: rojo, verde y azul. El ojo humano puede detectar millones de colores estimulando tres tipos de receptores de colores en el ojo. Puede relacionar esos receptores con R, G y B.

Idealmente, cada componente de color se almacena en un byte cuyos valores pueden oscilar entre 0 y 255.

Espacio de color HSL y HSV

Organizar el espacio de color RGB en un cubo es bastante complicado. Los resultados de tratar de representarlo en un cubo o rueda de colores son pobres. Mientras trabaja con millones o colores, cada matiz de color no se puede alinear correctamente en el espacio de color RGB.

motor de búsqueda de imágenes de rubí

Para superar este problema, en la década de 1970, los investigadores introdujeron los espacios de color HSV (Tono, Saturación, Valor) y HSL (Tono, Saturación, Luminosidad). Ambos espacios de color se pueden alinear correctamente en una rueda de colores y facilitan la identificación de varios tonos de color en ella.

Gema de rubí para colores

Camalian tiene que ver con los colores. Una de las cosas más sencillas que puede hacer con Camalian es identificar cada matiz de color utilizado en una imagen.

Digamos que tenemos una imagen con 15 colores distintos.

Sin duda, identificar los colores de la muestra es más fácil que identificarlos a partir de la imagen misma. Además, esta es una imagen simple, y las fotos reales capturadas suelen ser mucho más diversas en lo que respecta a su paleta de colores. Extraer los valores de color de la imagen requiere algunos bits de código bastante complicados, y ahí es donde entra Camalian. Hace estas cosas complicadas por usted para que pueda extraer información relacionada con el color de una imagen con facilidad.

Empezando

Si extraer colores con Camalian es fácil, instalar con él es aún más fácil. Puede instalar la gema Ruby ejecutando:

 gem install camalian

Y para usar esta gema, puede solicitarla directamente en su script de Ruby:

 require 'camalian'

Extracción de colores

Para extraer colores de una imagen, primero debemos cargarla en la memoria y usar métodos en el objeto de la imagen:

 image = Camalian::load( File.join( File.dirname(__FILE__), 'colormap.png') ) colors = image.prominent_colors(15) puts colors.map(&:to_hex)

Este fragmento de código carga una imagen llamada "colormap.png" del directorio donde reside el script y extrae los 15 colores más destacados.

Para ejecutarlo, guarde el archivo como "color_test1.rb" y ejecútelo en shell por ruby color_test1.rb . Debería producir una salida similar a la siguiente:

 ["#318578", "#41b53f", "#2560a3", "#359169", "#2154b1", "#4dda15", "#1d48bf", "#1530dc", "#296d94", "#193dcd", "#3da94d", "#45c131", "#3da84e", "#2d7986", "#193cce"]

¡Y es así de fácil! Acabamos de extraer 15 colores utilizados en la imagen de arriba. ¿Te imaginas intentar hacerlo usando un código loco, o peor, con tus ojos? Subamos las cosas un poco. Esta vez, intentaremos usar Camalian en una imagen con más detalles:

Al ejecutar el mismo script en esta imagen, obtenemos lo siguiente:

 [“#210b03”, “#723209”, “#974d09”, “#ae5d08”, “#c77414”, “#d77f15”, “#ffea54”, “#94651f”, “#b66a15”, “#c25f06”, “#fdd94d”, “#d39a39”, “#efa540”, “#fffffe”, “#fff655”]

Intentar visualizar la matriz de valores de color producidos anteriormente nos da algo como esto:

La paleta es buena, pero no hay patrón específico en los colores extraídos. Ordenemos los valores de color por similitud y veamos si eso ayuda. Todo lo que tenemos que hacer es llamar a una función más antes de imprimir la matriz en la consola:

 colors = image.prominent_colors(15).sort_similar_colors 

Pero, ¿y si quisiéramos extraer colores que son relativamente más claros? Puede ser que queramos colores que sean solo un 40 % oscuros o, en otras palabras, que tengan un valor de luminosidad (en el espacio de color HSL) entre 0 y 40. Todo lo que tenemos que hacer es:

 colors = image.prominent_colors(15).light_colors(0, 40) 

Hacer el motor de búsqueda de imágenes

Ahora que sabemos lo fácil que es manejar los colores usando Camalian, construyamos una aplicación web simple que le permita cargar imágenes y tenerlas indexadas por color. Para abreviar, omitiremos los diversos detalles involucrados en la construcción de una aplicación Ruby. En su lugar, nos centraremos en los detalles relacionados con los colores y el uso de Camalian.

En cuanto al alcance de esta aplicación de Ruby, la limitaremos a manejar cargas de imágenes, extraer colores de la imagen antes de almacenarlos y buscar la imagen cargada según el color y el umbral elegidos.

A continuación se muestra un diagrama modelo para explicar la estructura de nuestra aplicación:

Cada imagen cargada se representa mediante un objeto PortfolioItem. Cada objeto Color representa colores únicos descubiertos a través de imágenes cargadas y, finalmente, PortfolioColor representa la relación entre cada imagen y los colores que se encuentran en ella.

La mayoría de las partes de la aplicación son bastante estándar, especialmente cuando se trata de manejar la carga de imágenes, crear entidades de modelo y conservarlas en la base de datos, etc. En caso de que sea un desarrollador de Ruby, eso debería ser obvio. A continuación se muestra el método que se utiliza para extraer el color de la imagen cargada:

 after_save :extract_colors private def extract_colors image = Camalian::load(self.image.path) colors = image.prominent_colors(self.color_count.to_i).sort_similar_colors colors.each do |color| unless c = Color.where(r: color.r, g: color.g, b: color.b).first c = Color.create(r: color.r, g: color.g, b: color.b, h: color.h, s: color.s, l: color.l) end self.colors << c end end

Esto ayuda al extraer la paleta de colores y guardarla en la base de datos. Observe cómo extraemos solo un número específico de colores destacados (algo que el usuario puede definir al cargar la imagen).

Cuando un usuario envía una imagen a través del formulario en la interfaz de usuario web, la imagen se recibe a través de un controlador de publicación y se crea un nuevo PortfolioItem para ella. Este método, extract_colors , se invoca cada vez que un elemento de la cartera se conserva en la base de datos.

Para poder representar la paleta de colores en las páginas, usamos un ayudante simple:

 module PortfolioItemsHelper def print_color_palette(colors) color_string = '' colors.each do |c| color_string += content_tag :span, ' ', style: "display: block; float: left; width: 35px; height: 35px; background: #{c.to_hex}" end content_tag :div, color_string.html_safe, style: "display: inline-block;" end end

Básicamente, crea un div con pequeños tramos cuadrados, cada uno con su color de fondo establecido en uno de los colores destacados extraídos.

Finalmente, para implementar la búsqueda tenemos que usar algo de matemática y lógica:

 class PortfolioSearchForm include ActiveModel::Model attr_accessor :color, :similarity validates_presence_of :color, :similarity def color_object @color_object ||= Camalian::Color.new(self.color) end def color_range(color, level) (color_object.send(color) - level)..(color_object.send(color) + level) end def colors_by_rgb level = self.similarity.to_i * 255 / 100.0 Color.where(r: color_range(:r, level), g: color_range(:g, level), b: color_range(:b, level)) end def colors_by_hsl level = self.similarity.to_i Color.where(h: color_range(:h, (self.similarity.to_i * 30 / 100.0) ), s: color_range(:s, level), l: color_range(:l, level)) end end

Con el método colors_by_hsl , podemos obtener todas las entidades Color que coincidan con nuestra consulta. Y, con estos, podemos identificar todas las imágenes cargadas y mostrar nuestra página de resultados de búsqueda. La consulta en sí es bastante simple. Dado un color específico y un valor de similitud, se calcula un rango de valores para cada componente de color.

Y eso es prácticamente todas las partes difíciles.

probandolo

Puede encontrar el código completo en GitHub. Puede implementar una instancia de esta aplicación en Heroku o probarla localmente:

 git clone https://github.com/nazarhussain/camalian-sample-app.git cd camalian-sample-app bundle install rake db:migrate rails s

La aplicación final se parece a esto:

Una vez que la aplicación se esté ejecutando, apunte su navegador web a http://localhost:3000. Usando el formulario en pantalla, cargue algunas imágenes de diferentes paletas de colores. Luego, para buscar imágenes por color, use el campo de búsqueda en la esquina superior derecha. El menú desplegable de umbral le permite especificar la tolerancia de diferencia para hacer coincidir los colores de las imágenes.

¿Que sigue?

La aplicación de demostración que creamos en este artículo es bastante simple, ¡pero las posibilidades son infinitas! Algunos otros usos prácticos de esta biblioteca pueden incluir:

  • Restringir a los usuarios para que no carguen imágenes de perfil oscuras
  • Adapte el tema de color del sitio a alguna imagen cargada por el usuario
  • Para concursos de diseño, valide automáticamente las presentaciones contra los requisitos de la paleta de colores.

Puede explorar más a fondo la biblioteca en GitHub y consultar su código fuente. Siéntase libre de informar errores creando problemas o contribuir enviando solicitudes de extracción.