日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图像处理: 超像素(superpixels)分割 SLIC算法

發布時間:2023/12/31 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图像处理: 超像素(superpixels)分割 SLIC算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

簡介:最近項目使用到了超像素分割,因此順道研究了以下SLIC這一算法。超像素分割這類low-level vision問題已經在CVPR,ICCV這種頂級會議上逐漸銷聲匿跡,越來越流行的learning method漸漸占據了這些頂級會議90%的篇幅。本文講解的SLIC是2010年提出的一種十分簡單的超分辨分割算法,原理簡單、便于實現。

一.SLIC(simple linear iterative clustering)原理分析

  • 初始化種子點(聚類中心):按照設定的超像素個數,在圖像內均勻的分配種子點。假設圖片總共有 N 個像素點,預分割為 K 個相同尺寸的超像素,那么每個超像素的大小為N/ K ,則相鄰種子點的距離(步長)近似為S=sqrt(N/K)。

  • 在種子點的n*n鄰域內重新選擇種子點(一般取n=3)。具體方法為:計算該鄰域內所有像素點的梯度值,將種子點移到該鄰域內梯度最小的地方。這樣做的目的是為了避免種子點落在梯度較大的輪廓邊界上,以免影響后續聚類效果。

  • 在每個種子點周圍的鄰域內為每個像素點分配類標簽(即屬于哪個聚類中心)。和標準的k-means在整張圖中搜索不同,SLIC的搜索范圍限制為2S2S,可以加速算法收斂,如下圖。在此注意一點:期望的超像素尺寸為SS,但是搜索的范圍是2S*2S。

  • 距離度量。包括顏色距離和空間距離。對于每個搜索到的像素點,分別計算它和該種子點的距離。距離計算方法如下:


  • 其中,dc代表顏色距離,ds代表空間距離,Ns是類內最大空間距離,定義為Ns=S=sqrt(N/K),適用于每個聚類。最大的顏色距離Nc既隨圖片不同而不同,也隨聚類不同而不同,所以我們取一個固定常數m(取值范圍[1,40],一般取10)代替。最終的距離度量D’如下:

    由于每個像素點都會被多個種子點搜索到,所以每個像素點都會有一個與周圍種子點的距離,取最小值對應的種子點作為該像素點的聚類中心。

  • 迭代優化。理論上上述步驟不斷迭代直到誤差收斂(可以理解為每個像素點聚類中心不再發生變化為止),實踐發現10次迭代對絕大部分圖片都可以得到較理想效果,所以一般迭代次數取10。

  • 增強連通性。經過上述迭代優化可能出現以下瑕疵:出現多連通情況、超像素尺寸過小,單個超像素被切割成多個不連續超像素等,這些情況可以通過增強連通性解決。主要思路是:新建一張標記表,表內元素均為-1,按照“Z”型走向(從左到右,從上到下順序)將不連續的超像素、尺寸過小超像素重新分配給鄰近的超像素,遍歷過的像素點分配給相應的標簽,直到所有點遍歷完畢為止。

  • 二.偽算法描述

    /? Initialization ?/ Initialize cluster centers Ck = [lk , ak , bk , xk , yk ]T by sampling pixels at regular grid steps S. Move cluster centers to the lowest gradient position in a 3 × 3 neighborhood. Set label l(i) = ?1 for each pixel i. Set distance d(i) = ∞ for each pixel i.repeat /? Assignment ?/ for each cluster center Ck dofor each pixel i in a 2S × 2S region around Ck do Compute the distance D between Ck and i.if D < d(i) thenset d(i) = Dset l(i) = k end ifend for end for/? Update ?/ Compute new cluster centers. Compute residual error E. until E ≤ threshold

    三.參考博文

    1.https://github.com/laixintao/slic-python-implementation
    2.https://blog.csdn.net/zhj_matlab/article/details/52986700
    3.https://blog.csdn.net/electech6/article/details/45509779



    超像素(Superpixel)理解

      最近看點云處理的文章,有些文章中提到了superpixel這個概念,查了一些資料,對其理解記錄如下:

    • 超像素就是把一幅原本是像素級(pixel-level)的圖,劃分成區域級(district-level)的圖。可以將其看做是對基本信息進行的抽象。
    • 超像素分割屬于圖像分割(image segmentation),再細化應該屬于過分割(over segmentation)。
    • 比如我們對一幅圖像進行超像素分割,分割之后,會得到許多大小不一的區域,我們可以從這些區域中提取出有效的信息,比如顏色直方圖、紋理信息。比如有一個人,我們可以對這個人的圖像進行超像素分割,進而通過對每個小區域的特征提取,辨識出這些區域是處于人體的哪個部分(頭部、肩部,腿部),進而建立人體的關節圖像。
    • 如果你要用圖論的方法來分離前景背景。如果這幅圖的大小為480 * 640,那么你建立的圖(graph)有480640個節點。如果你預先對這幅圖像使用超像素分割,將其分割為1000個超像素,那么你建立的圖只有1000個節點。大大提升了計算速度。
    • 有趣直觀并且帶有源代碼(業界良心)的是SLIC Superpixel,使用K-means的聚類方法,分割的效果很好。地址為:https://infoscience.epfl.ch/record/177415



    原理
    超像素概念是2003年Xiaofeng Ren提出和發展起來的圖像分割技術,是指具有相似紋理、顏色、亮度等特征的相鄰像素構成的有一定視覺意義的不規則像素塊。它利用像素之間特征的相似性將像素分組,用少量的超像素代替大量的像素來表達圖片特征,很大程度上降低了圖像后處理的復雜度,所以通常作為分割算法的預處理步驟。

    常見的超像素分割方法包括: Graph-based 、NCut 、Turbopixel 、 Quick-shift 、 Graph-cut a、Graph-cut b 以及 SLIC 。

    其中,SLIC(simple linear iterativeclustering),即 簡單線性迭代聚類 。?
    它是2010年提出的一種思想簡單、實現方便的算法,將彩色圖像轉化為CIELAB顏色空間和XY坐標下的5維特征向量,然后對5維特征向量構造距離度量標準,對圖像像素進行局部聚類的過程。

    SLIC主要優點如下:

    生成的超像素如同細胞一般緊湊整齊,鄰域特征比較容易表達。這樣基于像素的方法可以比較容易的改造為基于超像素的方法。
    不僅可以分割彩色圖,也可以兼容分割灰度圖。
    需要設置的參數非常少,默認情況下只需要設置一個預分割的超像素的數量。
    相比其他的超像素分割方法,SLIC在運行速度、生成超像素的緊湊度、輪廓保持方面都比較理想。

    效果圖

    經過觀察發現,在迭代至第10輪后,分割效果基本不再發生變化。

    原圖


    K=64 時

    第1輪迭代,效果圖:

    第20輪迭代,效果圖:?


    K=128 時

    第1輪迭代,效果圖:?

    第20輪迭代,效果圖:?


    K=256 時

    第1輪迭代,效果圖:?

    第20輪迭代,效果圖:?


    K=1024 時

    第1輪迭代,效果圖:?

    第20輪迭代,效果圖:?


    實現代碼

    代碼是我上網找來的,稍微改動了一丟丟。

    原代碼出處:SLIC算法分割超像素原理及Python實現

    import math from skimage import io, color import numpy as np from tqdm import trangeclass Cluster(object):cluster_index = 1def __init__(self, h, w, l=0, a=0, b=0):self.update(h, w, l, a, b)self.pixels = []self.no = self.cluster_indexself.cluster_index += 1def update(self, h, w, l, a, b):self.h = hself.w = wself.l = lself.a = aself.b = bdef __str__(self):return "{},{}:{} {} {} ".format(self.h, self.w, self.l, self.a, self.b)def __repr__(self):return self.__str__()class SLICProcessor(object):@staticmethoddef open_image(path):"""Return:3D array, row col [LAB]"""rgb = io.imread(path)lab_arr = color.rgb2lab(rgb)return lab_arr@staticmethoddef save_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)def make_cluster(self, h, w):return Cluster(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 = Kself.M = Mself.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_widthself.S = int(math.sqrt(self.N / self.K))self.clusters = []self.label = {}self.dis = np.full((self.image_height, self.image_width), np.inf)def init_clusters(self):h = self.S / 2w = self.S / 2while h < self.image_height:while w < self.image_width:self.clusters.append(self.make_cluster(h, w))w += self.Sw = self.S / 2h += self.Sdef get_gradient(self, h, w):if w + 1 >= self.image_width:w = self.image_width - 2if h + 1 >= self.image_height:h = self.image_height - 2gradient = 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]return gradientdef move_clusters(self):for cluster in self.clusters:cluster_gradient = self.get_gradient(cluster.h, cluster.w)for dh in range(-1, 2):for dw in range(-1, 2):_h = cluster.h + dh_w = cluster.w + dwnew_gradient = self.get_gradient(_h, _w)if new_gradient < cluster_gradient:cluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])cluster_gradient = new_gradientdef assignment(self):for cluster in self.clusters:for h in range(cluster.h - 2 * self.S, cluster.h + 2 * self.S):if h < 0 or h >= self.image_height: continuefor w in range(cluster.w - 2 * self.S, cluster.w + 2 * self.S):if w < 0 or w >= self.image_width: continueL, 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))if D < self.dis[h][w]:if (h, w) not in self.label:self.label[(h, w)] = clustercluster.pixels.append((h, w))else:self.label[(h, w)].pixels.remove((h, w))self.label[(h, w)] = clustercluster.pixels.append((h, w))self.dis[h][w] = Ddef update_cluster(self):for cluster in self.clusters:sum_h = sum_w = number = 0for p in cluster.pixels:sum_h += p[0]sum_w += p[1]number += 1_h = sum_h / number_w = sum_w / numbercluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])def save_current_image(self, name):image_arr = np.copy(self.data)for cluster in self.clusters:for p in cluster.pixels:image_arr[p[0]][p[1]][0] = cluster.limage_arr[p[0]][p[1]][1] = cluster.aimage_arr[p[0]][p[1]][2] = cluster.bimage_arr[cluster.h][cluster.w][0] = 0image_arr[cluster.h][cluster.w][1] = 0image_arr[cluster.h][cluster.w][2] = 0self.save_lab_image(name, image_arr)def iterate_10times(self):self.init_clusters()self.move_clusters()for i in trange(20):self.assignment()self.update_cluster()name = 'Elegent_Girl_M{m}_K{k}_loop{loop}.jpg'.format(loop=i, m=self.M, k=self.K)self.save_current_image(name)if __name__ == '__main__':for k in [64, 128, 256, 1024]:p = SLICProcessor('800.jpg', k, 30)p.iterate_10times()

    打印結果:

    0%| | 0/20 [00:00<?, ?it/s]/home/user/anaconda2/lib/python2.7/site-packages/skimage/util/dtype.py:111: UserWarning: Possible precision loss when converting from float64 to uint8"%s to %s" % (dtypeobj_in, dtypeobj)) 100%|##########| 20/20 [32:36<00:00, 97.83s/it] 100%|##########| 20/20 [24:37<00:00, 73.88s/it] 100%|##########| 20/20 [21:30<00:00, 64.55s/it] 100%|##########| 20/20 [18:49<00:00, 56.46s/it]Process finished with exit code 0

    ?

    總結

    以上是生活随笔為你收集整理的图像处理: 超像素(superpixels)分割 SLIC算法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。