像素风最早出现在8bit的电子游戏中,受制于电脑内存大小以及显示色彩单一, 只能使用少量像素来呈现内容,却成就了不少经典的像素游戏。随着内存容量与屏幕分辨率的提升,内存与显示媒介的限制不再是问题,而像素风也慢慢演变成一种独特的创作风格。
像素画的一般的绘制流程包括了勾线、填色等,而逐个像素的绘制需要大量时间。一些流行的艺术方式,比如线描与绘画领域,都逐渐出现了自动化或半自动化生成的方法。本文将从零开始实现SLIC[1]算法,并实现一款生成像素画工具。
什么是SLIC算法像素画的绘制之所以不简单,是因为直接的下采样并不能准确的捕获关键像素,且容易导致丢失边缘信息,生成的像素画往往不尽人意。手工的勾线、填色,都是为了选取合适的像素点。由此,我们的问题变成了如何选取合适的像素点进行填色。
首先,引入一个概念——超像素。超像素是 2003 年 Xiaofeng Ren 提出和发展起来的图像分割技术,是指具有相似纹理、颜色、亮度等特征的相邻像素构成的有一定视觉意义的不规则像素块[1]。
通过将图片分割为超像素,可以得到相似的像素簇,相似的像素使用同一个颜色进行填充,得到的像素画会更合理。
超像素点分割的方法包括了提取轮廓、聚类、梯度上升等多种。论文[1]提出的SLIC超像素点分割算法(简单线性迭代聚类,simple linear iterative clustering)就是其中一种,它基于K-means聚类算法,根据像素的颜色和距离特征进行聚类来实现良好的分割结果,与若干种超像素点分割算法相比,SLIC具有简单灵活、效果好、处理速度快等优势。
SLIC的基本流程如下:
图像预处理。
将图像从RGB颜色空间转换到CIE-Lab颜色空间,Lab颜色空间更符合人类对颜色的视觉感知。这个空间里的距离能反映人感觉到的颜色差别,相关计算更为准确。
Lab颜色空间同样具有三个通道,分别是l,a,b,其中l代表亮度,数值范围为[0,100],a表示从绿色到红色的分量,数值范围为[-128,127],b表示蓝色到黄色的分量,数值范围为[-128,127]。
RGB和LAB之间没有直接的转换公式,需要将RGB转为XYZ颜色空间再转为LAB,代码见文末完整代码。
初始化聚类中心。
根据参数确定超像素的数目,也就是需要划分为多少个区域。假设图片有N个像素点,预计分割为K个超像素,每个超像素大小为N/K,相邻中心距离为S=Sqr(N/K),得到K个聚类坐标。
优化初始聚类中心。在聚类中心的3*3邻域内选择梯度最小的像素点作为新的聚类中心。
把图像看成二维离散函数,梯度也就是这个函数的求导,当相邻像素值有变化就会存在梯度,而在边缘上的像素点的梯度最大。将聚类中心挪到梯度最小的地方可以避免其落到边缘轮廓上,影响聚类效果。
离散梯度的梯度计算这里不做详细推导了,由于其中包含了若干*方与开方,计算量较大,一般会简化为用绝对值来*似*方和*方根的操作。简化后的计算坐标为(i,j)的像素点的梯度公式为:
其中(i+1,j)与(i,j+1)为像素右侧点与像素下方点的坐标。l(a,b)为(a,b)坐标上像素的亮度通道值l。
计算像素点与聚类中心的距离。
在聚类中心距离S的区域内 2S*2S的邻域内计算像素点与每个聚类中心的距离。
这里的距离使用的是欧式距离,总距离D由dc颜色距离与ds空间距离两部分组成。公式如下:
如果直接将l,a,b,x,y拼接成一个矢量计算距离,当超像素的大小变化时,x,y的值可以取到非常大 ,比如如果一张图1000*1000,空间距离可以达到1000*Sqr(2),而颜色距离最大仅10*Sqr(2),导致最终计算得到的距离值中,空间距离ds权重占比过大。
所以需要进行归一化,除以最大值即超像素点的初始宽度S,将值映射到[0,1]。
而颜色空间距离也会给到一个固定的值m来调节颜色距离与空间距离的影响权重,m取值范围为[1,40]。
距离公式即变成了