原先的八邻域已经写好了,最近在写右圆环时又遇到了八邻域,但是逻辑似乎有些混乱,在此再次记录下八邻域的思路。
八邻域需要在一个固定起点处以一个顺时针或者逆时针的顺序对周围的点进行扫描。在我的程序中,如果在扫描的过程中发现一个白点突变为黑点,则说明找到了新的黑线。此时记录下这个黑点的位置,并将其作为下一个起点,如此往复,直到爬出完整的边界。
以下是在爬取赛道时的八邻域代码:
//记录左边界的数据
int32_t border_location_left[border_length][2]; //记录边界位置
int32_t border_count_left = 0;
int32_t growth_direction_left[border_length]; //记录生长方向
int32_t growth_count_left = 0;
//记录右边界的数据
int32_t border_location_right[border_length][2]; //记录边界位置
int32_t border_count_right = 0;
int32_t growth_direction_right[border_length]; //记录生长方向
int32_t growth_count_right = 0;
void neighborSearch()
{
memset(border_location_left, 0, sizeof(border_location_left));
memset(border_location_right, 0, sizeof(border_location_right));
int32_t neighbor_left[9][2] = {{-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
int32_t neighbor_right[9][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};
border_count_left = 1;
growth_count_left = 1;
border_count_right = 1;
growth_count_right = 1;
//把起点加进去
border_location_left[0][0] = start_point_l[0];
border_location_left[0][1] = start_point_l[1];
border_location_right[0][0] = start_point_r[0];
border_location_right[0][1] = start_point_r[1];
for (int j = 0; j < border_length-1; j++)
{
//左边界部分
/*
[2] [1] [0/8]
[3] [ ] [7]
[4] [5] [6]
*/
// printf("%d\n", j);
for (int i = 0; i < 8; i++)
{
if (bin_image[start_point_l[0] + neighbor_left[i][0]][start_point_l[1] + neighbor_left[i][1]] == 255 && bin_image[start_point_l[0] + neighbor_left[i+1][0]][start_point_l[1] + neighbor_left[i+1][1]] == 0)
{
// printf("h=%d\n", bin_image[start_point_l[0] + neighbor_left[i][0]][start_point_l[1] + neighbor_left[i][1]]);
// printf("h=%d\n", bin_image[start_point_l[0] + neighbor_left[i+1][0]][start_point_l[1] + neighbor_left[i+1][1]]);
growth_direction_left[growth_count_left] = i;
growth_count_left++;
start_point_l[0] = start_point_l[0] + neighbor_left[i+1][0];
start_point_l[1] = start_point_l[1] + neighbor_left[i+1][1];
border_location_left[border_count_left][0] = start_point_l[0];
border_location_left[border_count_left][1] = start_point_l[1];
border_count_left++;
// printf("New Left Start Point: %d, %d\n", start_point_l[0], start_point_l[1]);
// printf("finished\n");
// printf("%d\n", j);
break;
}
}
//右边界部分
/*
[0/8] [1] [2]
[7] [ ] [3]
[6] [5] [4]
*/
for (int i = 0; i < 8; i++)
{
if (bin_image[start_point_r[0] + neighbor_right[i][0]][start_point_r[1] + neighbor_right[i][1]] == 255 && (bin_image[start_point_r[0] + neighbor_right[i+1][0]][start_point_r[1] + neighbor_right[i+1][1]] == 0 || bin_image[start_point_r[0] + neighbor_right[i+1][0]][start_point_r[1] + neighbor_right[i+1][1]] == 151))
{
growth_direction_right[growth_count_right] = i;
growth_count_right++;
border_location_right[border_count_right][0] = start_point_r[0] + neighbor_right[i+1][0];
border_location_right[border_count_right][1] = start_point_r[1] + neighbor_right[i+1][1];
// bin_image[start_point_r[0] + neighbor_right[i+1][0]][start_point_r[1] + neighbor_right[i+1][1]] = 151;
start_point_r[0] = start_point_r[0] + neighbor_right[i+1][0];
start_point_r[1] = start_point_r[1] + neighbor_right[i+1][1];
border_count_right++;
break;
}
}
//当两线交汇时停止搜线
if ((j != 0 && j != border_length-1) &&
((border_location_left[j][0] == border_location_right[j][0] && border_location_left[j][1] == border_location_right[j][1])
|| (border_location_left[j+1][0] == border_location_right[j-1][0] && border_location_left[j+1][1] == border_location_right[j-1][1])
|| (border_location_left[j-1][0] == border_location_right[j+1][0] && border_location_left[j-1][1] == border_location_right[j+1][1])))
{
break;
}
}
}
在右圆环的八邻域中,不需要记录下每一个黑点的位置,因为我们只需要圆环最左侧点的位置。
与上面相同,每一个起点我们都需要至多扫描八次,把周围点都扫描一遍以检查突变。如果扫描到突变点,直接退出当前的循环,记录并开始下一次循环。每次循环结束后检查爬取到的点是否在原起点的右侧,如果是,则退出循环。
出问题的原因也找出来了,我将一部分的点标记为了152,而我在找八邻域时的条件为从255到0,这使程序在找八邻域时如果遇到了被我标记为152的点,程序将一直在那里循环,将标记解除后恢复了正常。