在Ruby中构建基于颜色的图像搜索引擎

本文概述

  • 颜色空间
  • 红宝石宝石的颜色
  • 制作图像搜索引擎
  • 下一步是什么?
据说一张图片值一千字。在许多方面, 图片中的文字都是颜色。颜色是我们生活中不可或缺的一部分, 我们不能否认它们的重要性。
在查看图像时, 我们经常尝试识别图像的一部分颜色。我们都尝试过这样做, 但从未详细介绍。当要求你从图像中识别颜色时, 我们倾向于使用特定的颜色名称来标记它们, 例如红色, 蓝色和绿色。但是, 如果要求我们提取图像中30种最突出的颜色, 我们的眼睛将无法轻易检测或识别它们。 Camalian就是这样。它可以帮助你从图像中提取颜色, 然后进行处理。
在Ruby中构建基于颜色的图像搜索引擎

文章图片
在本文中, 我们将窥视所有色彩空间的含义, Camalian所提供的Ruby gem, 以及如何将其用于制作使用颜色识别和区分颜色的简单图像搜索引擎。
颜色空间 在开始之前, 我们先了解一些有关颜色的基本概念。屏幕上显示的图像是使用二维像素阵列表示的。尽管可以用不同的方式对图像文件进行编码, 但是对数据进行解压缩和解码后的粗略表示形式是相同的。在基于2d阵列的表示中, 彩色图像中的每个像素都具有三个分量:红色, 绿色和蓝色。尽管打印在纸上的图片也是点的二维表面, 但点本身通常是四种成分墨水的组合:青色, 品红色, 黄色和黑色。除了其他一些不同的技术外, 这些用于表示颜色的技术也称为颜色空间。一些最常用的颜色空间是RGB, CMYK, HSL和HSV。 CMYK主要用于印刷行业, 而其他所有则用于数字媒体。
RGB色彩空间
诸如CRT屏幕, LCD或电话之类的任何物理电子媒体都可以通过以下三种颜色来产生颜色:红色, 绿色, 蓝色。人眼可以通过刺激眼睛中的三种颜色受体来检测数百万种颜色。你可以将这些受体与R, G和B相关联。
理想情况下, 每个颜色分量都存储在一个字节中, 其值的范围可以在0到255之间。
HSL和HSV色彩空间
在多维数据集上安排RGB颜色空间非常具有挑战性。尝试在多维数据集和/或色轮上表示它的结果很差。在处理百万种颜色时, 每种颜色都无法在RGB颜色空间上正确对齐。
在Ruby中构建基于颜色的图像搜索引擎

文章图片
为了克服这个问题, 在1970年代, 研究人员引入了HSV(色相, 饱和度, 值)和HSL(色相, 饱和度, 亮度)色彩空间。这两个颜色空间都可以在色轮上正确对齐, 从而更容易识别其上的各种颜色。
红宝石宝石的颜色 Camalian就是关于颜色的。使用Camalian可以做的最简单的事情之一就是识别图像中使用的每种颜色。
假设我们有一幅具有15种不同颜色的图像。
在Ruby中构建基于颜色的图像搜索引擎

文章图片
从样本中识别颜色肯定比从图像本身识别颜色容易。此外, 这是一张简单的图像, 当涉及到调色板时, 所拍摄的真实照片通常要多样化得多。从图像中提取颜色值需要一些非常棘手的代码, 这就是Camalian的用处。它为你完成了这些棘手的任务, 因此你可以轻松地从图像中提取颜色相关的信息。
入门
如果使用Camalian轻松提取颜色, 则安装起来更加容易。你可以通过执行以下命令来安装Ruby gem:
gem install camalian

要使用此gem, 你可以将其直接添加到Ruby脚本中:
require 'camalian'

提取颜色
要从图像中提取颜色, 我们首先需要将其加载到内存中, 并在图像对象上使用方法:
image = Camalian::load( File.join( File.dirname(__FILE__), 'colormap.png') ) colors = image.prominent_colors(15) puts colors.map(& :to_hex)

此代码段从脚本所在的目录中加载名为” colormap.png” 的图像, 并从中提取15种最突出的颜色。
要运行它, 请将文件另存为” color_test1.rb” , 然后通过ruby color_test1.rb在shell中运行它。它应产生类似于以下内容的输出:
["#318578", "#41b53f", "#2560a3", "#359169", "#2154b1", "#4dda15", "#1d48bf", "#1530dc", "#296d94", "#193dcd", "#3da94d", "#45c131", "#3da84e", "#2d7986", "#193cce"]

就是这么简单!我们刚刚提取了上图中使用的15种颜色。你能想象用循环代码或更糟糕地用眼睛尝试这样做吗?让我们将其整理一下。这次, 我们将尝试在具有更多详细信息的图像上使用Camalian:
在Ruby中构建基于颜色的图像搜索引擎

文章图片
通过在此映像上运行相同的脚本, 我们将获得以下内容:
["#210b03", "#723209", "#974d09", "#ae5d08", "#c77414", "#d77f15", "#ffea54", "#94651f", "#b66a15", "#c25f06", "#fdd94d", "#d39a39", "#efa540", "#fffffe", "#fff655"]

尝试可视化上面产生的颜色值数组, 可以得到如下结果:
在Ruby中构建基于颜色的图像搜索引擎

文章图片
调色板很好, 但是提取的颜色中没有特定的图案。让我们按相似度对颜色值进行排序, 看看是否有帮助。我们需要做的就是在实际将数组打印到控制台之前再调用一个函数:
colors = image.prominent_colors(15).sort_similar_colors

在Ruby中构建基于颜色的图像搜索引擎

文章图片
但是, 如果我们要提取相对较浅的颜色怎么办?可能是我们希望只有40%的深色, 或者换句话说, (在HSL颜色空间中)明度的值介于0到40之间。我们要做的就是:
colors = image.prominent_colors(15).light_colors(0, 40)

在Ruby中构建基于颜色的图像搜索引擎

文章图片
制作图像搜索引擎 现在我们已经知道使用Camalian处理颜色非常容易, 让我们构建一个简单的网络应用程序, 使你可以上传图像并按颜色将它们编入索引。为简便起见, 我们将跳过构建Ruby应用程序所涉及的各种细节。相反, 我们将专注于处理颜色和Camalian使用情况的细节。
至于此Ruby应用程序的范围, 我们将其限制为处理图像上载, 在存储图像之前从图像中提取颜色以及根据选择的颜色和阈值搜索上载的图像。
下面是解释我们应用程序结构的模型图:
在Ruby中构建基于颜色的图像搜索引擎

文章图片
上载的每个图像都使用PortfolioItem对象表示。每个Color对象表示通过上传的图像发现的唯一颜色, 最后PortfolioColor表示每个图像与其中找到的颜色之间的关系。
该应用程序的大多数部分都是非常标准的, 尤其是在处理图像上载, 创建模型实体并将其持久保存到数据库等方面。如果你是Ruby开发人员, 那么这些工作就很简单了。以下是用于从上传的图像中提取颜色的方法:
after_save :extract_colorsprivate 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

这有助于提取调色板并将其保存到数据库。请注意, 我们是如何仅提取特定数量的突出颜色(用户在上传图像时可以定义的颜色)。
当用户通过Web UI上的表单提交图像时, 该图像将通过发布处理程序接收, 并为其创建新的PortfolioItem。每当投资组合项目保留到数据库时, 都会调用此方法extract_colors。
为了能够在页面上呈现调色板, 我们使用一个简单的帮助器:
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

本质上, 它会创建一个具有小方形跨度的div, 每个跨度的背景色都设置为提取的突出颜色之一。
最后, 要实现搜索, 我们必须使用一些数学和逻辑:
class PortfolioSearchForm include ActiveModel::Model attr_accessor :color, :similarity validates_presence_of :color, :similaritydef color_object @color_object ||= Camalian::Color.new(self.color) enddef color_range(color, level) (color_object.send(color) - level)..(color_object.send(color) + level) enddef 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)) enddef 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

使用colors_by_hsl方法, 我们可以获取所有与查询匹配的Color实体。并且, 借助这些, 我们可以识别所有上传的图像并呈现我们的搜索结果页面。查询本身非常简单。给定特定的颜色和相似度值, 将为每个颜色分量计算一个值范围。
这几乎是所有困难的部分。
尝试一下
你可以在GitHub上找到完整的代码。你可以将此应用程序的实例部署到Heroku, 或在本地尝试:
git clone https://github.com/nazarhussain/camalian-sample-app.git cd camalian-sample-app bundle install rake db:migrate rails s

最终的应用程序如下所示:
在Ruby中构建基于颜色的图像搜索引擎

文章图片
应用程序运行后, 将你的Web浏览器指向http:// localhost:3000。使用屏幕上的表格, 上传一些不同调色板的图像。然后, 要按颜色搜索图像, 请使用右上角的搜索字段。阈值下拉列表允许你指定相异度公差以匹配图像的颜色。
下一步是什么? 我们在本文中构建的演示应用程序非常简单, 但是可能性无穷!该库的其他一些实际用途可以包括:
  • 限制用户上传深色个人资料图片
  • 使网站的颜色主题适应用户上传的某些图片
  • 对于设计竞赛, 请根据调色板要求自动验证提交的内容
【在Ruby中构建基于颜色的图像搜索引擎】你可以在GitHub上进一步探索该库, 并查看其源代码。可以通过创建问题来报告错误, 也可以通过发送拉取请求进行贡献。

    推荐阅读