二值形態學——腐蝕與膨脹 及 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     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

 


免責聲明!

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



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