赞
踩
按照上海交通大学的方法,通过使用迷宫巡线(种子生长法)在巡线的过程中进行图象的自适应阈值,这样可极大的减少计算量。具体思想参考上交文章,以下内容为对代码(以左手迷宫巡线为例)的解析。
首先我们将**灰度图(时刻谨记)**作为输入,根据经验取图像下方中间偏左一点作为起始点(注意该点要在白色的赛道上),我们依次向左取像素点,直到像素点的值超过某一值(代码中thres=140),则认为该点已经靠近赛道。
// 原图找左右边线
int x1 = img_raw.width / 2 - begin_x, y1 = begin_y;
ipts0_num = sizeof(ipts0) / sizeof(ipts0[0]);
for (; x1 > 0; x1--)
if (AT_IMAGE(&img_raw, x1 - 1, y1) < thres) // 寻找边线起始点
break;
if (AT_IMAGE(&img_raw, x1, y1) >= thres)
findline_lefthand_adaptive(&img_raw, block_size, clip_value, x1, y1, ipts0, &ipts0_num);
else
ipts0_num = 0; // 如果没有找到像素点大于thres(140)的,则会将ipts_num置为0.
参考上交文档,“小明”要一直左手扶墙(勿忘)且脚踩白色像素点,所以“小明“面临三种情况,同时要确保左手扶墙”小明“在三种情况下,分别有三种确定对策:
代码及参数解释:
参数解释:
image_t * img
:存放图像相关数据的指针。block_size
:自适应阈值的范围。clip_value
:经验值,防止出现强制分割的现象(一般为2~5)。x
:”小明“出生位置x坐标。y
:"小明"出生位置y坐标。int pts[ ][2]
用来存放边线数据。int *num
:存放边线像素点的个数。代码:
/* 前进方向定义:
* 0
* 3 1
* 2
*/
AT_DTCM_SECTION_ALIGN_INIT(const int dir_front[4][2], 8) = {{0, -1},
{1, 0},
{0, 1},
{-1, 0}};
AT_DTCM_SECTION_ALIGN_INIT(const int dir_frontleft[4][2], 8) = {{-1, -1},
{1, -1},
{1, 1},
{-1, 1}};
// 左手迷宫巡线
AT_ITCM_SECTION_INIT(void findline_lefthand_adaptive(image_t *img, int block_size, int clip_value, int x, int y, int pts[][2], int *num))
{
assert(img && img->data); // 不满足则退出执行
assert(num && *num >= 0);
assert(block_size > 1 && block_size % 2 == 1);
int half = block_size / 2;
int step = 0, dir = 0, turn = 0; // step表示前进的步数;dir通过改变索引改变当前小人朝向的方向
while (step < *num && half < x && x < img->width - half - 1 && half < y && y < img->height - half - 1 && turn < 4)
{
int local_thres = 0;
for (int dy = -half; dy <= half; dy++) // for循环用来计算block区域的像素值之和
{
for (int dx = -half; dx <= half; dx++)
{
local_thres += AT(img, x + dx, y + dy);
}
}
local_thres /= block_size * block_size;
local_thres -= clip_value; // (x,y)点block区域内的阈值
int current_value = AT(img, x, y);
int front_value = AT(img, x + dir_front[dir][0], y + dir_front[dir][1]);
int frontleft_value = AT(img, x + dir_frontleft[dir][0], y + dir_frontleft[dir][1]);
if (front_value < local_thres) // 前进方向像素为黑色
{
dir = (dir + 1) % 4; // 遇到前方为黑色需要右转一次
turn++;
}
else if (frontleft_value < local_thres) // 前方像素为白色,且左前方像素为黑色
{
x += dir_front[dir][0];
y += dir_front[dir][1];
pts[step][0] = x; // 用来存放边线坐标信息
pts[step][1] = y;
step++;
turn = 0;
}
else // 前方为白色,左前方为白色(墙角)
{
x += dir_frontleft[dir][0]; // 遇到墙角要斜着走
y += dir_frontleft[dir][1];
dir = (dir + 3) % 4; // 遇到墙角要左转一次
pts[step][0] = x;
pts[step][1] = y;
step++;
turn = 0;
}
}
*num = step;
}
代码说明:
dir:用来控制”小明”转向,如dir = (dir + 1) % 4
,dir
对应的索引会向下移动一位(向右转一次)
dir_front
:存放前进步伐,dir
会索引到,当前面向的前方。
dir_frontleft
:存放左前进的步伐,dir
会索引到当前面向的左前方。(见图)
代码中存在一些宏定义的名称,如AT(img, x + dx, y + dy)
为求对应像素点的像素值,这些定义需要在全部代码中查找。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。