Matlab實現bwlabel函數(區域標記)功能


算法分析

  1. 圖像預處理。對二值圖進行形態學開操作,開操作能去掉細小的塊,平滑目標區域邊界且保持面積不變

  2. 遍歷二值圖矩陣,尋找目標區域且未被標記的點,若當前像素未標記且當前位置像素點為1(二值圖的目標區域)

  3. 將該目標點入隊,並標上區域編號label

  4. BFS,對步驟1中的求得8鄰域的像素點,如果該點未越界,是目標點(灰度值為1)並且未被標記過則入隊,並且標上當前編號label,隊列中每個點的8領域判斷完則出隊,當隊列為空時一個連通區域標記完成,label+1

  5. 回到步驟1,直到二值圖遍歷完成

  6. 輸出,將標記矩陣以彩色標記的形式輸出,循環結束時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領域時為避免重復標記,需要多次判斷當前是否已經標記


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM