【手撕算法】C++实现超像素分割算法
寫完這篇,圖像分割的傳統方法就快全了,傳統圖像分割大體有基于閾值的,這類就沒啥算法可以寫,所以直接略過了;然后就是K-means這種聚類/分裂的,從幾個點開始進行聚類分割,或者一張圖不斷分裂達到分割目的;
【手撕算法】K-means算法實現主題色提取
再有就是區域生長這類的;
【手撕算法】基于隊列實現的區域增長分割算法
以及分水嶺算法,分水嶺算法代碼寫好有一段時間了,但實在不知道文章咋寫…就再放放吧;最后就是超像素分割了,超像素分割有k-means算法的影子,所以可以先看看k-means算法的代碼實現過程。
1,算法原理
初始化種子點(聚類中心):按照設定的超像素個數,在圖像內均勻的分配種子點。假設圖片總共有 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”型走向(從左到右,從上到下順序)將不連續的超像素、尺寸過小超像素重新分配給鄰近的超像素,遍歷過的像素點分配給相應的標簽,直到所有點遍歷完畢為止。
2,偽算法描述
3,程序介紹
程序聲明了一個SLIC算法類,類的具體程序太長了,就不貼了,大家可以去qq群【222954293】下載程序自己看,都注釋好了。
就看一下主程序吧:
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;//權重mdouble 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范圍內的整數。
3,效果展示
4,THE END
本文原創內容有限,就是整合了一下自己看的超像素分割的博客,兩篇不錯的鏈接放這兒了:
https://blog.csdn.net/zhj_matlab/article/details/52986700 https://blog.csdn.net/qq_26129959/article/details/90760028代碼放qq群【222954293】了,今天就到這里啦。
總結
以上是生活随笔為你收集整理的【手撕算法】C++实现超像素分割算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机黑屏什么原因,教您电脑黑屏的原因是
- 下一篇: C++ OpenCV光平面标定-线激光提