【手撕算法】C++實現超像素分割算法

點擊上方"藍色小字"關注我呀
javascript







寫完這篇,圖像分割的傳統方法就快全了,傳統圖像分割大致有基於閾值的,這類就沒啥算法能夠寫,因此直接略過了;而後就是K-means這種聚類/分裂的,從幾個點開始進行聚類分割,或者一張圖不斷分裂達到分割目的;

【手撕算法】K-means算法實現主題色提取
java

再有就是區域生長這類的;算法

【手撕算法】基於隊列實現的區域增加分割算法
微信

以及分水嶺算法,分水嶺算法代碼寫好有一段時間了,但實在不知道文章咋寫...就再放放吧;最後就是超像素分割了,超像素分割有k-means算法的影子,因此能夠先看看k-means算法的代碼實現過程。app

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

  2. 在種子點的n*n鄰域內從新選擇種子點(通常取n=3)。具體方法爲:計算該鄰域內全部像素點的梯度值,將種子點移到該鄰域內梯度最小的地方。這樣作的目的是爲了不種子點落在梯度較大的輪廓邊界上,以避免影響後續聚類效果。flex

  3. 在每一個種子點周圍的鄰域內爲每一個像素點分配類標籤(即屬於哪一個聚類中心)。和標準的k-means在整張圖中搜索不一樣,SLIC的搜索範圍限制爲2S2S,能夠加速算法收斂,以下圖。在此注意一點:指望的超像素尺寸爲SS,可是搜索的範圍是2S*2S。優化

  4. 距離度量。包括顏色距離和空間距離。對於每一個搜索到的像素點,分別計算它和該種子點的距離。距離計算方法以下:ui

    其中,dc表明顏色距離,ds表明空間距離,Ns是類內最大空間距離,定義爲Ns=S=sqrt(N/K),適用於每一個聚類。最大的顏色距離Nc既隨圖片不一樣而不一樣,也隨聚類不一樣而不一樣,因此咱們取一個固定常數m(取值範圍[1,40],通常取10)代替。最終的距離度量D’以下:url

    因爲每一個像素點都會被多個種子點搜索到,因此每一個像素點都會有一個與周圍種子點的距離,取最小值對應的種子點做爲該像素點的聚類中心。

  5. 迭代優化。理論上上述步驟不斷迭代直到偏差收斂(能夠理解爲每一個像素點聚類中心再也不發生變化爲止),實踐發現10次迭代對絕大部分圖片均可以獲得較理想效果,因此通常迭代次數取10。

  6. 加強連通性。通過上述迭代優化可能出現如下瑕疵:出現多連通狀況、超像素尺寸太小,單個超像素被切割成多個不連續超像素等,這些狀況能夠經過加強連通性解決。主要思路是:新建一張標記表,表內元素均爲-1,按照「Z」型走向(從左到右,從上到下順序)將不連續的超像素、尺寸太小超像素從新分配給鄰近的超像素,遍歷過的像素點分配給相應的標籤,直到全部點遍歷完畢爲止。
僞算法描述

程序介紹

程序聲明瞭一個SLIC算法類,類的具體程序太長了,就不貼了,你們能夠去qq羣下載程序本身看,都註釋好了。

就看一下主程序吧:

int main(){  【1】讀取原圖並顯示 Mat image = imread("千矢.png",33); if (image.empty()) { printf_s("圖片讀取失敗"); return -1; } imshow("原圖", image);  【2】轉換爲LAB顏色空間  方便計算距離 Mat lab_image = image.clone(); cvtColor(image, lab_image, COLOR_BGR2Lab);
//定義超像素數以及權重 int w = image.cols, h = image.rows; int nr_superpixels = 300;//超像素數  int nc = 40;//權重m  double step = sqrt((w * h) / (double)nr_superpixels);  【3】執行SLIC超像素算法 SLIC slic; slic.generate_superpixels(&lab_image, step, nc); slic.create_connectivity(&lab_image);
  【4】顯示分割輪廓和分割結果圖 //該三個函數能夠分別註釋單獨顯示查看 slic.colour_with_cluster_means(&image);//顏色均值填充 slic.display_contours(&image, Scalar(0, 0, 255));//顯示輪廓 //slic.display_center_grid(&image, Scalar(255, 0, 0));//顯示中心點 imshow("result", image);  waitKey(0);}

一共是四個步驟。其中步驟【2】中須要本身定義兩個變量nr_superpixels和nc。

  • nr_superpixels爲超像素個數,你能夠根據圖像大小本身定義,若是圖像x方向10個超像素塊,y方向30個超像素塊,那就是300。

  • 權重變量nc,即上文【算法原理】第4步中的固定常數m,通常取1-40範圍內的整數。

效果展現

THE  END

本文原創內容有限,就是整合了一下本身看的超像素分割的博客,兩篇不錯的連接放這兒了:

https://blog.csdn.net/zhj_matlab/article/details/52986700https://blog.csdn.net/qq_26129959/article/details/90760028

代碼放qq羣了,今天就到這裏啦。

本文分享自微信公衆號 - Opencv視覺實踐(gh_31e12b1be0e0)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索