1. 程式人生 > >二值形態學——腐蝕與膨脹 及 C語言代碼實現

二值形態學——腐蝕與膨脹 及 C語言代碼實現

hide 內部 isp 反射 尺寸 恢復 lag pos 參考

參考文獻:數字圖像處理(第三版) 何東健 西安電子科技大學出版社

二值形態學中的運算對象是集合, 但實際運算中, 當涉及兩個集合時並不把它們看作是互相對等的。 一般設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     int
i, 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 }
View Code

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語言代碼實現