实现SLIC算法生成像素画
前言
像素风最早出现在8bit的电子游戏中,受制于电脑内存大小以及显示色彩单一, 只能使用少量像素来呈现内容,却成就了不少经典的像素游戏。随着内存容量与屏幕分辨率的提升,内存与显示媒介的限制不再是问题,而像素风也慢慢演变成一种独特的创作风格。
像素画的一般的绘制流程包括了勾线、填色等,而逐个像素的绘制需要大量时间。一些流行的艺术方式,比如线描与绘画领域,都逐渐出现了自动化或半自动化生成的方法。本文将从零开始实现SLIC
[1]算法,并实现一款生成像素画工具。
什么是SLIC算法
像素画的绘制之所以不简单,是因为直接的下采样并不能准确的捕获关键像素,且容易导致丢失边缘信息,生成的像素画往往不尽人意。手工的勾线、填色,都是为了选取合适的像素点。由此,我们的问题变成了如何选取合适的像素点进行填色。
首先,引入一个概念——超像素。超像素是 2003 年 Xiaofeng Ren 提出和发展起来的图像分割技术,是指具有相似纹理、颜色、亮度等特征的相邻像素构成的有一定视觉意义的不规则像素块[1]。
通过将图片分割为超像素,可以得到相似的像素簇,相似的像素使用同一个颜色进行填充,得到的像素画会更合理。
超像素点分割的方法包括了提取轮廓、聚类、梯度上升等多种。论文[1]
提出的SLIC
超像素点分割算法(简单线性迭代聚类,simple linear iterative clustering
)就是其中一种,它基于K-means
聚类算法,根据像素的颜色和距离特征进行聚类来实现良好的分割结果,与若干种超像素点分割算法相比,SLIC
具有简单灵活、效果好、处理速度快等优势。
如何实现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]
。距离公式即变成了
当
m
越大,颜色空间除以m
后的值越小,即空间距离的权重越大,生成的像素会更为形状规则,当m
越小,颜色距离权重更大,超像素会在边缘更为紧凑,而形状大小较为不规则。像素点分类。
标记每个像素点的类别为距离其最小的聚类中心的类别。
重新计算聚类中心。
计算属于同一个聚类的所有像素点的平均向量值,重新得到聚类中心 。
迭代
4~6
的过程。直到旧聚类中心与新聚类中心的距离小于一定阈值或者达到一定迭代次数,一般来说,当迭代次数到达
10
,算法能够达到收敛。聚类优化。
迭代到最后,可能会出现与聚类中心不属于同一连通域的孤立像素点,可以使用到连通算法将其分配到最近的聚类标签。
论文中并未给出具体的实现算法。而本文的应用场景是生成像素画,会对像素进行下取样,并不会细化到每个像素,由此,本文不做聚类优化处理。
小小总结一下,SLIC算法流程大体与K-means
是一致的,不断迭代计算距离最小的聚类簇,不同的是只对聚类中心的S
距离内像素点进行计算,减少了不少的计算量。
生成像素画
基于SLIC
算法,我们已经可以把一张图划分为N
个超像素点。每个超像素中像素都是相近的。也就是说,每个像素都被归类为一个超像素,有一个聚类中心。那么将像素的颜色赋值为其聚类中心的颜色即得到我们想要的效果。
设定一定步长stride
,使用Canvas
,每隔stride
个像素,将像素赋值为其聚类中心的颜色,即得到最终的像素化结果。
而每个人对于像素画的主观感受是不一致的,为了让用户有更多的选择,得到自己满意的结果。可以暴露更多的人工干预参数,比如取消聚类优化的终止条件,改为由用户来设置迭代次数,以及最终取像素值的步长。人工设定的参数包括了
- 超像素点大小
blocksize
;blocksize
越小,超像素点分割越细腻。 - 迭代次数
iters
;iters
越大,分割结果更精准,计算时间越长。 - 颜色空间权重
weight
;weight
越大,颜色对于分割结果的影响越大。 - 取像素点步长
stride
;stride
越小,生成的像素图越接近超像素点,也就越细腻。
实现用户交互界面
作为一个工具,自然需要用户交互界面,前端界面基于HTML/Javascript/CSS
搭建,使用Canvas API
绘制图像内容,而用户交互面板选择的是dat.gui
[3] 库。dat.gui
是一个轻量级的图像化界面库,非常适用于参数的修改,常用作可视化 Demo 的演示。支持的参数类型包括了Number
、String
、Boolean
、自定义函数等。可以为不同的属性绑定相应的响应事件,当属性值改变时自动触发事件。
为生成像素化工具添加以下属性与事件:
- 当
iters、stride、blockSize、weight
(颜色空间权重m)参数变化时重新进行SLIC
算法的计算,并重新绘制计算结果; - 添加
Upload image
与Export 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),不定时推送文章:
实现SLIC算法生成像素画相关推荐
- Python使用图片作为像素生成像素画
具体见代码. #!python3 # -*- coding: utf-8 -*-import os import math from PIL import Imageclass ProcessBar( ...
- 最简单的SLIC算法实现
超像素由一系列位置相邻且颜色.亮度.纹理等特征相似的像素点组成的小区域.这些小区域大多保留了进一步进行图像分割的有效信息,且一般不会破坏图像中物体的边界信息,用少量的超像素代替大量像素表达图像特征,降 ...
- 多线程加速 Excel 画像素画
提高效率 一张图片的分辨率,小点的有 50x50=2500 个像素,大的则有 1920*1080=2073600 个像素. 而且 Python 操作 Excel,逐个的给 Excel 单元格上色,还是 ...
- 超像素SLIC算法源码阅读
超像素SLIC算法源码阅读 超像素SLIC算法源码阅读 SLIC简介 源码阅读 实验结果 其他超像素算法对比 超像素SLIC算法源码阅读 SLIC简介 SLIC的全称Simple Linear Ite ...
- 超像素(slic算法)特征提取(颜色,纹理)——个人梳理
一.研究背景 在上一篇slic超像素分割的文章中,提到了需要对分割后的超像素进行特征提取,依旧为简化复现论文,论文在文末附上,在这里我整理以下特征提取过程中的代码以及心得,方便后期回溯复盘.本文的特征 ...
- julia 调用python库_Julia调用Python实现超像素分割SLIC算法
最近想要在julia中实现 Simple Linear Iterative Clustering (SLIC) 算法对图像进行超像素分割,关于SLIC超像素分割算法,请参考SLIC Superpixe ...
- python 生成excel像素画_【译】只用 CSS 就能做到的像素画/像素动画
只用 CSS 就能做到的像素画/像素动画 这篇文章将会介绍只用 CSS 就能制作像素画·像素动画的方法.虽说纯 CSS 就能做到,但是为了更高的可维护性,也会顺便介绍使用 Sass 的制作方法. 上面 ...
- python 读取图片颜色值生成excel像素画
像素画: 需要用到的包: 进度条:progressbar pip install progressbar -i http://mirrors.aliyun.com/pypi/simple/ --tru ...
- 超像素分割(Slic算法)——个人梳理
一.使用背景 我在进行乳腺癌图像识别的学校项目中,参考了山东大学的硕士论文,并希望加以简化复现,此论文会在文末附上.项目要求我们需要对乳腺癌图片进行分类(无肿瘤,良性肿瘤,恶性肿瘤),参照论文所说,我 ...
最新文章
- 智能车竞赛技术报告 | 智能车视觉 - 中原工学院 - 逐鹿 - 分母队
- org 07c00h的原因
- SAP ABAP实用技巧介绍系列之Debug XSLT transformation
- 1千条数据平均分配给15人_5项数据挂零!但5犯太吓人!CBA第1狠人场均干1人
- 164. Maximum Gap
- 前端学习(3101):vue+element今日头条管理-react简介2
- python selenium 下载文件_Python Selenium —— 文件上传、下载,其实很简单
- mysql cascade|restrict|no action|set null__mysql 外键的几种约束
- java实现创建窗口
- paip.提升用户体验----置顶菜单
- 计算机软件C盘移到D盘怎么移,c盘的软件怎样转到d盘_如何将软件从c盘移出转到d盘-win7之家...
- bzoj1597: [Usaco2008 Mar]土地购买
- win10电脑任务栏软件图标变成白色解决办法
- javaWeb的线下服装店管理平台、基于ssm(springboot版本也有)+mysql线下服装销售系统
- 123457123457#0#-----com.cym.YuErBaiKe02--前拼后广--育儿百科
- python设置背景颜色为豆绿色_eclipse 设置豆沙绿保护色,保护眼睛
- C#如何在list中添加序号
- maven 中配置多个mirror的问题
- 个人博客园样式、背景及细节美化过程
- MIMIC-III:MIMIC_Extract代码实例数据预处理