細化技術:把一個平面區域簡化成圖的結構形狀表示法
骨架:一種細化結構,它是目標的重要拓撲描述,具備很是普遍的應用。在圖像識別或數據壓縮時,常常用細化結構。
例如:在識別字符以前,每每要先對字符做細化處理,求出字符的細化結構。
細化的做用:目的將圖像的骨架提取出來的同時,保持圖像細小部分的連通性,對被處理的圖像進行細化有助於突出形狀特色和減小冗餘信息量。算法
細化算法:採起逐次去除邊界的方法進行的,不能破化圖像的連通性。
一般選擇一組結構元素對,不斷在這些結構對中循環,若是所得結果再也不變化,則終止迭代過程,隨着迭代的進行,集合也不斷細化。
結構對的選擇:僅受結構元素不相交的限制(不一樣的結構對),事實上,咱們可使用同一個結構對,即在不斷重複的迭代細化過程使用同一個結構對。
細化知足的條件:
1.在細化的過程當中,圖像應該有規律地縮小;
2.在圖像逐步縮小的過程當中,應當使圖像的連通性質保持不變。編程
咱們對一副二值圖像進行骨架提取,就是刪除不須要的輪廓點,只保留其骨架點。假設一個像素點,咱們定義該點爲p1,則它的八鄰域點p2->p9位置以下圖所示,該算法考慮p1點鄰域的實際狀況,以便決定是否刪除p1點。假設咱們處理的爲二值圖像,背景爲黑色,值爲0,要細化的前景物體像素值爲1。測試
算法的描述以下。spa
首先複製源圖像到目地圖像,而後創建一個臨時圖像,接着執行下面操做:.net
1. 把目地圖像複製給臨時圖像,對臨時圖像進行一次掃描,對於不爲0的點,若是知足如下四個條件,則在目地圖像中刪除該點(就是設置該像素爲0),這裏p2,…,p9是對應位置的像素灰度值(其爲1或者0)。3d
a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6code
大於等於2會保證p1點不是端點或孤立點,由於刪除端點和孤立點是不合理的,小於等於6保證p1點是一個邊界點,而不是一個內部點。等於0時候,周圍沒有等於1的像素,因此p1爲孤立點,等於1的時候,周圍只有1個灰度等於1的像素,因此是端點(注:端點是周圍有且只能有1個值爲1的像素)。blog
b. p2->p9的排列順序中,01模式的數量爲1,好比下面的圖中,有p2p3 => 01, p6p7=>01,因此該像素01模式的數量爲2。get
之因此要01模式數量爲1,是要保證刪除當前像素點後的連通性。好比下面的圖中,01模式數量大於1,若是刪除當前點p1,則連通性不能保證。圖像處理
c. P2*p4*p6 = 0
d. p4*p6*p8 = 0
在第一次子迭代中,只是移去東南的邊界點,而不考慮西北的邊界點,注意p4,p6出現了2次,就是說它們有一個爲0,則c,d就知足。
2. 接下來,把目地圖像再次複製到臨時圖像,接着對臨時圖像進行一次掃描,若是不爲0的點它的八鄰域知足如下4個條件,則在目地圖像中刪除該點(就是設置該像素爲0)
a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6
b. p2->p9的排列順序中,01模式的數量(這裏假設二值圖非零值爲1)爲1。
c. p2*p4*p8 = 0
d. p2*p6*p8 = 0
第二次迭代則相反,會移去西北的邊界點,注意p2,p8出現了2次,就是說它們有一個爲0,則c,d就知足。
執行完上面兩個步驟後,就完成了一次細化算法,咱們能夠屢次迭代執行上述過程,獲得最終的骨架圖。
1.首先對圖像進行二值化,白色爲255,黑色爲0。
2.設置一個3*3的領域S模板。
3.S模板中各個位置上的取值取決於模板所對應圖像中不一樣位置的像素,若是S模板某一個位置上所對應的像素值爲白,模板上該位置賦爲0,不然賦爲1。
4.循環全部的前景像素點,對符合以下條件的像素點標記爲刪除:
5.循環全部的前景像素點,對符合以下條件的像素點標記爲刪除:
6.若是沒有知足的點,則結束細化過程。
下面:
Image_Use爲目標圖像:高120,長180,處理時不考慮邊界(四邊)
//背景爲黑色,值爲0,要細化的前景物體像素值爲1。 int temp[3][3]; int count = 0,flinsh_flag = 0; while(1){ flinsh_flag = 0; for(int i = 1;i<120-1;i++) { for(int j = 1;j<180-1;j++) { if(Image_Use[i][j] == 255) continue; //第一步初始化模板 memset(temp, 0, sizeof(temp)); count = 0; //第二步根據模板所對應的像素點,對模板進行賦值 //若是S模板某一個位置上所對應的像素值爲白,模板上該位置賦爲0,不然賦爲1 if(Image_Use[i][j-1] == 0) temp[1][0] = 1; if(Image_Use[i][j+1] == 0) temp[1][2] = 1; if(Image_Use[i-1][j-1] == 0) temp[0][0] = 1; if(Image_Use[i-1][j+1] == 0) temp[0][2] = 1; if(Image_Use[i-1][j] == 0) temp[0][1] = 1; if(Image_Use[i+1][j-1] == 0) temp[2][0] = 1; if(Image_Use[i+1][j+1] == 0) temp[2][2] = 1; if(Image_Use[i+1][j] == 0) temp[2][1] = 1; // for(int x = 0;x<3;x++) for(int y = 0;y<3;y++) { if(x == 1 && y == 1) continue; if(temp[x][y] == 1) count ++; } if(count>=2&&count<=6) { int ap = 0; if (temp[0][1] == 0 && temp[0][2] == 1) ++ap; if (temp[0][2] == 0 && temp[1][2] == 1) ++ap; if (temp[1][2] == 0 && temp[2][2] == 1) ++ap; if (temp[2][2] == 0 && temp[2][1] == 1) ++ap; if (temp[2][1] == 0 && temp[2][0] == 1) ++ap; if (temp[2][0] == 0 && temp[1][0] == 1) ++ap; if (temp[1][0] == 0 && temp[0][0] == 1) ++ap; if (temp[0][0] == 0 && temp[0][1] == 1) ++ap; if(ap == 1&&((temp[0][1]*temp[1][2]*temp[2][1])== 0)&&((temp[1][2]*temp[2][1]*temp[1][0])== 0)) { Image_Use[i][j] = 255; flinsh_flag ++; } } } } if(flinsh_flag == 0) { break; } flinsh_flag = 0; for(int i = 1;i<120-1;i++) { for(int j = 1;j<180-1;j++) { if(Image_Use[i][j] == 255) continue; //第一步初始化模板 memset(temp, 0, sizeof(temp)); count = 0; //第二步根據模板所對應的像素點,對模板進行賦值 //若是S模板某一個位置上所對應的像素值爲白,模板上該位置賦爲0,不然賦爲1 if(Image_Use[i][j-1] == 0) temp[1][0] = 1; if(Image_Use[i][j+1] == 0) temp[1][2] = 1; if(Image_Use[i-1][j-1] == 0) temp[0][0] = 1; if(Image_Use[i-1][j+1] == 0) temp[0][2] = 1; if(Image_Use[i-1][j] == 0) temp[0][1] = 1; if(Image_Use[i+1][j-1] == 0) temp[2][0] = 1; if(Image_Use[i+1][j+1] == 0) temp[2][2] = 1; if(Image_Use[i+1][j] == 0) temp[2][1] = 1; // for(int x = 0;x<3;x++) for(int y = 0;y<3;y++) { if(x == 1 && y == 1) continue; if(temp[x][y] == 1) count ++; } if(count>=2&&count<=6) { int ap = 0; if (temp[0][1] == 0 && temp[0][2] == 1) ++ap; if (temp[0][2] == 0 && temp[1][2] == 1) ++ap; if (temp[1][2] == 0 && temp[2][2] == 1) ++ap; if (temp[2][2] == 0 && temp[2][1] == 1) ++ap; if (temp[2][1] == 0 && temp[2][0] == 1) ++ap; if (temp[2][0] == 0 && temp[1][0] == 1) ++ap; if (temp[1][0] == 0 && temp[0][0] == 1) ++ap; if (temp[0][0] == 0 && temp[0][1] == 1) ++ap; if(ap == 1&&((temp[0][1]*temp[1][2]*temp[1][0])== 0)&&((temp[0][1]*temp[2][1]*temp[1][0]) == 0)) { Image_Use[i][j] = 255; flinsh_flag++; } } } } if(flinsh_flag == 0) { break; } }
粗化處理能夠對圖像的二值化補集進行細化後獲得。
refer: