图像轮廓搜索是图像处理中很基本很常用的算法,基于边缘跟踪的轮廓搜索是轮廓提取算法中较为高效的一种搜索算法。具体如下:
(1) 从左到右,从上往下依次搜索非零点
(2) 搜索到非零点并标记当前非零点,对当前非零点的八邻域按照逆时针进行搜索下一个非零点
(3)若能够搜索到非零点,则重复步骤二,指导搜索完当前轮廓
(4)当前轮廓搜索完毕,则返回(1)进行下一个轮廓进行搜索,如此重复直到所有的轮廓搜索完毕
void fetchContour(uchar *ptr, int step, int x, int y,point_t *points,int *count)
{
int deltas[16];
int s = 0, s_end = 0;
int cur_x = x;
int cur_y = y;
int n = 0;
uchar *i0 = ptr, *i1, *i3, *i4 = 0;
const uchar nbd = 2;
const uchar nbd_right = 3;
POS_INDEX(deltas, step, 1);
memcpy(deltas + 8, deltas, 8 * sizeof(deltas[0]));
s_end = s = 4;
//寻找该点周围非零点
do
{
s = (s - 1) & 7;
i1 = i0 + deltas[s];
if (*i1 != 0)
break;
} while (s != s_end);
//如果是孤立点,将其标记为3
if (s == s_end)
{
*i0 = nbd_right;
}
else//非孤立点则对该点的边缘进行跟踪
{
i3 = i0;//i3为当前点的索引
cur_x = x;
cur_y = y;
for (;;)
{
points[n].x = cur_x;
points[n].y = cur_y;
n++;
s_end = s;
//寻找i3周围不为零的点
for (;;)
{
i4 = i3 + deltas[++s];
if (*i4 != 0)
break;
}
s &= 7;
//获取当前非零点的位置
cur_x = cur_x + codeDeltas[s][0];
cur_y = cur_y + codeDeltas[s][1];
//右边边界
if ((unsigned)(s - 1) < (unsigned)s_end)
*i3 = nbd_right;
//其他边界
else if (*i3 == 1)
*i3 = nbd;
//回到起始位置
if (i4 == i0 && i3 == i1)
break;
//更新i3的位置
i3 = i4;
//s索引向当前搜索到点的位置,方便下一次搜索
s = (s + 4) & 7;
}
}
*count = n;
return;
}
for (y = 1; y < height; y++)
{
for (x = 1; x < width; x++)
{
//寻找每一行的非零元
for (; x < width && (p = img -> pix[y * width + x]) == prev; x++);
if (x >= width)
break;
if ((!(prev == 0 && p == 1)) || inner)
{
if (p == 2) inner = 1;
else if (p == 3) inner = 0;
prev = p;
continue;
}
inner = 1;
count = 0;
fetchContour(&(img -> pix[y * width + x]), step, x, y,points,&count);
p = img -> pix[y * width + x];
if (p == 2) inner = 1;
else if (p == 3) inner = 0;
}
prev = 0;
inner = 0;
}
如有不当之处,望指教,谢谢!