【數字圖像處理】圖像細化處理


 

圖像細化

細化技術:把一個平面區域簡化成圖的結構形狀表示法
骨架:一種細化結構,它是目標的重要拓撲描述,具有非常廣泛的應用。在圖像識別或數據壓縮時,經常用細化結構。
例如:在識別字符之前,往往要先對字符作細化處理,求出字符的細化結構。
細化的作用:目的將圖像的骨架提取出來的同時,保持圖像細小部分的連通性,對被處理的圖像進行細化有助於突出形狀特點和減少冗余信息量。

 

細化算法

細化算法:采取逐次去除邊界的方法進行的,不能破化圖像的連通性。
通常選擇一組結構元素對,不斷在這些結構對中循環,如果所得結果不再變化,則終止迭代過程,隨着迭代的進行,集合也不斷細化。
結構對的選擇:僅受結構元素不相交的限制(不同的結構對),事實上,我們可以使用同一個結構對,即在不斷重復的迭代細化過程使用同一個結構對。
細化滿足的條件:
1.在細化的過程中,圖像應該有規律地縮小;
2.在圖像逐步縮小的過程中,應當使圖像的連通性質保持不變。

 

 

 

 

細化算法過程詳解

      我們對一副二值圖像進行骨架提取,就是刪除不需要的輪廓點,只保留其骨架點。假設一個像素點,我們定義該點為p1,則它的八鄰域點p2->p9位置如下圖所示,該算法考慮p1點鄰域的實際情況,以便決定是否刪除p1點。假設我們處理的為二值圖像,背景為黑色,值為0,要細化的前景物體像素值為1。

 

image

算法的描述如下。

首先復制源圖像到目地圖像,然后建立一個臨時圖像,接着執行下面操作:

1. 把目地圖像復制給臨時圖像,對臨時圖像進行一次掃描,對於不為0的點,如果滿足以下四個條件,則在目地圖像中刪除該點(就是設置該像素為0),這里p2,…,p9是對應位置的像素灰度值(其為1或者0)。

   a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6

    大於等於2會保證p1點不是端點或孤立點,因為刪除端點和孤立點是不合理的,小於等於6保證p1點是一個邊界點,而不是一個內部點。等於0時候,周圍沒有等於1的像素,所以p1為孤立點,等於1的時候,周圍只有1個灰度等於1的像素,所以是端點(注:端點是周圍有且只能有1個值為1的像素)。

image

 

   b. p2->p9的排列順序中,01模式的數量為1,比如下面的圖中,有p2p3 => 01, p6p7=>01,所以該像素01模式的數量為2。

image

     之所以要01模式數量為1,是要保證刪除當前像素點后的連通性。比如下面的圖中,01模式數量大於1,如果刪除當前點p1,則連通性不能保證。

image

    c. P2*p4*p6 = 0

    d. p4*p6*p8 = 0

image

      在第一次子迭代中,只是移去東南的邊界點,而不考慮西北的邊界點,注意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

image

第二次迭代則相反,會移去西北的邊界點,注意p2,p8出現了2次,就是說它們有一個為0,則c,d就滿足。

執行完上面兩個步驟后,就完成了一次細化算法,我們可以多次迭代執行上述過程,得到最終的骨架圖。

 


細化實例編程

1.首先對圖像進行二值化,白色為255,黑色為0。
2.設置一個3*3的領域S模板。
3.S模板中各個位置上的取值取決於模板所對應圖像中不同位置的像素,如果S模板某一個位置上所對應的像素值為白,模板上該位置賦為0,否則賦為1。
4.循環所有的前景像素點,對符合如下條件的像素點標記為刪除:

  • 2 ≤ N(p1) ≤ 6——N(p1)表示跟P1相鄰的8個像素點中,為前景像素點的個數
  • S(P1) = 1——S(P1)表示將p2-p9-p2之間按序前后分別成對值為0、1的個數
  • P2 * P4 * P6 = 0
  • P4 * P6 * P8 = 0

5.循環所有的前景像素點,對符合如下條件的像素點標記為刪除:

  •  2 ≤ N(p1) ≤ 6——N(p1)表示跟P1相鄰的8個像素點中,為前景像素點的個數
  •  S(P1) = 1——S(P1)表示將p2-p9-p2之間按序前后分別成對值為0、1的個數
  •  P2 * P4 * P8 = 0
  • P2 * P6 * P8 = 0

 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:

圖像處理細化算法

C/C++ 圖像處理(19)------細化算法


免責聲明!

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



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