由于最近项目需要,粗略的研究了一下不同的细化算法。https://www.cnblogs.com/mikewolf2002/p/3327318.html 这位大哥的博客里面有一系列的细化算法,还附带原理,可以看看。
我这里就贴一下不同细化算法的结果图吧
Rosenfeld
ZhangSuen
Thining-Algorithm
Pavlidis
Linear Skeletons from Square Cupboards
最后一个是我自己理解后修改的代码:
满足的条件可以总结为:
(1)为前景点
(2)为边界点
(3)端点不能删
(4)孤立点不能删
(5)连通性不变
(6)先从边缘删
附一下代码:
//8邻域的偏移量
int offset[9][2] = { {0,0},{1,0},{1,-1},{0,-1},{-1,-1},
{-1,0},{-1,1},{0,1},{1,1} };
//四邻域的偏移量
int n_odd[8] = { 1, 3, 5, 7 };
int px, py;
int b[9]; //3*3格子的灰度信息
int condition[6]; //1-6个条件是否满足
int counter; //移去像素的数量
int i, x, y, copy, sum;
int width, height;
width = n_X;
height = n_Y;
double *img = outline_childs;
int step = n_X;
do
{
counter = 0;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
//前面标记为删除的像素,我们置其相应邻域值为-1
for (i = 0; i < 9; i++)
{
b[i] = 0;
px = x + offset[i][0];
py = y + offset[i][1];
if (px >= 0 && px < width && py >= 0 && py < height)
{
// printf("%d\n", img[py*step+px]);
if (img[py*step + px] >0)
{
b[i] = 1;
}
else if (img[py*step + px] == -1)
{
b[i] = -1;
}
}
}
for (i = 0; i < 6; i++)
{
condition[i] = 0;
}
//条件1,是前景点
if (b[0] == 1) condition[0] = 1;
//条件2,是边界点
sum = 0;
for (i = 0; i < 4; i++)
{
sum = sum + 1 - abs(b[n_odd[i]]);
}
if (sum >= 1) condition[1] = 1;
//条件3, 端点不能删除
//端点不是只有等于1才是端点
sum = 0;
for (i = 1; i <= 8; i++)
{
if(b[i]>0)
sum = sum + /*abs*/(b[i]);
}
if (sum >= 4) condition[2] = 1;
if (sum == 2)
{
if ((b[4] == 1 && b[3] == 1) || (b[2] == 1 && b[3] == 1)
|| (b[4] == 1 && b[5] == 1) || (b[5] == 1 && b[6] == 1)
|| (b[6] == 1 && b[7] == 1) || (b[7] == 1 && b[8] == 1)
|| (b[8] == 1 && b[1] == 1) || (b[1] == 1 && b[2] == 1))
condition[2] = 0;
else
condition[2] = 1;
}
if (sum == 3)
{
if ((b[4] == 1 && b[3] == 1&& b[2] == 1 )
|| (b[4] == 1 && b[5] == 1 && b[6] == 1)
|| (b[6] == 1 && b[7] == 1 && b[8] == 1)
|| (b[8] == 1 && b[1] == 1 && b[2] == 1))
condition[2] = 0;
else
condition[2] = 1;
}
//条件4, 孤立点不能删除
sum = 0;
for (i = 1; i <= 8; i++)
{
if (b[i] == 1) sum++;
}
if (sum >=2) condition[3] = 1;
//条件5, 连通性检测
if (func_nc8(b) == 1) condition[4] = 1;
//条件6,宽度为2的骨架只能删除1边
sum = 0;
for (i = 1; i <= 8; i++)
{
if (b[i] != -1)
{
sum++;
}
else
{
copy = b[i];
b[i] = 0;
if (func_nc8(b) == 1) sum++;
b[i] = copy;
}
}
if (sum == 8) condition[5] = 1;
if (condition[0] && condition[1] && condition[2] && condition[3] && condition[4] && condition[5])
{
img[y*step + x] = -1; //可以删除,置位GRAY,GRAY是删除标记,但该信息对后面像素的判断有用
counter++;
//printf("----------------------------------------------\n");
//PrintMat(dst);
}
}
}
if (counter != 0)
{
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
if (img[y*step + x] == -1)
img[y*step + x] = 0;
}
}
}
} while (counter != 0);