本人的代码元素处理框架来自于这位博主的文章。

第18届全国大学生智能汽车竞赛四轮车开源讲解【5】--直道、弯道、十字_智能车竞赛开源-CSDN博客

结合了博主的思路和我自己的思路,我在这里为大家梳理一下。

十字得处理关键是在于拐点(角点)(突变点)的寻找,找拐点的思路有很多种,基本上我都了解过,这里我只介绍最简单最直观而且好调的方法。

圈出来的那个点就是标准的拐点。有以下几种特点:

1.上面几个点横坐标与拐点差距较大。

2.下面点横坐标于拐点差距不大。

3.上方出现丢线。

/*-------------------------------------------------------------------------------------------------------------------
  @brief     左下角点检测
  @param     起始点,终止点
  @return    返回角点所在的行数,找不到返回0
  Sample     Find_Left_Down_Point(int start,int end);
  @note      角点检测阈值可根据实际值更改
-------------------------------------------------------------------------------------------------------------------*/
uint8 Find_Left_Down_Point(int start,int end)//找四个角点,返回值是角点所在的行数
{
    uint8 i,t;
    uint8 left_down_line=0;
    if(Left_Lost_Time>=0.9*MT9V03X_H)//大部分都丢线,没有拐点判断的意义
       return left_down_line;
    if(start<end)
    {
        t=start;
        start=end;
        end=t;
    }
    if(start>=MT9V03X_H-1-5)//下面5行数据不稳定,不能作为边界点来判断,舍弃
        start=MT9V03X_H-1-5;
    if(end<=MT9V03X_H-Search_Stop_Line)
        end=MT9V03X_H-Search_Stop_Line;
    if(end<=5)
       end=5;
    for(i=start;i>=end;i--)
    {
        if(left_down_line==0&&//只找第一个符合条件的点
           abs(Left_Line[i]-Left_Line[i+1])<=3&&//角点的阈值可以更改
           abs(Left_Line[i+1]-Left_Line[i+2])<=3&&
           abs(Left_Line[i+2]-Left_Line[i+3])<=3&&
              (Left_Line[i]-Left_Line[i-2])>=6&&
              (Left_Line[i]-Left_Line[i-3])>=10&&
              (Left_Line[i]-Left_Line[i-4])>=10)
        {
            left_down_line=i;//获取行数即可
            break;
        }
    }
    return left_down_line;
}

左上、右上、右下拐点的思路同理,这里不再赘述。

有了拐点之后,识别十字就很方便了。看下面这张图。

这是标准的正入十字,他的特点如下:

1.四个拐点都有。

2.左右都丢线。

这两个条件判断十字足够了

/*-------------------------------------------------------------------------------------------------------------------
  @brief     十字检测
  @param     null
  @return    null
  Sample     Cross_Detect(void);
  @note      利用四个拐点判别函数,查找四个角点,根据找到拐点的个数决定是否补线
-------------------------------------------------------------------------------------------------------------------*/
void Cross_Detect(void)
{
    uint8 down_search_stop_l=0;//下点搜索开始行
    uint8 down_search_stop_r=0;//下点搜索开始行

    Cross_Flag=0;
    if(Island_State==0&&Ramp_Flag==0)//与环岛互斥开
    {
        Left_Up_Find=0;
        Right_Up_Find=0;



        if(Both_Lost_Time>=10)//十字必定有双边丢线,在有双边丢线的情况下再开始找角点
        {
            //Scan_line_l2r();//右线重扫

            //Find_Up_Point( MT9V03X_H-1, 0 );
            Right_Up_Find=Find_Right_Up_Point(image_h-10,10);
            Left_Up_Find=Find_Left_Up_Point(image_h-10,10);

            //ips200_show_uint(60, 210, Right_Up_Find, 3);
            //ips200_show_uint(10, 210, Left_Up_Find, 3);



            if(Left_Up_Find==0&&Right_Up_Find==0)//只要没有同时找到两个上点,直接结束
            {
                return;
            }
        }
        if(Left_Up_Find!=0&&Right_Up_Find!=0)//找到两个上点,就找到十字了
        {
            Cross_Flag=1;//对应标志位,便于各元素互斥掉
            down_search_stop_l=Left_Up_Find;
            down_search_stop_r=Right_Up_Find;


            Right_Down_Find=Find_Right_Down_Point(Boundry_Start_Right-3,down_search_stop_l+2);
            Left_Down_Find=Find_Left_Down_Point(Boundry_Start_Left-3,down_search_stop_r+2);

            if(Left_Down_Find<=Left_Up_Find)
            {
                Left_Down_Find=0;//下点不可能比上点还靠上
            }
            if(Right_Down_Find<=Right_Up_Find)
            {
                Right_Down_Find=0;//下点不可能比上点还靠上
            }

/********************************************下面是十字处理******************************************************************************/
            if(Left_Down_Find!=0&&Right_Down_Find!=0)
            {//四个点都在,无脑连线,这种情况显然很少
                Left_Add_Line (Left_Line [Left_Up_Find ],Left_Up_Find ,Left_Line [Left_Down_Find ] ,Left_Down_Find);
                Right_Add_Line(Right_Line[Right_Up_Find],Right_Up_Find,Right_Line[Right_Down_Find],Right_Down_Find);
            }
            else if(Left_Down_Find==0&&Right_Down_Find!=0)//11//这里使用的都是斜率补线
            {//三个点                                     //01
                //Lengthen_Left_Boundry(Left_Up_Find-1,MT9V03X_H-1);
                extendline_l(limit_a_b_uint8(Left_Up_Find-7,Search_Stop,image_h-1),Left_Up_Find-2);
                Right_Add_Line(Right_Line[Right_Up_Find],Right_Up_Find,Right_Line[Right_Down_Find],Right_Down_Find);
            }
            else if(Left_Down_Find!=0&&Right_Down_Find==0)//11
            {//三个点                                     //10
                Left_Add_Line (Left_Line [Left_Up_Find ],Left_Up_Find ,Left_Line [Left_Down_Find ] ,Left_Down_Find);
                //Lengthen_Right_Boundry(Right_Up_Find-1,MT9V03X_H-1);
                extendline_r(limit_a_b_uint8(Right_Up_Find-7,Search_Stop,image_h-1),Right_Up_Find-2);
            }
            else if(Left_Down_Find==0&&Right_Down_Find==0)//11
            {//就俩上点                                   //00
                //Lengthen_Left_Boundry (Left_Up_Find-1,MT9V03X_H-1);
                //Lengthen_Right_Boundry(Right_Up_Find-1,MT9V03X_H-1);
                extendline_l(limit_a_b_uint8(Left_Up_Find-7,Search_Stop,image_h-1),Left_Up_Find-2);
                extendline_r(limit_a_b_uint8(Right_Up_Find-7,Search_Stop,image_h-1),Right_Up_Find-2);
            }
        }
        else
        {
            Cross_Flag=0;
        }
    }

}

个人认为斜入十字没必要单独处理。

下一篇文章我会详细讲解如何补线。

我第一次写文章,内容可能不够详细,如果有疑问可以在评论区留言,我会看到并及时更新补充。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐