一、理論概念
區域生長是按照事先定義的生長准則將一個像素或者子區域逐步聚合成一個完整獨立的連通區域過程。對於圖像感興趣目標區域R,z為區域R上事先發現的種子點,按照規定的生長准則逐步將與種子點z一定鄰域內符合相似性判據的像素合並成一個種子群以備下一階段的生長,這樣不斷的進行循環生長直到滿足生長停止條件為止,從而完成了對感興趣區域由一個種子點生長為一個獨立連通區域的過程。其中相似性判據可以是像素灰度值、顏色、紋理特征等圖像信息。
因此區域生長算法一般分為三個步驟實現:
(1) 確定生長種子點
(2) 規定生長准則
(3) 確定生長停止條件
實際工程應用中區域生長算法常被用於對二值化圖像指定連通區域的分割。圖1以圖文方式對區域生長算法的三步驟進行解釋:
① 原始二值化圖像(a)中的紅色標注的像素為指定生長點;
② 圖像(b)和(c)是采用不同生長准則進行區域生長的結果,其中圖(b)是在4鄰域下,待測像素與生長點像素灰度值相等的像素集合。正如圖中所示第1次生長時,與生長點像素灰度相等的像素有上、下、左、右四個像素,接着第二次生長時,就由前一次已經生長的像素按照同樣的准則進行下去,直到遇到圖像邊界或背景區域時生長停止。圖(c)是在8鄰域下,待測像素與生長點像素灰度值相等的像素集合。
二、MATLAB示例代碼實現
2.1 主函數文件
%主文件 clc; clear all; close all; %申明全局變量 R:區域生長的結果圖像;BW:二值化圖像;counter:感興趣連通區域的像素個數 %row:圖像的行數;col:圖像的列數 global R BW counter row col I = imread('E:\MATLAB仿真\fsr.bmp'); I = I(:,:,1); [row,col] = size(I); figure,imshow(I); level = graythresh(I); BW = im2bw(I,level); figure,imshow(BW); [y0,x0] = getpts; x0 = uint32(x0); y0 = uint32(y0); counter = 0; R = zeros(row,col); R = uint8(R); fsrRegiongrow(x0,y0,4);% fsrRegiongrow1(x0,y0,4); figure,imshow(R);
2.2 函數模塊1
function fsrRegiongrow(x0,y0,mode) %功能: 通過函數遞歸方法對二值化圖像指定連通區域實現區域生長 %輸入參數: x0,y0表示生長點像素坐標,mode表示以多大鄰域進行區域生長,常取mode = 4;mode = 8; %輸出參數: void %作者&時間: 奔跑在湘邊———2016年5月6日 global R BW counter row col if 8 == mode for i = -1 : 1 for j = -1 : 1 x1 = x0 + i; y1 = y0 + j; %生長准則:判斷生長點8鄰域內像素的各自灰度值是否與生長點所在像素灰度值相等 if x1 > 0 && x1 <= row && y1 > 0 && y1 <= col && BW(x1,y1) == BW(x0,y0) && 0 == R(x1,y1) R(x1,y1) = 255; counter = counter + 1; fsrRegiongrow(x1,y1,mode); end end end elseif 4 == mode for i = -1 : 1 x1 = x0 + i; y1 = y0; if x1 > 0 && x1 <= row && y1 > 0 && y1 <= col && BW(x1,y1) == BW(x0,y0) && 0 == R(x1,y1) R(x1,y1) = 255; counter = counter + 1; fsrRegiongrow(x1,y1,mode); end end x1 = x0; y1 = y0 - 1; if x1 > 0 && x1 <= row && y1 > 0 && y1 <= col && BW(x1,y1) == BW(x0,y0) && 0 == R(x1,y1) R(x1,y1) = 255; counter = counter + 1; fsrRegiongrow(x1,y1,mode); end x1 = x0; y1 = y0 + 1; if x1 > 0 && x1 <= row && y1 > 0 && y1 <= col && BW(x1,y1) == BW(x0,y0) && 0 == R(x1,y1) R(x1,y1) = 255; counter = counter + 1; fsrRegiongrow(x1,y1,mode); end end end
2.3 函數模塊2
function fsrRegiongrow1(x0,y0,mode) %功能: 模擬棧的先進后出思路對二值化圖像指定連通區域實現區域生長 %輸入參數: x0,y0表示生長點像素坐標,mode表示以多大鄰域進行區域生長,常取mode = 4;mode = 8; %輸出參數: void %作者&時間: 奔跑在湘邊———2016年5月6日 global R BW counter row col zhan = zeros(row*col,2);%創建棧數組 pzhan = 1; %棧計數 zhan(pzhan,1) = x0; zhan(pzhan,2) = y0; R(x0,y0) = 255; counter = 1; if 8 == mode while pzhan > 0 x1 = zhan(pzhan,1);%出棧 y1 = zhan(pzhan,2); pzhan = pzhan - 1; %棧計數減一 for i = -1 : 1 for j = -1 : 1 %生長准則:判斷生長點8鄰域內像素的各自灰度值是否與生長點所在像素灰度值相等 if x1+i > 0 && x1+i <= row && y1+j > 0 && y1+j <= col && BW(x1+i,y1+j) == BW(x1,y1) && R(x1+i,y1+j) ~= R(x1,y1) R(x1+i,y1+j) = R(x1,y1); counter = counter + 1; pzhan = pzhan + 1; %棧計數增一 zhan(pzhan,1) = x1 + i;%入棧 zhan(pzhan,2) = y1 + j; end end end end elseif 4 == mode while pzhan > 0 x1 = zhan(pzhan,1); y1 = zhan(pzhan,2); pzhan = pzhan - 1; for i = -1 : 2 : 1 j = 0; if x1+i > 0 && x1+i <= row && y1+j > 0 && y1+j <= col && BW(x1+i,y1+j) == BW(x1,y1) && R(x1+i,y1+j) ~= R(x1,y1) R(x1+i,y1+j) = R(x1,y1); counter = counter + 1; pzhan = pzhan + 1; zhan(pzhan,1) = x1 + i; zhan(pzhan,2) = y1 + j; end end for j = -1 : 2 : 1 i = 0; if x1+i > 0 && x1+i <= row && y1+j > 0 && y1+j <= col && BW(x1+i,y1+j) == BW(x1,y1) && R(x1+i,y1+j) ~= R(x1,y1) R(x1+i,y1+j) = R(x1,y1); counter = counter + 1; pzhan = pzhan + 1; zhan(pzhan,1) = x1 + i; zhan(pzhan,2) = y1 + j; end end end end end
三、說明
在基於MATLAB7.11.0(R2010b)平台調用函數模塊fsrRegiongrow時,MATLAB會彈出如下警告
??? Maximum recursion limit of 500 reached. Use set(0,'RecursionLimit',N)
to change the limit. Be aware that exceeding your available stack space can crash MATLAB and/or your computer.
Error in ==> fsrRegiongrow
上述警告表示遞歸次數超出了MATLAB默認值,也就是說待處理的感興趣連通區域像素個數太多(大於500),此時用戶可以嘗試通過提示的set函數來修改函數遞歸次數,但是本文通過測試發現如果遞歸次數超出1591時(不同的平台該值可能不同),MATLAB軟件會自動立即關閉。總之,大量的遞歸調用會建立函數的副本,消耗大量的時間和內存,但是遞歸可以使得程序結構清晰易懂,所以本文給出函數遞歸的方法來實現區域生長只是提供一個思路,如果待處理的連通區域像素個數很多,調用fsrRegiongrow1函數就可以了!fsrRegiongrow1函數模塊是在堆上創建棧數組模擬棧的先進后出思想來實現的,可以快速的實現區域生長。
四、實驗結果