[函數名稱]

  二值圖像細化算法      WriteableBitmap ThinningProcess(WriteableBitmap src)

[算法說明]

  圖像細化(Image Thinning),一般指二值圖像的骨架化(Image Skeletonization)的一種操作運算。所謂的細化就是經過一層層的剝離,從原來的圖中去掉一些點,但仍要保持原來的形狀,直到得到圖像的骨架。骨架,可以理解為圖象的中軸。

  細化算法有很多,我們這裡介紹一種二值圖像的快速細化算法—Zhang 細化算法,該算法是Zhang1984年提出。

  算法過程如下:

  1,設二值圖像中0為背景,1為目標。目標像素的8鄰域如下圖所示:

 2,對於當前點P1,我們判斷以下7個條件:

  (1)p1=1;

 (2)2<=N(p1)<=6;

  (3)T(p1)=1;

  (4)p2*p4*p6=0;

  (5)p4*p6*p8=0;

  (6)p2(p4*p8=0;

  (7)p2*p6*p8=0;

  其中,N(p1)表示p1像素的8鄰域像素中目標像素的個數;T(p1)表示像素p1-p9中,像素值從0變換到1的次數。

  對於p1,如果滿足(1)&(2)&(3)&[(4)&(5)||(6)&(7)]時,將p1像素標記為背景像素0

  將以上判斷作為1次迭代過程進行迭代,如果當前圖像中不存在可以標記為背景的像素p1時,迭代結束,細化完成。

  Zhang快速細化算法有一個缺點:細化後的圖像不一定是單像素的骨架。

  本文代碼中以1為背景,0為目標。

 

[csharp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. [函數代碼]  
  2.         /// <summary>  
  3.         /// Zhang's fast thinning process for binary image.  
  4.         /// </summary>  
  5.         /// <param name="src">The source image.</param>  
  6.         /// <returns></returns>  
  7.         public static WriteableBitmap ThinningProcess(WriteableBitmap src)////二值圖像細化(Zhang快速細化算法)  
  8.         {  
  9.             if (src != null)  
  10.             {  
  11.                 int w = src.PixelWidth;  
  12.                 int h = src.PixelHeight;  
  13.                 WriteableBitmap srcImage = new WriteableBitmap(w, h);  
  14.                 byte[] temp = src.PixelBuffer.ToArray();  
  15.                 byte[] tempMask = (byte[])temp.Clone();  
  16.                 int[,] srcBytes = new int[w, h];  
  17.                 for (int j = 0; j < h; j++)  
  18.                 {  
  19.                     for (int i = 0; i < w ; i++)  
  20.                     {  
  21.                         srcBytes[i, j] = (tempMask[i * 4 + j * w * 4] * 0.114 + tempMask[i * 4 + 1 + j * w * 4] * 0.587 + tempMask[i * 4 + 2 + j * w * 4] * 0.299 < 128 ? 0 : 1);  
  22.                     }  
  23.                 }  
  24.                 Thinning(ref srcBytes, w, h);  
  25.                 for (int j = 0; j < h; j++)  
  26.                 {  
  27.                     for (int i = 0; i < w; i++)  
  28.                     {  
  29.                         temp[i * 4 + j * w * 4] = temp[i * 4 + 1 + j * w * 4] = temp[i * 4 + 2 + j * w * 4] = (byte)(srcBytes[i, j] * 255);  
  30.                     }  
  31.                 }  
  32.                 Stream sTemp = srcImage.PixelBuffer.AsStream();  
  33.                 sTemp.Seek(0, SeekOrigin.Begin);  
  34.                 sTemp.Write(temp, 0, w * 4 * h);  
  35.                 return srcImage;  
  36.             }  
  37.             else  
  38.             {  
  39.                 return null;  
  40.             }  
  41.         }  
  42.         private static void Thinning(ref int[,] srcBytes,int w,int h)  
  43.         {  
  44.             int[] srcTemp;  
  45.             int countNumber;  
  46.             do  
  47.             {  
  48.                 countNumber = 0;  
  49.                 for (int y = 1; y < h - 1; y++)  
  50.                 {  
  51.                     for (int x = 1; x < w - 1; x++)  
  52.                     {  
  53.                         srcTemp = new int[9] { srcBytes[x, y], srcBytes[x - 1, y - 1], srcBytes[x, y - 1], srcBytes[x + 1, y - 1], srcBytes[x + 1, y], srcBytes[x + 1, y + 1], srcBytes[x, y + 1], srcBytes[x - 1, y + 1], srcBytes[x - 1, y] };  
  54.                         if (srcBytes[x, y] != 1)  
  55.                         {  
  56.                             if (CountN(srcTemp) >= 2 && CountN(srcTemp) <= 6)  
  57.                             {  
  58.                                 if (CountT(srcTemp) == 1)  
  59.                                 {  
  60.                                     if (srcBytes[x, y - 1] * srcBytes[x + 1, y] * srcBytes[x, y + 1] == 0)  
  61.                                     {  
  62.                                         if (srcBytes[x - 1, y] * srcBytes[x + 1, y] * srcBytes[x, y + 1] == 0)  
  63.                                         {  
  64.                                             srcBytes[x, y] = (byte)1;  
  65.                                             countNumber++;  
  66.                                         }  
  67.                                     }  
  68.                                     else  
  69.                                     {  
  70.                                         if (srcBytes[x, y - 1] * srcBytes[x + 1, y] * srcBytes[x - 1, y] == 0)  
  71.                                         {  
  72.                                             if (srcBytes[x, y - 1] * srcBytes[x, y + 1] * srcBytes[x - 1, y] == 0)  
  73.                                             {  
  74.                                                 srcBytes[x, y] = (byte)1;  
  75.                                                 countNumber++;  
  76.                                             }  
  77.                                         }  
  78.                                     }  
  79.                                 }  
  80.                             }  
  81.                         }  
  82.                     }  
  83.                 }  
  84.             } while (countNumber != 0);  
  85.         }  
  86.         private static int CountN(params int[] src)  
  87.         {  
  88.             int count = 0;  
  89.             for (int i = 0; i < src.Length; i++)  
  90.             {  
  91.                 if (src[i] == 0)  
  92.                 {  
  93.                     count++;  
  94.                 }  
  95.             }  
  96.             return count;  
  97.         }  
  98.         private static int CountT(params int[] src)  
  99.         {  
  100.             int count = 0;  
  101.             for (int i = 1; i < src.Length; i++)  
  102.             {  
  103.                 if (src[i] == 1 && src[i - 1] == 0)  
  104.                 {  
  105.                     count++;  
  106.                 }  
  107.             }  
  108.             if (src[src.Length - 1] == 0 && src[0] == 1)  
  109.             {  
  110.                 count++;  
  111.             }  
  112.             return count;  
  113.         }  

 

 

[圖像效果]

arrow
arrow
    全站熱搜

    Rocky 發表在 痞客邦 留言(0) 人氣()