超像素(SuperPixel),就是把原本多个像素点,组合成一个大的像素。比如,原本的图片有二十多万个像素,用超像素处理之后,就只有几千个像素了。后面做直方图等处理就会方便许多。经常作为图像处理的预处理步骤。

在超像素算法方面,SLIC Superpixels Compared to State-of-the-art Superpixel Methods这篇论文非常经典。论文中从算法效率,内存使用以及直观性比较了现有的几种超像素处理方法,并提出了一种更加实用,速度更快的算法——SLIC(simple linear iterative clustering),名字叫做简单的线性迭代聚类。其实是从k-means算法演化的,算法复杂度是O(n),只与图像的像素点数有关。

这个算法突破性的地方有二:

限制聚类时搜索的区域(2Sx2S),这样将k-means算法的复杂度降为常数。整个算法的复杂度为线性。

计算距离时考虑LAB颜色和XY距离,5维。这样就把颜色和距离都考虑进去了。通过M可以调整颜色和距离的比重,灵活性强,超像素更加规则。

SLIC算法原理

整个算法的输入只有一个,即超像素的个数K。

图片原有N个像素,要分割成K个像素,那么每个像素的大小是N/K。超像素之间的距离(即规则情况下超像素的边长)就是S=√N/K。

我们的目标是使代价函数(cost function)最小。具体到本算法中,就是每个像素到所属的中心点的距离之和最小。

首先,将K个超像素种子(也叫做聚类,即超像素的中心),均匀撒到图像的像素点上。

一次迭代的第一步,对每个超像素的中心,2S范围内的所有像素点,判断他们是否属于这个超像素。这样之后,就缩短了像素点到超像素中心的距离。

一次迭代的第二步,对每个超像素,将它的超像素中心移动到这个超像素的中点上。这样也缩短了像素点到超像素中心的距离。

一般来说,迭代10是聚类效果和计算成本折中的次数。

SLIC算法步骤

撒种子。将K个超像素中心分布到图像的像素点上。

微调种子的位置。以K为中心的3×3范围内,移动超像素中心到这9个点中梯度最小的点上。这样是为了避免超像素点落到噪点或者边界上。

初始化数据。取一个数组label保存每一个像素点属于哪个超像素。dis数组保存像素点到它属于的那个超像素中心的距离。

对每一个超像素中心x,它2S范围内的点:如果点到超像素中心x的距离(5维)小于这个点到它原来属于的超像素中心的距离,那么说明这个点属于超像素x。更新dis,更新label。

对每一个超像素中心,重新计算它的位置。

重复4 5 两步。

伪代码(来自论文)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

/∗Initialization∗/

InitializeclustercentersCk=[lk,ak,bk,xk,yk]TbysamplingpixelsatregulargridstepsS.

Moveclustercenterstothelowestgradientpositionina3×3neighborhood.

Setlabell(i)=−1foreachpixeli.Setdistanced(i)=∞foreachpixeli.

repeat

/∗Assignment∗/

foreachclustercenterCkdo

foreachpixeliina2S×2SregionaroundCkdo

ComputethedistanceDbetweenCkandi.

ifD

setd(i)=D

setl(i)=k

endif

endfor

endfor

/∗Update∗/

Computenewclustercenters.ComputeresidualerrorE.

untilE≤threshold

Python实现SLIC

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

importmath

fromskimageimportio,color

importnumpyasnp

fromtqdmimporttrange

classCluster(object):

cluster_index=1

def__init__(self,h,w,l=0,a=0,b=0):

self.update(h,w,l,a,b)

self.pixels=[]

self.no=self.cluster_index

self.cluster_index+=1

defupdate(self,h,w,l,a,b):

self.h=h

self.w=w

self.l=l

self.a=a

self.b=b

def__str__(self):

return"{},{}:{} {} {} ".format(self.h,self.w,self.l,self.a,self.b)

def__repr__(self):

returnself.__str__()

classSLICProcessor(object):

@staticmethod

defopen_image(path):

"""

Return:

3D array, row col [LAB]

"""

rgb=io.imread(path)

lab_arr=color.rgb2lab(rgb)

returnlab_arr

@staticmethod

defsave_lab_image(path,lab_arr):

"""

Convert the array to RBG, then save the image

"""

rgb_arr=color.lab2rgb(lab_arr)

io.imsave(path,rgb_arr)

defmake_cluster(self,h,w):

returnCluster(h,w,

self.data[h][w][0],

self.data[h][w][1],

self.data[h][w][2])

def__init__(self,filename,K,M):

self.K=K

self.M=M

self.data=self.open_image(filename)

self.image_height=self.data.shape[0]

self.image_width=self.data.shape[1]

self.N=self.image_height*self.image_width

self.S=int(math.sqrt(self.N/self.K))

self.clusters=[]

self.label={}

self.dis=np.full((self.image_height,self.image_width),np.inf)

definit_clusters(self):

h=self.S/2

w=self.S/2

whileh

whilew

self.clusters.append(self.make_cluster(h,w))

w+=self.S

w=self.S/2

h+=self.S

defget_gradient(self,h,w):

ifw+1>=self.image_width:

w=self.image_width-2

ifh+1>=self.image_height:

h=self.image_height-2

gradient=self.data[w+1][h+1][0]-self.data[w][h][0]+\

self.data[w+1][h+1][1]-self.data[w][h][1]+\

self.data[w+1][h+1][2]-self.data[w][h][2]

returngradient

defmove_clusters(self):

forclusterinself.clusters:

cluster_gradient=self.get_gradient(cluster.h,cluster.w)

fordhinrange(-1,2):

fordwinrange(-1,2):

_h=cluster.h+dh

_w=cluster.w+dw

new_gradient=self.get_gradient(_h,_w)

ifnew_gradient

cluster.update(_h,_w,self.data[_h][_w][0],self.data[_h][_w][1],self.data[_h][_w][2])

cluster_gradient=new_gradient

defassignment(self):

forclusterinself.clusters:

forhinrange(cluster.h-2*self.S,cluster.h+2*self.S):

ifh<0orh>=self.image_height:continue

forwinrange(cluster.w-2*self.S,cluster.w+2*self.S):

ifw<0orw>=self.image_width:continue

L,A,B=self.data[h][w]

Dc=math.sqrt(

math.pow(L-cluster.l,2)+

math.pow(A-cluster.a,2)+

math.pow(B-cluster.b,2))

Ds=math.sqrt(

math.pow(h-cluster.h,2)+

math.pow(w-cluster.w,2))

D=math.sqrt(math.pow(Dc/self.M,2)+math.pow(Ds/self.S,2))

ifD

if(h,w)notinself.label:

self.label[(h,w)]=cluster

cluster.pixels.append((h,w))

else:

self.label[(h,w)].pixels.remove((h,w))

self.label[(h,w)]=cluster

cluster.pixels.append((h,w))

self.dis[h][w]=D

defupdate_cluster(self):

forclusterinself.clusters:

sum_h=sum_w=number=0

forpincluster.pixels:

sum_h+=p[0]

sum_w+=p[1]

number+=1

_h=sum_h/number

_w=sum_w/number

cluster.update(_h,_w,self.data[_h][_w][0],self.data[_h][_w][1],self.data[_h][_w][2])

defsave_current_image(self,name):

image_arr=np.copy(self.data)

forclusterinself.clusters:

forpincluster.pixels:

image_arr[p[0]][p[1]][0]=cluster.l

image_arr[p[0]][p[1]][1]=cluster.a

image_arr[p[0]][p[1]][2]=cluster.b

image_arr[cluster.h][cluster.w][0]=0

image_arr[cluster.h][cluster.w][1]=0

image_arr[cluster.h][cluster.w][2]=0

self.save_lab_image(name,image_arr)

defiterate_10times(self):

self.init_clusters()

self.move_clusters()

foriintrange(10):

self.assignment()

self.update_cluster()

name='lenna_M{m}_K{k}_loop{loop}.png'.format(loop=i,m=self.M,k=self.K)

self.save_current_image(name)

if__name__=='__main__':

p=SLICProcessor('Lenna.png',500,30)

p.iterate_10times()

效果如下:

Lenna图像在M=30,K=500时第一次迭代产生的超像素图。

Lenna图像在M=30,K=500时第10次迭代产生的超像素图。

python图像分割算法_SLIC算法分割超像素原理及Python实现相关推荐

  1. opencv14-图像分割--超像素分割与形态学分割

    二值形态学在二值图像上进行运算,二值图像是从其他等级的强度通道产生的.为了进行图像分析,采用的方法是去除形状噪声或异常值以及加强主要特征点.形态学可用于目标识别.细胞生物学.医学.粒子分析和自动显微镜 ...

  2. python协同过滤算法_协同过滤(ALS)的原理及Python实现

    提到ALS相信大家应该都不会觉得陌生(不陌生你点进来干嘛[捂脸]),它是协同过滤的一种,并被集成到Spark的Mllib库中.本文就ALS的基本原理进行讲解,并手把手.肩并肩地带您实现这一算法. 完整 ...

  3. python云盘搭建教程_超简单!基于Python搭建个人“云盘”,目前最好用的个人云盘...

    超简单!基于Python搭建个人"云盘",目前最好用的个人云盘 1. 简介 当我们想要从本地向云服务器上传文件时,比较常用的有pscp等工具,但避免不了每次上传都要写若干重复的代码 ...

  4. Python教程分享,10款超好用的Python开发工具!

    学会Python技术后,我们在参加工作的时候如果能有辅助工具的话,那么会很大程度的提高我们的工作效率,那么Python都有哪些好用的开发工具呢?下面小编就为大家详细的介绍一下10款超好用的python ...

  5. python自制个人网盘_超简单!基于Python搭建个人“云盘”

    1 简介 当我们想要从本地向云服务器上传文件时,比较常用的有pscp等工具,但避免不了每次上传都要写若干重复的代码. 而笔者最近发现的一个基于Python的工具updog,可以帮助我们在服务器上搭建类 ...

  6. python excel 库 知乎_超全整理|Python 操作 Excel 库 xlwings 常用操作详解!

    来源:早起Python 作者:陈熹.刘早起 大家好,我是早起. 在之前的文章中我们曾详细的讲解了如何使用openpyxl 操作Excel,其实在Python中还有其他可以直接操作 Excel 文件的库 ...

  7. python读取txt文件并分割成列表_在python中读取文本文件并将其拆分为单个单词

    给定此文件:$ cat words.txt line1 word1 word2 line2 word3 word4 line3 word5 word6 如果一次只需要一个单词(忽略文件中空格和换行符的 ...

  8. python高斯滤波和降噪_高斯滤波原理及python实现

    高斯滤波器时一种线性平滑滤波器,主要适用处理高斯噪声,所以在了解高斯滤波之前,我们首先熟悉一下高斯噪声.噪声在图像中表现的通常是引起视觉效果的孤立像素点和像素块,简单说噪声点就是会给图像带来干扰,让图 ...

  9. julia 调用python库_Julia调用Python实现超像素分割SLIC算法

    最近想要在julia中实现 Simple Linear Iterative Clustering (SLIC) 算法对图像进行超像素分割,关于SLIC超像素分割算法,请参考SLIC Superpixe ...

  10. 超像素分割(Slic算法)——个人梳理

    一.使用背景 我在进行乳腺癌图像识别的学校项目中,参考了山东大学的硕士论文,并希望加以简化复现,此论文会在文末附上.项目要求我们需要对乳腺癌图片进行分类(无肿瘤,良性肿瘤,恶性肿瘤),参照论文所说,我 ...

最新文章

  1. a href=#与 a href=javascript:void(0) 的差别
  2. 【Ids4实战】深究配置——用户信息操作篇
  3. 20150504-日报
  4. python自动输入_使用Python和pywin32自动输入数据
  5. JavaScript的排序问题
  6. Android开源库
  7. XCODE GDB这个是老版本xcode,新版的是lldb
  8. 亲测可用|奥维互动地图加载谷歌地图等图源的方法
  9. python安装第三方库出现问题怎么办_关于Python第三方库安装失败问题的解决方案...
  10. 家庭必备,轻、快、好用的WIN10自带虚拟机
  11. C语言如何求球的体积和表面
  12. LeetCode-自除数
  13. springIOC原理解析
  14. [语录]足球解说员贺炜语录
  15. 怎么在线把图片转成PDF?几个步骤轻松转换
  16. 官方scratch3.0正式发布,全面支持移动设备在线编程!
  17. kali2022.1安装google chrome develop 专业版
  18. 什么是生产管理?制造企业想要做好生产管理应该怎么做?
  19. cell数据如何删除重复项
  20. 数据结构第一次上机实验报告

热门文章

  1. 世界各个地区WIFI 2.4G及5G信道一览表(附无线通信频率分配表)
  2. SpringBoot 静态资源版本管理
  3. 【学习中】王者荣耀游戏拆解分析(1)
  4. 8分钟教你学会局域网邮箱服务器搭建
  5. 基于matlab的gmsk,基于matlab的gmsk
  6. javascript 自定义对象的两种方法
  7. JAVA项目中枚举和字典表,枚举与字典表的选择
  8. 揭露北京车牌租赁公司的内幕
  9. 项目组最重要的三个角色
  10. 1.微信开放平台 和 微信公众平台 和 商户平台 的区别