算法分析
-
圖像預處理。對二值圖進行形態學開操作,開操作能去掉細小的塊,平滑目標區域邊界且保持面積不變
-
遍歷二值圖矩陣,尋找目標區域且未被標記的點,若當前像素未標記且當前位置像素點為1(二值圖的目標區域)
-
將該目標點入隊,並標上區域編號label
-
BFS,對步驟1中的求得8鄰域的像素點,如果該點未越界,是目標點(灰度值為1)並且未被標記過則入隊,並且標上當前編號label,隊列中每個點的8領域判斷完則出隊,當隊列為空時一個連通區域標記完成,label+1
-
回到步驟1,直到二值圖遍歷完成
-
輸出,將標記矩陣以彩色標記的形式輸出,循環結束時label的值多加了1,退出循環時,label的值減1才是該圖中的連通區域的個數
偽代碼
function [conn,num] = mybwlabel( I )
% 使用BFS對二值圖區域標記
% 輸入:I是二值圖矩陣
% 輸出:tmp是標記矩陣,num是連通區域個數
[m n] = 計算二值圖的大小
conn = 開辟一個和二值圖同樣大小的標記矩陣
label = 給區域編號設初值1
queue = 定義二維數組用於存放一個連通區域的點的坐標(模擬隊列)
neighbour = 8鄰域(坐標無序)
遍歷二值圖
如果當前點屬於目標區域且未標記
queue = 當前點坐標入隊
conn(i,j) = 給該點賦值區域編號
隊列不空
index = 取出隊首坐標
8鄰域搜索
cur_index = 當前點鄰域坐標
如果當前坐標未越界
如果當前像素鄰域像素為1並且標記圖像的這個鄰域像素沒有被標記
標記當前點
當前坐標入隊(矩陣合並)
隊首坐標出
label = 區域編號加1
num = 連通區域的個數為label-1
end
代碼
function [conn,num] = mybwlabel( I )
% 對二值圖區域標記
% 輸入:I是二值圖矩陣
% 輸出:tmp是標記矩陣,num是連通區域個數
[m n] = size(I);
conn = zeros(m,n); %標記矩陣
label = 1;
queue = []; %用二維數組模擬隊列
%和當前像素坐標相加得到八個鄰域坐標(坐標無序)
neighbour = [-1 -1;-1 0;-1 1;0 -1;0 1;1 -1;1 0;1 1];
for i = 2 : m-1
for j = 2 : n-1
if I(i,j) == 1 && conn(i,j) == 0 %屬於目標區域且未標記才處理
conn(i,j) = label;
queue = [i;j]; %記錄當前點坐標
while ~isempty(queue) %隊列不空,這里沒有出隊操作,隊列中的每一個元素的8領域都判斷一遍
index = [queue(1,1),queue(2,1)];
for k = 1 : 8 %8鄰域搜索
cur_index = index + neighbour(k,:); %加上每一行的坐標得到周圍8鄰域的坐標點
if cur_index(1) >= 2 && cur_index(1) <= m - 1 && cur_index(2) >= 2 && cur_index(2) <= n - 1 %防止坐標越界
if I(cur_index(1),cur_index(2)) == 1 && conn(cur_index(1),cur_index(2)) ==0 %如果當前像素鄰域像素為1並且標記圖像的這個鄰域像素沒有被標記,那么標記
conn(cur_index(1),cur_index(2)) = label;
queue = [queue [cur_index(1);cur_index(2)]];
end
end
end
queue(:,1) = []; %隊列中第一列的坐標出隊
end
label = label+1;
end
end
end
num = label - 1; %連通區域的個數(減去背景這個連通區域)
end
實驗結果
% 調用示例:
I = imread('rice.png');
Ib = im2bw(I);
[B,num] = mybwlabel(Ib);
subplot(1,3,1),imshow(I),title('原圖');
subplot(1,3,2),imshow(Ib),title('二值圖');
subplot(1,3,3),imshow(label2rgb(B)),title('區域標記');
連通區域個數:
圖像預處理去噪,由上圖中二值化之后,二值圖中有很多噪聲點,可以通過形態學開操作去除這些點
SE = strel('disk',3); %定義一個圓形結構元
Ib = imopen(Ib,SE); %開操作去除噪聲
開操作之后的效果
連通區域個數:
開操作之后去除噪聲,連通區域個數明顯減少
實驗分析
-
在標記連通區域之前可以通過形態學操作,去除噪聲點
-
對二值圖中每一個像素點的8鄰域,都遍歷一遍,將8鄰域中屬於目標區域的點的坐標都入隊,對於當前滿足條件的像素點判斷結束時,就會標記完一個連通區域
-
在遍歷8領域時為避免重復標記,需要多次判斷當前是否已經標記