圖像分割
圖像分割,英文名image segmentation,就是把圖像分成若幹個特定的、具有獨特性質的區域并提出感興趣目标的技術和過程。它是由圖像處理到圖像分析的關鍵步驟。現有的圖像分割方法主要分以下幾類:
- 基于門檻值的分割方法
- 基于區域的分割方法
- 基于邊緣的分割方法以及基于特定理論的分割方法
從數學角度來看,圖像分割是将數字圖像劃分成互不相交的區域的過程。圖像分割的過程也是一個标記過程,即把屬于同一區域的像索賦予相同的編号。
- 圖像分割的目标是将圖像中像素根據一定的規則分為若幹個(N)個cluster集合,I每個集合包含一類像素。
- 根據算法分為監督學習算法和無監督學習算法,圖像分割的算法多數都是無監督學習算法。---KMeans
距離變換與分水嶺介紹
距離變換
距離變換常見算法有兩種
- 不斷膨脹/ 腐蝕得到
- 基于倒角距離
分水嶺變換
分水嶺變換常見的算法
基于浸泡理論實作
相關API
cv::distanceTransform(
InputArray src,
OutputArray dst,
OutputArray labels,
int distanceType,
int maskSize,
int labelType = DIST_LABEL_CCOMP
)
distanceType = DIST_L1/DIST_L2,
maskSize = 3x3,最新的支援5x5,推薦3x3、
labels離散維諾圖輸出,
dst輸出8位或者32位的浮點數,單一通道,大小與輸入圖像一緻
cv::watershed(
InputArray image,
InputOutputArray markers
)
操作步驟
- 将白色背景變成黑色-目的是為後面的變換做準備
- 使用filter2D與拉普拉斯算子實作圖像對比度提高,sharp
- 轉為二值圖像通過threshold
- 距離變換
- 對距離變換結果進行歸一化到[0~1]之間
- 使用門檻值,再次二值化,得到标記
- 腐蝕得到每個Peak - erode
- 發現輪廓 – findContours
- 繪制輪廓- drawContours
- 分水嶺變換 watershed
- 對每個分割區域着色輸出結果
代碼示範
建立一個項目opencv-0027,配置屬性(VS2017配置OpenCV通用屬性),然後在源檔案寫入#include和main方法
這次我們用opencv裡面自帶的一張圖像來實個這個方法
運作顯示的圖像為
1.将白色背景變成黑色
我們運作看一下
可以看到右邊的已經把背景都換為黑色了。
2.使用filter2D與拉普拉斯算子實作圖像對比度提高,sharp
我們再運作看一下,左邊的就是生成的結果圖,可以看出左邊的清晰度更高了一些
3.轉為二值圖像通過threshold
我們再運作看一下,左邊的圖像已經讓我們轉換為二值圖像了,也比較清晰
4.距離變換
5.對距離變換結果進行歸一化到[0~1]之間
因為距離變換看不出任何效果,是以我們把4和5兩步放在一起顯示
我們再運作一下看看執行結果
6.使用門檻值,再次二值化,得到标記
顯示效果為
7.腐蝕得到每個Peak
效果不太好看,我們需要再進行二值的腐蝕,把上面的代碼再修改一下
我們再看一下運作效果,可以看出來比剛才的效果好很多了
8.标記并且開始查找輪廓
這一步隻是查找輪廓,我們接下來繪制查找的輪廓再一起顯示出來
9.繪制輪廓
上面drawContours和circle最後一個參數都是用了-1,代表着畫的輪廓裡面進行顔色填充
我們再顯示一下看看效果
看到好像什麼也沒有,這是因為我們畫的輪廓太小了, 我們改一下顯示效果
把最後顯示cv::imshow(imgdst,makers*5000)再乘5000,重新看一下顯示效果
這會兒就可以看到繪制的輪廓出來了
10.分水嶺變換
我們看看顯示的效果
可以看出,每個輪廓都有明顯的區分開了。
11.對每個分割區域着色輸出結果
然後我們再運作看到最後結果
-END-