图像分割python代码_SILC超像素分割算法详解(附Python代码)
SILC算法詳解
一、原理介紹
SLIC算法是simple linear iterative cluster的簡稱,該算法用來生成超像素(superpixel)
算法步驟:
已知一副圖像大小M*N,可以從RGB空間轉(zhuǎn)換為LAB空間,LAB顏色空間表現(xiàn)的顏色更全面
假如預(yù)定義參數(shù)K,K為預(yù)生成的超像素數(shù)量,即預(yù)計將M*N大小的圖像(像素數(shù)目即為M*N)分隔為K個超像素塊,每個超像素塊范圍大小包含[(M*N)/K]個像素
假設(shè)每個超像素區(qū)域長和寬都均勻分布的話,那么每個超像素塊的長和寬均可定義為S,S=sqrt(M*N/K)
遍歷操作,將每個像素塊的中心點的坐標(biāo)(x,y)及其lab的值保存起來,加入到事先定義好的集合中
每個像素塊的中心點默認(rèn)是(S/2,S/2)進(jìn)行獲取的,有可能落在噪音點或者像素邊緣(所謂像素邊緣,即指像素突變處,比如從黑色過渡到白色的交界處),這里,利用差分方式進(jìn)行梯度計算,調(diào)整中心點:
算法中,使用中心點的8領(lǐng)域像素點,計算獲得最小梯度值的像素點,并將其作為新的中心點,差分計算梯度的公式:
Gradient(x,y)=dx(i,j) + dy(i,j);
dx(i,j) = I(i+1,j) - I(i,j);
dy(i,j) = I(i,j+1) - I(i,j);
遍歷現(xiàn)中心點的8領(lǐng)域像素點,將其中計算得到最小Gradient值的像素點作為新的中心點
調(diào)整完中心點后即需要進(jìn)行像素點的聚類操作
通過聚類的方式迭代計算新的聚類中心;
首先,需要借助K-means聚類算法,將像素點進(jìn)行歸類,通過變換的歐氏聚距離公式進(jìn)行,公式如下(同時參考像素值和坐標(biāo)值提取相似度):
通過兩個參數(shù)m和S來協(xié)調(diào)兩種距離的比例分配。參數(shù)S即是上面第③步計算得出的每個像素塊的長度值,而參數(shù)M為LAB空間的距離可能最大值,其可取的范圍建議為[1,40]
為了節(jié)省時間,只遍歷每個超像素塊中心點周邊的2S*2S區(qū)域內(nèi)的像素點,計算該區(qū)域內(nèi)每個像素點距離哪一個超像素塊的中心點最近,并將其劃分到其中;完成一次迭代后,重新計算每個超像素塊的中心點坐標(biāo),并重新進(jìn)行迭代(注:衡量效率和效果后一般選擇迭代10次)
二、代碼實現(xiàn)
1 importmath2 from skimage importio, color3 importnumpy as np4
5 classCluster(object):6
7 cluster_index = 1
8
9 def __init__(self, row, col, l=0, a=0, b=0):10 self.update(row, col, l, a, b)11 self.pixels =[]12 self.no =self.cluster_index13 Cluster.cluster_index += 1
14
15 defupdate(self, row, col, l, a, b):16 self.row =row17 self.col =col18 self.l =l19 self.a =a20 self.b =b21
22
23 classSLICProcessor(object):24 @staticmethod25 defopen_image(path):26 rgb =io.imread(path)27 lab_arr =color.rgb2lab(rgb)28 returnlab_arr29
30 @staticmethod31 defsave_lab_image(path, lab_arr):32 rgb_arr =color.lab2rgb(lab_arr)33 io.imsave(path, rgb_arr)34
35 defmake_cluster(self, row, col):36 row=int(row)37 col=int(col)38 returnCluster(row, col,39 self.data[row][col][0],40 self.data[row][col][1],41 self.data[row][col][2])42
43 def __init__(self, filename, K, M):44 self.K =K45 self.M =M46
47 self.data =self.open_image(filename)48 self.rows =self.data.shape[0]49 self.cols = self.data.shape[1]50 self.N = self.rows *self.cols51 self.S = int(math.sqrt(self.N /self.K))52
53 self.clusters =[]54 self.label ={}55 self.dis =np.full((self.rows, self.cols), np.inf)56
57 definit_clusters(self):58 row = self.S / 2
59 col = self.S / 2
60 while row <61 while col self.clusters.append>
65 row +=self.S66
67 defget_gradient(self, row, col):68 if col + 1 >=self.cols:69 col = self.cols - 2
70 if row + 1 >=self.rows:71 row = self.rows - 2
72
73 gradient = (self.data[row + 1][col][0] +self.data[row][col+1][0]-2*self.data[row][col][0])+\74 (self.data[row + 1][col][1] +self.data[row][col+1][1]-2*self.data[row][col][1]) +\75 (self.data[row + 1][col][2] +self.data[row][col+1][2]-2*self.data[row][col][2])76
77 returngradient78
79 defmove_clusters(self):80 for cluster inself.clusters:81 cluster_gradient =self.get_gradient(cluster.row, cluster.col)82 for dh in range(-1, 2):83 for dw in range(-1, 2):84 _row = cluster.row +dh85 _col = cluster.col +dw86 new_gradient =self.get_gradient(_row, _col)87 if new_gradient <88 cluster.update _col self.data cluster_gradient="new_gradient90</p">
91 defassignment(self):92 for cluster inself.clusters:93 for h in range(cluster.row - 2 * self.S, cluster.row + 2 *self.S):94 if h < 0 or h >= self.rows: continue
95 for w in range(cluster.col - 2 * self.S, cluster.col + 2 *self.S):96 if w < 0 or w >= self.cols: continue
97 L, A, B =self.data[h][w]98 Dc =math.sqrt(99 math.pow(L - cluster.l, 2) +
100 math.pow(A - cluster.a, 2) +
101 math.pow(B - cluster.b, 2))102 Ds =math.sqrt(103 math.pow(h - cluster.row, 2) +
104 math.pow(w - cluster.col, 2))105 D = math.sqrt(math.pow(Dc / self.M, 2) + math.pow(Ds / self.S, 2))106 if D
116 defupdate_cluster(self):117 for cluster inself.clusters:118 sum_h = sum_w = number =0119 for p incluster.pixels:120 sum_h +=p[0]121 sum_w += p[1]122 number += 1
123 _h =int( sum_h /number)124 _w =int( sum_w /number)125 cluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])126
127 defsave_current_image(self, name):128 image_arr =np.copy(self.data)129 for cluster inself.clusters:130 for p incluster.pixels:131 image_arr[p[0]][p[1]][0] =cluster.l132 image_arr[p[0]][p[1]][1] =cluster.a133 image_arr[p[0]][p[1]][2] =cluster.b134 image_arr[cluster.row][cluster.col][0] =0135 image_arr[cluster.row][cluster.col][1] =0136 image_arr[cluster.row][cluster.col][2] =0137 self.save_lab_image(name, image_arr)138
139 defiterates(self):140 self.init_clusters()141 self.move_clusters()142 #考慮到效率和效果,折中選擇迭代10次
143 for i in range(10):144 self.assignment()145 self.update_cluster()146 self.save_current_image("output.jpg")147
148
149 if __name__ == '__main__':150 p = SLICProcessor('beauty.jpg', 200, 40)151 p.iterates()
三、運行效果截圖
(原圖)
(效果圖)
代碼參考了https://github.com/laixintao/slic-python-implementation,且做了改進(jìn)
作為一枚技術(shù)小白,寫這篇筆記的時候參考了很多博客論文,在這里表示感謝,轉(zhuǎn)載請注明出處......
88>61>總結(jié)
以上是生活随笔為你收集整理的图像分割python代码_SILC超像素分割算法详解(附Python代码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PyTorch固定随机数种子
- 下一篇: websocket python爬虫_p