智能车视觉处理系列文章——迷宫巡线法详解(含代码)

巡线方法

1.迷宫巡线法

​ 按照上海交通大学的方法,通过使用迷宫巡线(种子生长法)在巡线的过程中进行图象的自适应阈值,这样可极大的减少计算量。具体思想参考上交文章,以下内容为对代码(以左手迷宫巡线为例)的解析。

  • 首先我们将**灰度图(时刻谨记)**作为输入,根据经验取图像下方中间偏左一点作为起始点(注意该点要在白色的赛道上),我们依次向左取像素点,直到像素点的值超过某一值(代码中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.
    

    在这里插入图片描述

  • 参考上交文档,“小明”要一直左手扶墙(勿忘)脚踩白色像素点,所以“小明“面临三种情况,同时要确保左手扶墙”小明“在三种情况下,分别有三种确定对策:

    1. 前进方向像素为黑——向右转。
    2. 前进方向像素为白,且左前方像素为白(墙角)——斜着走(x,y值均改变),且向左转。
    3. 前进方向像素为白,左前方像素为黑——向前走。
  • 代码及参数解释:

    参数解释

    • 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;
    }
    

    代码说明

    1. dir:用来控制”小明”转向,如dir = (dir + 1) % 4dir对应的索引会向下移动一位(向右转一次

    2. dir_front:存放前进步伐,dir会索引到,当前面向的前方。

    3. dir_frontleft:存放左前进的步伐,dir会索引到当前面向的左前方。(见图)

      在这里插入图片描述

    4. 代码中存在一些宏定义的名称,如AT(img, x + dx, y + dy)为求对应像素点的像素值,这些定义需要在全部代码中查找。

      在这里插入图片描述

  • 20
    点赞
  • 191
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值