上理論:
Hilditch 細化算法的步驟為:
對圖像從左向右從上向下迭代每個像素,是為一個迭代周期。在每個迭代周期中,對於每一個像素p,如果它同時滿足6個條件,則標記它。在當前迭代周期結束時,則把所有標記的像素的值設為背景值。如果某次迭代周期中不存在標記點(即滿足6個條件的像素),則算法結束。假設背景值為0,前景值為1,則:
6個條件為:
(I):p 為1,即p不是背景;
(2):x1,x3,x5,x7不全部為1(否則把p標記刪除,圖像空心了);
(3):x1~x8 中,至少有2個為1(若只有1個為1,則是線段的端點。若沒有為1的,則為孤立點);
(4):p的8連通聯結數為1;
聯結數指在像素p的3*3鄰域中,和p連接的圖形分量的個數:
(5)假設x3已經標記刪除,那麼當x3為0時,p的8聯通聯結數為1;
(6)假設x5已經標記刪除,那麼當x5為0時,p的8聯通聯結數為1。
我上一個自己寫的代碼
[csharp]
/// <summary>
/// Hilditch細化算法
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private int[,] ThinnerHilditch(int[,] input)
{
int lWidth = input.GetLength(0);
int lHeight = input.GetLength(1);
bool IsModified = true;
int Counter = 1;
int[] nnb = new int[9];
//去掉邊框像素
for (int i = 0; i < lWidth; i++)
{
input[i, 0] = 0;
input[i, lHeight - 1] = 0;
}
for (int j = 0; j < lHeight; j++)
{
input[0, j] = 0;
input[lWidth - 1, j] = 0;
}
do
{
Counter++;
IsModified = false;
int[,] nb = new int[3, 3];
for (int i = 1; i < lWidth; i++)
{
for (int j = 1; j < lHeight; j++)
{
//條件1必須為黑點
if (input[i, j] != 1)
{
continue;
}
//取3*3領域
for (int m = 0; m < 3; m++)
{
for (int n = 0; n < 3; n++)
{
nb[m, n] = input[i - 1 + m, j - 1 + n];
}
}
//復制
nnb[0] = nb[2, 1]==1?0:1;
nnb[1] = nb[2, 0]==1?0:1;
nnb[2] = nb[1, 0]==1?0:1;
nnb[3] = nb[0, 0]==1?0:1;
nnb[4] = nb[0, 1]==1?0:1;
nnb[5] = nb[0, 2]==1?0:1;
nnb[6] = nb[1, 2]==1?0:1;
nnb[7] = nb[2, 2]==1?0:1;
// 條件2:p0,p2,p4,p6 不皆為前景點
if (nnb[0] == 0 && nnb[2] == 0 && nnb[4] == 0 && nnb[6] == 0)
{
continue;
}
// 條件3: p0~p7至少兩個是前景點
int iCount = 0;
for (int ii = 0; ii < 8; ii++)
{
iCount += nnb[ii];
}
if (iCount > 6) continue;
// 條件4:聯結數等於1
if (DetectConnectivity(nnb) != 1)
{
continue;
}
// 條件5: 假設p2已標記刪除,則令p2為背景,不改變p的聯結數
if (input[i, j - 1] == -1)
{
nnb[2] = 1;
if (DetectConnectivity(nnb) != 1)
continue;
nnb[2] = 0;
}
// 條件6: 假設p4已標記刪除,則令p4為背景,不改變p的聯結數
if (input[i, j + 1] == -1)
{
nnb[6] = 1;
if (DetectConnectivity(nnb) != 1)
continue;
nnb[6] = 0;
}
input[i, j] = -1;
IsModified = true;
}
}
for (int i = 0; i < lWidth; i++)
{
for (int j = 0; j < lHeight; j++)
{
if (input[i, j] == -1)
{
input[i, j] = 0;
}
}
}
} while (IsModified);
return input;
}
/// <summary>
/// Hilditch細化算法 www.2cto.com
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private int[,] ThinnerHilditch(int[,] input)
{
int lWidth = input.GetLength(0);
int lHeight = input.GetLength(1);
bool IsModified = true;
int Counter = 1;
int[] nnb = new int[9];
//去掉邊框像素
for (int i = 0; i < lWidth; i++)
{
input[i, 0] = 0;
input[i, lHeight - 1] = 0;
}
for (int j = 0; j < lHeight; j++)
{
input[0, j] = 0;
input[lWidth - 1, j] = 0;
}
do
{
Counter++;
IsModified = false;
int[,] nb = new int[3, 3];
for (int i = 1; i < lWidth; i++)
{
for (int j = 1; j < lHeight; j++)
{
//條件1必須為黑點
if (input[i, j] != 1)
{
continue;
}
//取3*3領域
for (int m = 0; m < 3; m++)
{
for (int n = 0; n < 3; n++)
{
nb[m, n] = input[i - 1 + m, j - 1 + n];
}
}
//復制
nnb[0] = nb[2, 1]==1?0:1;
nnb[1] = nb[2, 0]==1?0:1;
nnb[2] = nb[1, 0]==1?0:1;
nnb[3] = nb[0, 0]==1?0:1;
nnb[4] = nb[0, 1]==1?0:1;
nnb[5] = nb[0, 2]==1?0:1;
nnb[6] = nb[1, 2]==1?0:1;
nnb[7] = nb[2, 2]==1?0:1;
// 條件2:p0,p2,p4,p6 不皆為前景點
if (nnb[0] == 0 && nnb[2] == 0 && nnb[4] == 0 && nnb[6] == 0)
{
continue;
}
// 條件3: p0~p7至少兩個是前景點
int iCount = 0;
for (int ii = 0; ii < 8; ii++)
{
iCount += nnb[ii];
}
if (iCount > 6) continue;
// 條件4:聯結數等於1
if (DetectConnectivity(nnb) != 1)
{
continue;
}
// 條件5: 假設p2已標記刪除,則令p2為背景,不改變p的聯結數
if (input[i, j - 1] == -1)
{
nnb[2] = 1;
if (DetectConnectivity(nnb) != 1)
continue;
nnb[2] = 0;
}
// 條件6: 假設p4已標記刪除,則令p4為背景,不改變p的聯結數
if (input[i, j + 1] == -1)
{
nnb[6] = 1;
if (DetectConnectivity(nnb) != 1)
continue;
nnb[6] = 0;
}
input[i, j] = -1;
IsModified = true;
}
}
for (int i = 0; i < lWidth; i++)
{
for (int j = 0; j < lHeight; j++)
{
if (input[i, j] == -1)
{
input[i, j] = 0;
}
}
}
} while (IsModified);
return input;
}
希望對大家有用。
摘自 aofengdaxia