天天看點

OpenCV學習(9) 分水嶺算法(3)

本教程我學習一下opencv中分水嶺算法的具體實作方式。

原始圖像和Mark圖像,它們的大小都是32*32,分水嶺算法的結果是得到兩個連通域的輪廓圖。

原始圖像:(原始圖像必須是3通道圖像)

OpenCV學習(9) 分水嶺算法(3)

Mark圖像:

OpenCV學習(9) 分水嶺算法(3)

結果圖像:

OpenCV學習(9) 分水嶺算法(3)

      初始的mark圖像資料如下,黃色的部分為我們的第一個mark區域,值為255,第二個區域為褐紅色的區域,值為128,第三個綠色的區域,值為64。

OpenCV學習(9) 分水嶺算法(3)

opencv分水嶺算法描述如下:

初始化mark矩陣,生成最初的注水區域。

1.設定mark圖像的邊框值為-1

2. 标記每個mark區域的邊界為-2

3. 對于mark圖像一個像素值,如果它本身值為0,但上下左右四鄰域有一個像素值不為0,則把該點按照RGB高度值放入相應的隊列。

      舉例說明:如下圖像素點,它的mark值為0,但左和上像素值不為0,此時,我們求原始圖像中對應像素的高度值,高度值的計算方式如下面公式,其中R表示Red通道值,G表示Green通道值,B表示Blue通道值,下标L表示左,R表示右,T表示上,B表示下,abs表示取絕對值,min和max分别為最小值和最大值函數:

min(max(abs(R-RL), abs(G-GL), abs(B-BL)),max(abs(R-RT), abs(G-GT), abs(B-BT)),max(abs(R-RR), abs(G-GR), abs(B-BR)),max(abs(R-RB), abs(G-GB), abs(B-BB)))

OpenCV學習(9) 分水嶺算法(3)

上圖中指定的像素,它的高度值顯然為0,是以我們把(2,2)點放入高度為0的隊列中(總共有256個隊列,對應0-255的高度)

OpenCV學習(9) 分水嶺算法(3)

   初始化階段完成後,我們得到下面的mark圖,并把-2對應的邊界像素點,按照其對應的RGB高度值放入相應的隊列。

OpenCV學習(9) 分水嶺算法(3)

之後就進入了遞歸注水過程,遞歸過程描述如下:

for(; ; )

{

    掃描0-255高度值隊列,如果找到一個像素标記,則彈出該标記,并退出掃描。

    如果該像素的四鄰域中存在兩個不同的非0值,表示該點為兩個注水盆地的邊緣,即分水嶺線,在mark圖像中标記該點為-1。

    掃描該點的四鄰域,是否存在為0的mark域,存在的話這把該鄰域點按照rgb高度值,放入相應的隊列。

}

經過上述的遞歸過程,最後我們得到的mark圖像如下所示,其中綠色格子的-1即為所有的分水嶺邊界:

OpenCV學習(9) 分水嶺算法(3)

代碼參見工程:FirstOpenCV10

      我們也可以把輸入圖像換成灰階圖,這樣求高度值時,就比較簡單,void WatershedGray(cv::Mat &src, cv::Mat &dst);該函數示範灰階圖的分水嶺算法。

繼續閱讀