實驗中需要用到區域聯通的演算法,就是類似於matlab中bwlabel的函式。網上找了找c++原始碼未果,
bwlabel-python版
用python描述了matlab中的實現方法,但是最後對標籤的處理部分並未看明白,故自己用c++實現了乙個。先直接看bwlabel函式**:
cv::mat bwlabel(const cv::mat in, int * num, const int mode)
if(num != null)
*num = number;
delete sc;
delete ec;
delete r;
delete labels;
return result;
}
bwlabel中要用到三個輔助函式:number_of_runs,fill_run_vectors,first_pass。函式number_of_runs計算每一行中非零畫素團的個數並累加起來。
1 1 0 0 0 1 1 1 0 0
比如,上面這一行就有2個非零畫素團,我們稱這樣的畫素團為run,函式number_of_runs實現如下:
int number_of_runs(const cv::mat in)
}return result;
}
這個函式演算法思想是,掃瞄每一行,對每一行,如果當前元素非零並且前一元素為零則run的個數加一。
函式fill_run_vectors的作用是填充三個資料結構:sc,ec,r,它們分別表示開始列標、結束列標和行標,陣列長度為由number_of_runs函式得到的run的個數。函式fill_run_vectors實現如下:
void fill_run_vectors(const cv::mat in, int sc, int ec, int r)
else
}if(col == cols-1 && prev == 1)}}
}
演算法思想還是遍歷每一行,用變數prev儲存一行中上乙個團是0還是1,如果出現01跳變那麼就要記錄下新的run的開始列標和行標,如果出現10跳變(或者這行結束並且prev=1)那麼就記錄下這個run的結束列標。
函式first_pass顧名思義,字面上說第一次掃瞄。因為函式掃瞄每乙個run塊,給它打標籤。當出現如下情況時:
1 1 0 0 1 1 1 0
0 1 1 1 1 0 0 0
函式給第一行第乙個run打上標籤1,第二個run打上標籤2,當遍歷到第二行時,發現這一行的乙個run與第一行第乙個run相鄰,故打上標籤1,但當繼續遍歷時發現這個run也與第一行第二個run相鄰,但函式並沒有改變第一行第二個run的標籤,而是記錄下這兩個標籤其實該一樣。遍歷完第二行結果為:
1 1 0 0 2 2 2 0
0 1 1 1 1 0 0 0
遍歷完每乙個run過後就是處理剛才未處理的標籤了。函式first_pass實現如下:
void first_pass(const int sc, const int ec, const int r,int labels, const int num_runs, const int mode)
else if(r[k] > cur_row + 1)
if(first_run_on_prev_row >= 0)
}p += 1;}}
if(labels[k] == 0)
}/// process labels
for(int i = 0; i < equal_idx; i++)
}delete equal_i;
delete equal_j;
/process ignore labels
int * hist = new int[next_label];
int * non_labels = new int[next_label];
memset(hist, 0, sizeof(int)*next_label);
int non_num = 0;
for(int i = 0; i < num_runs; i++)
for(int i = 1; i < next_label; i++)
for(int j = 0; j < num_runs; j++)}}
delete hist;
delete non_labels;
}
前面遍歷每乙個run分兩種情況,上一行有run和上一行無run:當上一行無run時就分配乙個新的標籤,當上一行有run時還要考慮是否與上一行run相鄰,若相鄰則打上上一行的標籤,當出現上面講到的情況時就儲存這兩個標籤到陣列equal_i,equal_j中。
接下來就是處理equal_i和equal_j這兩個陣列了,要將它們當中相同族的不同標籤合併到一起(注釋process labels下面**)。
這樣過後還不能完事,有可能出現標籤間斷的現象(如1,2,4,6),就是還必須把標籤(如1,2,4,6)對映到乙個連續的空間(1,2,3,4)。參見注釋process ignore labels以下**。
這樣過後就差不多了,最後一步是在bwlabel中給返回的mat中元素打上對應的標籤。
Matlab實現bwlabel函式(區域標記)功能
影象預處理。對二值圖進行形態學開操作,開操作能去掉細小的塊,平滑目標區域邊界且保持面積不變 遍歷二值圖矩陣,尋找目標區域且未被標記的點,若當前畫素未標記且當前位置畫素點為1 二值圖的目標區域 將該目標點入隊,並標上區域編號label bfs,對步驟1中的求得8鄰域的畫素點,如果該點未越界,是目標點 ...
bwlabel演算法 BWLABEL的演算法
的函式 使得最後我也參加了討論。當時我說了一句錯 話 大概 ipt中的 bwlabel 也使用廣度優先的演算法吧。其實bwlabel 用的並不是圖的廣度 優先遍歷。它用的演算法正是本系列文章 討論的內容。雖然是本系列的第一篇,但我不打算介紹 bwlabel 的功能,因為這篇文章針對需要了 解演算法的...
Matlab中bwlabel函式的使用
l bwlabel bw,n 功能概述 返回乙個和bw大小相同的l矩陣,包含了標記了bw中每個連通區域的類別標籤,這些標籤的值為1 2 num 連通區域的個數 n的值為4或8,表示是按4連通尋找區域,還是8連通尋找,預設為8。用法 l bwlabel bw l bwlabel bw,n l,num ...