二值形態學——腐蝕與膨脹 及 C語言代碼實現
參考文獻:數字圖像處理(第三版) 何東健 西安電子科技大學出版社
二值形態學中的運算對象是集合, 但實際運算中, 當涉及兩個集合時並不把它們看作是互相對等的。 一般設A為圖像集合, S為結構元素, 數學形態學運算是用S對A進行操作。 結構元素本身也是一個圖像集合, 不過通常其尺寸要比目標圖像小得多。 對結構元素可指定一個原點, 將其作為結構元素參與形態學運算的參考點。 原點可包含在結構元素中, 也可不包含在結構元素中, 但運算的結果常不相同。 以下用黑點代表值為1的區域, 白點代表值為0的區域, 運算對於值為1的區域進行。
1.腐蝕
腐蝕是一種最基本的數學形態學運算。 對給定的目標圖像X和結構元素S, 將S在圖像上移動, 則在每一個當前位置x, S+x只有3種可能的狀態, 如下圖所示:
第(1)種情形說明S+x與X相關;
第(2)種情形說明S+x與X不相關;
第(3)種情形說明S+x與X只是部分相關。
因而滿足(1)式的點x的全體元素,稱該點集為S對X的腐蝕(簡稱腐蝕, 也稱X用S腐蝕),記為。
腐蝕也可以用集合的方式定義:
該式表明, X用S腐蝕的結果是所有使S平移x後仍在X中的x的集合。 換句話說, 用S來腐蝕X得到的集合是S完全包含在X中時S的原點位置的集合。
腐蝕在數學形態學運算中的作用是消除物體邊界點、 去除小於結構元素的物體、 清除兩個物體間的細小連通等。 如果結構元素取3×3的像素塊, 腐蝕將使物體的邊界沿周邊減少1個像素。
“腐蝕”圖解:(腐蝕將圖像(區域)縮小了)
代碼實現:
【註】二值腐蝕基本運算,背景為黑色,目標為白色。
1 //二值腐蝕 2 /*函數參數: 3 a——待腐蝕的圖像 4 b——腐蝕後的結果 5 mat[5][5]——結構元素,我這裏默認設了5*5的大小 6 */ 7 void Bi_Corrosion(Mat &a, Mat &b, int mat[5][5]) 8 { 9 intView Codei, j, k, o; 10 int rows = a.rows; 11 int cols = a.cols*a.channels(); 12 13 bool flag; 14 15 uchar *dst = b.data; 16 uchar *src = a.data; 17 //針對圖像中每一個像素位置,判斷是否結構元素能填入目標內部 18 for(i = 2; i < rows-2; i++) { 19 for(j = 2; j < cols-2; j++) { 20 //判斷結構元素是否可以在當前點填入目標內部,1為可以,0為不可以 21 flag = 1; 22 for(k = -2; k <= 2 && flag; k++) { 23 for(o = -2; o <= 2; o++) { 24 //如果當前結構元素位置為1,判斷與對應圖像上的像素點是否為非0 25 if(mat[k+2][o+2]) { 26 //如果圖像當前像素為0,則沒有擊中該點,不是腐蝕的輸出 27 if(!*(src+(i+k)*cols+j+o)){ 28 flag = 0; break; 29 } 30 } 31 } 32 } 33 *(dst+i*cols+j) = flag ? 255 : 0; 34 } 35 } 36 }
2.膨脹
腐蝕可以看作是將圖像X中每一個與結構元素S全等的子集S+x收縮為點x。 反之, 也可以將X中的每一個點x擴大為S+x, 即膨脹運算, 記為。用集合語言定義膨脹運算的定義形式為:
圖示:
【註意】來看下特殊情況: 用B膨脹後,結果向左平移了;而用B圖像的反射膨脹後位置不變。
對於非對稱結構S,膨脹後會使得原圖錯移,但膨脹不會,總的位置和形狀不變,因此膨脹公式也可以寫做:
對集合X的膨脹也可以看做是對集合X補集的腐蝕的補集具有對偶特性:
腐蝕和膨脹運算與集合運算的關系如下:
代碼實現:
【註】二值膨脹基本運算,背景為黑色,目標為白色。
1 //二值膨脹 2 /*函數參數: 3 a——待腐蝕的圖像 4 b——腐蝕後的結果 5 mat——結構元素 6 */ 7 void Bi_Expansion(Mat &a, Mat &b, int mat[5][5]) { 8 int i, j, k, o; 9 int rows = a.rows; 10 int cols = a.cols*a.channels(); 11 Mat tmp = a.clone(); 12 uchar* src = tmp.data; 13 //膨脹是對圖像中目標補集的腐蝕,因此先求輸入圖像數據的補集 14 for(i = 0; i < rows; i++) 15 for(j = 0; j < cols; j++) 16 *(src+i*cols+j) = 255 - *(src+i*cols+j); 17 //膨脹是結構元素的對稱集對補集的腐蝕,此處求其反射 18 for(i = 0; i < 5; i++) 19 for(j = 0; j <= i; j++) 20 mat[i][j] = mat[j][i]; 21 bool flag; 22 uchar* dst = b.data; 23 //針對圖像中每一個像素位置,判斷是否結構元素能填入目標內部 24 for(i = 2; i < rows-2; i++) { 25 for(j = 2; j < cols-2; j++) { 26 //判斷結構元素是否可以在當前點填入目標內部,1為可以,0為不可以 27 flag = 1; 28 for(k = -2; k <= 2 && flag; k++) { 29 for(o = -2; o <= 2; o++) { 30 //如果當前結構元素位置為1,判斷與對應圖像上的像素點是否為非0 31 if(mat[k+2][o+2]) { 32 if(!*(src+(i+k)*cols+j+o)){//沒擊中 33 flag = 0; break; 34 } 35 } 36 } 37 } 38 *(dst+i*cols+j) = flag ? 255 : 0; 39 } 40 } 41 //用結構元素對稱集對目標補集腐蝕後,還要對結構再求一次補集,才是膨脹結構輸出 42 //賦值結構元素腐蝕漏掉的區域,使原圖像恢復為二值圖像 43 for(i = 0; i < rows; i++) { 44 for(j = 0; j < cols; j++) { 45 *(dst+i*cols+j) = 255 - *(dst+i*cols+j); 46 if(*(dst+i*cols+j) != 255 && *(dst+i*cols+j) != 0) 47 *(dst+i*cols+j) = 0; 48 } 49 } 50 }View Code
二值形態學——腐蝕與膨脹 及 C語言代碼實現