实现SLIC算法生成像素画

前言

像素风最早出现在8bit的电子游戏中,受制于电脑内存大小以及显示色彩单一, 只能使用少量像素来呈现内容,却成就了不少经典的像素游戏。随着内存容量与屏幕分辨率的提升,内存与显示媒介的限制不再是问题,而像素风也慢慢演变成一种独特的创作风格。

像素画的一般的绘制流程包括了勾线、填色等,而逐个像素的绘制需要大量时间。一些流行的艺术方式,比如线描与绘画领域,都逐渐出现了自动化或半自动化生成的方法。本文将从零开始实现SLIC[1]算法,并实现一款生成像素画工具。

什么是SLIC算法

像素画的绘制之所以不简单,是因为直接的下采样并不能准确的捕获关键像素,且容易导致丢失边缘信息,生成的像素画往往不尽人意。手工的勾线、填色,都是为了选取合适的像素点。由此,我们的问题变成了如何选取合适的像素点进行填色。

首先,引入一个概念——超像素。超像素是 2003 年 Xiaofeng Ren 提出和发展起来的图像分割技术,是指具有相似纹理、颜色、亮度等特征的相邻像素构成的有一定视觉意义的不规则像素块[1]。

通过将图片分割为超像素,可以得到相似的像素簇,相似的像素使用同一个颜色进行填充,得到的像素画会更合理。

超像素点分割的方法包括了提取轮廓、聚类、梯度上升等多种。论文[1]提出的SLIC超像素点分割算法(简单线性迭代聚类,simple linear iterative clustering)就是其中一种,它基于K-means聚类算法,根据像素的颜色和距离特征进行聚类来实现良好的分割结果,与若干种超像素点分割算法相比,SLIC具有简单灵活、效果好、处理速度快等优势。 SLIC

如何实现SLIC算法

SLIC的基本流程如下:

  1. 图像预处理。

    将图像从RGB颜色空间转换到CIE-Lab颜色空间,Lab颜色空间更符合人类对颜色的视觉感知。这个空间里的距离能反映人感觉到的颜色差别,相关计算更为准确。

    Lab颜色空间同样具有三个通道,分别是lab,其中l代表亮度,数值范围为[0,100]a表示从绿色到红色的分量,数值范围为[-128,127]b表示蓝色到黄色的分量,数值范围为[-128,127]

    RGBLAB之间没有直接的转换公式,需要将RGB转为XYZ颜色空间再转为LAB,代码见文末完整代码。

  2. 初始化聚类中心。

    根据参数确定超像素的数目,也就是需要划分为多少个区域。假设图片有N个像素点,预计分割为K个超像素,每个超像素大小为N/K,相邻中心距离为S=Sqr(N/K),得到K个聚类坐标。

  3. 优化初始聚类中心。在聚类中心的3*3邻域内选择梯度最小的像素点作为新的聚类中心。

    把图像看成二维离散函数,梯度也就是这个函数的求导,当相邻像素值有变化就会存在梯度,而在边缘上的像素点的梯度最大。将聚类中心挪到梯度最小的地方可以避免其落到边缘轮廓上,影响聚类效果。

    离散梯度的梯度计算这里不做详细推导了,由于其中包含了若干平方与开方,计算量较大,一般会简化为用绝对值来近似平方和平方根的操作。简化后的计算坐标为(i,j)的像素点的梯度公式为:

    其中(i+1,j)(i,j+1)为像素右侧点与像素下方点的坐标。l(a,b)(a,b)坐标上像素的亮度通道值l

  4. 计算像素点与聚类中心的距离。

    在聚类中心距离S的区域内 2S*2S的邻域内计算像素点与每个聚类中心的距离。

    这里的距离使用的是欧式距离,总距离Ddc颜色距离与ds空间距离两部分组成。公式如下:

    如果直接将labxy拼接成一个矢量计算距离,当超像素的大小变化时,xy的值可以取到非常大 ,比如如果一张图1000*1000,空间距离可以达到1000*Sqr(2),而颜色距离最大仅10*Sqr(2),导致最终计算得到的距离值中,空间距离ds权重占比过大。

    所以需要进行归一化,除以最大值即超像素点的初始宽度S,将值映射到[0,1]

    而颜色空间距离也会给到一个固定的值m来调节颜色距离与空间距离的影响权重,m取值范围为[1,40]

    距离公式即变成了

    205.png

    m越大,颜色空间除以m后的值越小,即空间距离的权重越大,生成的像素会更为形状规则,当m越小,颜色距离权重更大,超像素会在边缘更为紧凑,而形状大小较为不规则。

  5. 像素点分类。

    标记每个像素点的类别为距离其最小的聚类中心的类别。

  6. 重新计算聚类中心。

    计算属于同一个聚类的所有像素点的平均向量值,重新得到聚类中心 。

  7. 迭代4~6的过程。

    直到旧聚类中心与新聚类中心的距离小于一定阈值或者达到一定迭代次数,一般来说,当迭代次数到达10,算法能够达到收敛。

  8. 聚类优化。

    迭代到最后,可能会出现与聚类中心不属于同一连通域的孤立像素点,可以使用到连通算法将其分配到最近的聚类标签。

    论文中并未给出具体的实现算法。而本文的应用场景是生成像素画,会对像素进行下取样,并不会细化到每个像素,由此,本文不做聚类优化处理。

小小总结一下,SLIC算法流程大体与K-means是一致的,不断迭代计算距离最小的聚类簇,不同的是只对聚类中心的S距离内像素点进行计算,减少了不少的计算量。

生成像素画

基于SLIC算法,我们已经可以把一张图划分为N个超像素点。每个超像素中像素都是相近的。也就是说,每个像素都被归类为一个超像素,有一个聚类中心。那么将像素的颜色赋值为其聚类中心的颜色即得到我们想要的效果。

设定一定步长stride,使用Canvas,每隔stride个像素,将像素赋值为其聚类中心的颜色,即得到最终的像素化结果。

而每个人对于像素画的主观感受是不一致的,为了让用户有更多的选择,得到自己满意的结果。可以暴露更多的人工干预参数,比如取消聚类优化的终止条件,改为由用户来设置迭代次数,以及最终取像素值的步长。人工设定的参数包括了

  • 超像素点大小blocksizeblocksize越小,超像素点分割越细腻。
  • 迭代次数itersiters越大,分割结果更精准,计算时间越长。
  • 颜色空间权重weightweight越大,颜色对于分割结果的影响越大。
  • 取像素点步长stridestride越小,生成的像素图越接近超像素点,也就越细腻。

实现用户交互界面

作为一个工具,自然需要用户交互界面,前端界面基于HTML/Javascript/CSS搭建,使用Canvas API绘制图像内容,而用户交互面板选择的是dat.gui [3] 库。dat.gui是一个轻量级的图像化界面库,非常适用于参数的修改,常用作可视化 Demo 的演示。支持的参数类型包括了NumberStringBoolean、自定义函数等。可以为不同的属性绑定相应的响应事件,当属性值改变时自动触发事件。

为生成像素化工具添加以下属性与事件:

  • iters、stride、blockSize、weight(颜色空间权重m)参数变化时重新进行SLIC算法的计算,并重新绘制计算结果;
  • 添加Upload imageExport image按钮,支持用户上传图片与下载像素化后的图片;

在绘制图像的Canvas画布层上叠加一层Canvas画布,对算法的结果进行可视化,添加以下功能

  • grid开关控制是否绘制像素网格;
  • Centers开关控制是否显示聚类中心;
  • Contours开关控制是否显示聚类边缘轮廓;

其中聚类中心点Centers的绘制直接使用ctx.fillRect 传入中心点坐标即可。

超像素轮廓Contours的绘制则需要先计算得到轮廓点。

可以对每个像素点与周围的8个像素点进行比较,如果聚类中心不同的像素点个数大于2,则代表着这个像素点周围有两个以上不同类别的点,则这个点为轮廓。效果如下:

最后,就得到一个简单的生成像素画工具了。

体验地址

完整版代码地址(JS版)

参考文献

[1] Achanta R, Shaji A, Smith K, Lucchi A, Fua P, Su ̈sstrunk S. SLIC superpixels. Technical Report. IVRG CVLAB; 2010.

[2] Gerstner T , Decarlo D , Alexa M , et al. Pixelated image abstraction with integrated user constraints[J]. Computers & graphics, 2013.

[3] https://github.com/dataarts/dat.gui

欢迎关注凹凸实验室博客:aotu.io

或者关注凹凸实验室公众号(AOTULabs),不定时推送文章:

欢迎关注凹凸实验室公众号

### 回答1: 在MATLAB中,Slic算法是一种图像超像素分割算法,具有良好的性能和效果。Slic算法将图像分割为一组紧密相连的区域,以减少图像中的冗余信息并提取出重要的结构特征。 Slic算法的优势在于其计算速度快、结果准确。该算法首先根据用户定义的超像素数量或尺寸将图像分成均匀的网格,然后在每个网格单元中选择代表像素。这些代表像素包含了图像的颜色、梯度、纹理等特征信息。 接下来,使用K均值聚类算法对这些代表像素进行聚类,以得到最终的超像素分割结果。聚类过程中,Slic算法考虑了像素之间的距离以及它们在特征空间中的相似性,以保证分割结果的准确性和连续性。 对于高分辨率的图像,Slic算法能够很好地处理,并能够保持图像细节的完整性。此外,在目标跟踪、图像分割和计算机视觉等领域中,Slic算法也被广泛应用。 总之,Slic算法是一种在MATLAB中实现的高效的超像素分割算法,具有快速的计算速度和准确的分割结果。它能够在图像处理和计算机视觉领域中提供相对较好的性能,有助于提取图像的结构特征和降低冗余信息的影响。 ### 回答2: Slice算法是一种基于图像分割原理的算法,特别适用于处理医学图像中的结构分割问题。它在MATLAB中有广泛的应用,可以用于对医学图像中的不同结构进行分割,如肿瘤、血管等。Slice算法的高分主要体现在以下几个方面。 首先,Slice算法能够准确地对医学图像中的结构进行分割。它采用了基于统计学的方法,通过对图像的直方图进行建模,找到图像中不同结构的灰度分布特征。然后,根据不同结构的灰度分布特征,结合阈值分割方法,将图像中的各个结构进行分割。因此,Slice算法得到的分割结果准确可靠。 其次,Slice算法在处理大规模医学图像时具有较高的效率。医学图像通常具有高分辨率和大尺寸的特点,对于传统的分割算法来说,处理时间较长。而Slice算法利用了图像直方图的特性,将灰度分布划分为多个区域,从而实现了对大规模图像的快速分割。这样可以在保证分割准确性的前提下,大幅度节省计算时间。 最后,MATLAB提供了丰富的图像处理函数和工具箱,可以很方便地实现Slice算法。MATLAB提供了图像处理工具箱,其中包含了各种图像分割的函数和算法。通过调用这些函数和算法,可以快速地实现Slice算法,并进行分割结果的可视化。此外,MATLAB还提供了图像预处理、后处理等功能,可以对分割结果进行进一步的优化和处理。 综上所述,Slice算法在MATLAB中能够高效地实现医学图像分割,具有准确性高、处理效率高和实现方便等优点。它是一种非常优秀的图像分割算法,被广泛应用于医学图像处理领域。 ### 回答3: 在MATLAB中,slic算法是一种用于图像分割的有效方法,它结合了超像素的概念和K-means聚类算法slic算法的主要思想是将图像分割为一组连续的区域,这些区域称为超像素。为了实现这一点,slic算法使用了K-means聚类算法,将像素点聚类到具有相似颜色和空间位置的簇中。 slic算法的步骤如下: 1. 初始化超像素数量和每个像素的初始位置,通常是像素均匀分布在整个图像上。 2. 使用像素的颜色和空间位置信息计算与每个超像素的中心最接近的像素,并将像素分配给相应的超像素。 3. 在像素分配过程中,计算超像素的中心位置,并将中心位置移动到超像素的平均位置。 4. 重复第2步和第3步,直到超像素的中心位置不再变化为止。 5. 最后,根据每个超像素周围的边界信息进行后处理,以平滑超像素边缘。 通过使用slic算法,可以获得具有更高分辨率的图像分割结果,因为超像素具有相对较大的尺寸。这样的结果对于许多图像处理任务,如目标检测、图像分析和图像重建等都非常有用。 在MATLAB中,可以使用内置的函数"superpixels"来实现slic算法。此函数提供了一些参数,如超像素的数量、超像素的紧凑度等,可以根据实际需求进行调整。 总之,slic算法是一种在MATLAB中实现图像分割的高分算法,能够生成具有更高分辨率和更准确边界的超像素。通过使用该算法,可以在许多图像处理任务中获得更好的结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值