原理:
参照冈萨雷斯数字图像处理英文版第11章第一小节。
C实现代码如下:
static uint8_t* enlarge_gray_img(uint8_t* img, int w, int h, int scale, int pad_value)
{
uint32_t dst_row_bytes;
uint32_t src_row_bytes;
uint32_t src_off;
uint32_t dst_off;
uint8_t* tmp;
int i;
int j;
int nw, nh;
nw = w + scale * 2;
nh = h + scale * 2;
dst_row_bytes = (nw + 3) &~3;
src_row_bytes = (w + 3) & ~3;
tmp = (uint8_t*)malloc(dst_row_bytes * nh);
if (!tmp)
{
return NULL;
}
memset(tmp, pad_value, dst_row_bytes * nh);
dst_off = dst_row_bytes + scale;
src_off = 0;
for (i = 0; i < h; i++)
{
memcpy(tmp + dst_off, img + src_off, w);
src_off += src_row_bytes;
dst_off += dst_row_bytes;
}
return tmp;
}
int moore_boundary_track(uint8_t* gray, int width, int height, _point* boundary)
{
uint32_t row_bytes;
uint32_t off;
int i;
int j;
uint8_t pixel;
int get_first_pt;
int count = 0;
uint8_t* img = enlarge_gray_img(gray, width, height, 1, 255);
if (!img)
{
return 0;
}
width += 2;
height += 2;
off = 0;
row_bytes = (width + 3) & ~3;
//get first point
off = row_bytes;
get_first_pt = 0;
for (i = 1; i < height; i++)
{
for (j = 1; j < width; j++)
{
pixel = img[off + j];
if (pixel == 0)
{
get_first_pt = 1;
break;
}
}
if (get_first_pt)
{
break;
}
off += row_bytes;
}
if (get_first_pt)
{
_point start;
_point c;
_point b;
_point cur;
_point direct[8] = { { -1, 0 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 0 }, { 0, 1 }, { -1, 1 } };
int dir;
int return_start;
off = i * row_bytes + j;
return_start = 0;
b.x = j, b.y = i;
c.x = j - 1, c.y = i;
start = b;
dir = 0;
count = 0;
while (!return_start)
{
dir++;
cur = c;
for (i = 0; i < 8; i++)
{
if (dir == 8)
{
dir = 0;
}
cur.x = b.x + direct[dir].x;
cur.y = b.y + direct[dir].y;
pixel = img[cur.y*row_bytes + cur.x];
if (pixel == 0)
{
break;
}
c = cur;
dir++;
}
if (i == 8)
{
return 0;
}
b = cur;
if (b.x == start.x && b.y == start.y)
{
return_start = 1;
}
boundary[count] = b;
boundary[count].x -= 1;
boundary[count].y -= 1;
count++;
switch (dir)
{
case 0:
case 1:
dir = 6;
break;
case 2:
case 3:
dir = 0;
break;
case 4:
case 5:
dir = 2;
break;
case 6:
case 7:
dir = 4;
default:
break;
}
}
}
return count;
}
测试效果如下: