背景
创意平台是一个拥有丰富素材、模板的多场景在线设计平台。
众所周知,颜色在设计中扮演着极为重要的角色,它不仅仅是美感的体现,还深刻影响用户的感知、情绪和行为。为了提升用户的检索效率,提高作品的最终视觉效果,我们需要支持颜色检索图片。
在最初版本中,我们通过人工识别的方式,将颜色作为标签与图片关联起来,显然,这与创意平台设计的初衷背道而驰,所以我们决定在系统层面上实现图片颜色识别及关联自动化。
目的
实现素材&模板的主色识别及关联自动化。换句话说,就是让用户在上传素材&模板之后,不经过人工处理,就能够通过颜色检索到对应的素材&模板。
实现方案
通过分析用户的使用场景,我们可以将流程细化成四步:用户上传素材&模板->服务器提取主色->服务器关联颜色与素材&模板->用户检索素材&模板,其中服务器需要做三件事,提取主色、颜色归类、颜色关联,那么接下来我们将对这三件事进行详细阐述。
1.主色提取
计算机是如何表达图像的?
在提取主色前,我们首先需要知道计算机是如何表达图像的。首先给出结论:计算机是通过像素和颜色信息来表达图像的。图像是由多个不可分割的单元组成的,这些单元被称为像素,每个像素代表图像中的一个点,像素都包含颜色信息、位置信息。像素的颜色信息通常使用RGB(红、绿、蓝)模型表示。
RGB颜色模型
在RGB模型中,颜色由红色、绿色和蓝色三个颜色通道的组合来表示。每个通道的强度可以在0到255之间变化,其中0表示没有该颜色,255表示该颜色的最大强度。例如,RGB(255, 0, 0) 表示红色,因为红通道的强度是255,而绿和蓝通道的强度为0。
主色提取算法
知道了图像在计算机中的表达方式后,那么自然而然的想法是,可以通过统计图像中像素个数排名靠前的颜色来得到主色,显然,这种提取方式在一些简单场景上(如:纯色图片)效果不错,但是在复杂场景(如:颜色渐变)上就不太合适了。
常见的主色提取算法有Kmeans算法、中位切分法、八叉树算法等,相较于其他语言,Java在图像处理方面有着明显的劣势,虽然有基础的图像处理API,但缺少强大的图像处理库,通过调研这三种算法的实现难度、实现效果后,我们更倾向于Kmean算法和中位切分法,幸运的是,我们在github上找到开源的颜色提取项目Color thief,它是基于中位切分法实现的。此开源项目的核心思想简述如下:
将图像的颜色集合视作色彩空间的长方体
在RBG中最长的一边,找到颜色中位数,将其一分为二,使两个长方体中的像素数量相等,重复此步骤直至长方体数量等于主题色数量
在引用开源项目后,我们成功提取出图片的主色,但是在实验过程中发现以下两个问题:
问题1:部分透明底的PNG图片会被识别成黑色
问题2:提取出的主色会受主色数量及采样率的影响
针对问题1:
经过对比分析,我们猜测是透明的像素点被识别成了黑色,为了验证这一猜想,我们调研了PNG图片的格式,PNG图片分为三通道PNG(RGB PNG)、四通道PNG(RGBA PNG),其中R G B A分别代表红色通道、绿色通道、蓝色通道、透明度通道,所以我们在获取像素点颜色这一步骤中过滤了全透明像素点,成功解决这一问题。
针对问题2:
我们都知道采样是一种近似方法,对图像进行采样可能导致信息丢失、颜色提取的精确度降低。另外,减少像素数量,可以提高计算效率,对于大尺寸的图像,可以显著减少处理时间、减少资源消耗。我们期望在尽可能还原图像最真实的颜色的基础上,降低对服务器的影响,在创意平台中,96.8%的图片大小处于5M以内,我们对于这类图片使用最高的采样标准,对于超过5M的图片,尽可能使用最高的采样标准,对于处理失败的图片,未来将采取压缩或者转格式的方式来降低图像文件大小。
主色提取数量的变化会影响提取的主色范围。最初,在参考常规的颜色提取网站后,我们选定了主色数量为4个,在大多数场景下效果不错,但在特殊场景下,肉眼感知的主色和图片识别的主色不一致。
我们第一反应:这张图片应包含橙色、灰色、黑色、棕色。
但提取出来的颜色是这样的:
为什么没有识别出橙色?我们知道,中位切分法是通过不断二分颜色直方体,使得直方体数量等于主色数量,最后得出主色,所以在二分的过程中可能导致颜色精度损失。因此我们的策略是尽可能提取多的颜色,但不可能全量提取,所以我们在原有4个主色的基础上,分别增加1、2、3个进行对比测试。
提取5个主色
提取6个主色
提取7个主色
测试结果显示,在把主色数量设置为5时,提取的主色基本就能覆盖所有主色,再增加提取的主色数量也不过是增加"重复"的棕色,因此选定主色提取数量为5个。
然而,这又引入一个新问题,当把主色提取数量设置为5个后,简单类型的图像主色包含占比很低的颜色。为了避免这一情况,就需要过滤占比较低的颜色,但是占比多少算低,没有一个准确的定论,只能通过不断调整主色在原图上的占比阈值来反复测试,最后,我们找到一个相对合适的占比范围。
2. 颜色归类
首先,我们回顾一下RGB颜色空间,以r g b为轴,建立空间坐标系,如下图所示。
可以看到,在RGB空间中,八个顶角分别代表了黑色、红色、绿色、蓝色、黄色、洋红色、青色、白色。显然,通过主色rgb值就确定主色属于什么颜色是一件非常困难的事情,原因有二,第一,rgb三个分量是高度相关的,即使在rgb分量上有些许的变化,也会导致颜色分类改变;第二,RBG颜色空间是面向机器的,颜色均匀性很差,无法通过空间点之间的关系进行分类;所以我们不能使用RGB颜色空间。
为了将主色进行颜色归类,我们需要更合适的颜色模型。通过调研,常见的颜色模型有CMYK、LAB、HSV。
常见的颜色模型
CMYK颜色模型
CMYK颜色模型是一种用于印刷和出版的颜色模型,它表示颜色通过四个颜色通道:青(Cyan)、洋红(Magenta)、黄(Yellow)和黑(Key,通常表示黑色)。这四个颜色通道可以组合产生多种颜色。
LAB颜色模型
LAB颜色空间是一种颜色空间,也称为CIE Lab*颜色空间,由国际照明委员会(CIE)定义。它是一种基于人眼感知的颜色空间,与设备无关,用于更准确地描述和测量颜色,更适用于颜色编辑
L(亮度)
表示颜色的明亮程度
取值范围:0(黑)到100(白)
a(从绿到红)
表示颜色在红绿轴上的位置
取值范围:-128(绿)到127(红)
b(从蓝到黄)
表示颜色在蓝黄轴上的位置
取值范围:-128(蓝)到127(黄)
LAB颜色空间如下所示:
HSV颜色模型
HSV颜色模型是一种描述颜色的方式,其中颜色由三个属性组成:色调(Hue)、饱和度(Saturation)和明度(Value)。HSV模型相对于RGB模型更加直观,更符合人类对颜色的感知。
色调(Hue)
表示颜色的种类或类型
取值范围:[0,360],单位:度
饱和度(Saturation)
表示颜色的强度
饱和度为0表示灰度,颜色越饱和,其颜色越纯净
取值范围:[0,100%]
明度(Value)
表示颜色的亮度
明度为0表示黑色,明度为最大值时颜色最亮。
取值范围:[0,100%]
HSV颜色空间如下所示:
按照角度划分出颜色范围如下所示:
通过对比这三种颜色模型,我们最终选择了HSV颜色模型。原因有二,第一,HSV颜色空间只需要通过一个变量就能控制颜色的线性变化,而LAB颜色空间需要两个;第二,HSV颜色空间更加容易确定颜色空间范围。
如何归类
通过观察HSV颜色空间,颜色归类可以抽象成在局部三维空间中找到指定的点,在这个局部颜色空间中,所有的像素点均被归类成同一个颜色。我们需要做两件事,第一,将主色转换成空间中的点;第二,确定颜色在HSV颜色空间的范围
我们将rgb映射成hsv,构建成三维空间坐标系。rgb转hsv公式如下,由于java中Color工具类中已实现rgb转hsv,因此不需要再重复实现。
其中 max 等于 r, g, b 中的最大者
其中 min 等于 r, g, b 中的最小者
为了方便计算,hsv的取值范围分别映射成[0-180] [0-255] [0-255],如下图所示:
参考网上资料给出的颜色取值表,我们经过了一系列的主色转换测试,发现部分颜色的分类不能够满足需求,所以,在原有取值表的基础上,耗费了大量时间进行调整范围测试,最终找到一个相对合适的取值范围。原hsv颜色取值表如下所示:
3.颜色检索实现及效果展示
在确定主色所在的颜色分类空间范围后,我们有两种实现思路:
第一种方案,存储素材&模板的主色hsv值,使用给定范围空间作为入参去检索素材&模板,也就是在空间里找点。创意平台目前是使用ElasticSearch和MySQL对素材&模板进行存储和检索的,虽然两者都支持了空间检索,但是仅支持二维空间检索。如果要使用其他的空间检索工具,成本会非常高,因为需要保证数据一致性。
第二种方案,存储素材&模板的主色hsv对应的颜色分类,即"色卡",效果等同于颜色标签,再通过"色卡"进行检索。实现简单,数据一致性也可通过内部自研的数据同步工具保证。
经过多方面考量,最终,我们选择了第二种实现方案,通过ElasticSearch实现存储与检索,效果不错。我们支持了PNG、SVG、JPEG、JPG、GIF、PPT、PPTX类型文件的主色提取及关联自动化,自动识别成功率达到99%。
"色卡"紫色检索图片素材的效果如下所示:
在设计团队视角上,资源中心展示的素材&模板均由设计师设置并展示,如果要使用颜色筛选功能则需要设计师人工识别颜色并打标。现在,由系统自动化处理,可节省时间成本20~30s/次(至少节省原人工处理流程时间的70%)。另外,资源中心内展示的图片素材&模板存量约为9000,通过系统处理可节省时间50~75h;周均上传图片素材&模板约100,周均节省时间33~50min;
在业务团队视角上,图片主色识别&关联自动化功能上线前,日均检索总次数为95,上线后,日均检索总次数为122(提升约27%),其中使用"色卡"检索的次数为18(占比约15%),由此可见,颜色检索素材&模板功能是很重要的。
总结及展望
在颜色检索2.0版本中,我们将颜色检索图片抽象成在三维空间中寻找点,首先使用中位切分法提取图像的主色,然后构建主色的hsv空间坐标系,在空间坐标系中划分各颜色空间领域,最后通过将主色归类到各颜色所在空间,实现颜色关联图像,从而达成颜色检索图片的目的。
颜色检索只是CBIR(Content-Based Image Retrieval)领域的冰山一角,而我们在功能上使用到的技术更是微不足道的一粒冰粒,在图像特征的其他方向如纹理、形状上,我们还有许多的路要走。
参考资料
1.https://github.com/sergeyk/rayleigh
2.https://github.com/SvenWoltmann/color-thief-java
3.https://immortalqx.github.io/2020/08/17/opencv-notes-2/
4.https://blog.csdn.net/xxboy61/article/details/88356005
5.https://www.mathworks.com/help/images/understanding-color-6.spaces-and-color-space-conversion.html
7.https://blog.csdn.net/qq_42475234/article/details/122746811
8.https://blog.csdn.net/lly_3485390095/article/details/104570885
END