智能车图像处理(三)元素判断

相对于电磁处理赛道元素,摄像头有更多的方式去判断特殊元素,csdn上也有很多的博主介绍了他们对于特殊元素的处理,这里我将先对16届新出的三岔讲解我的思路及代码,之后再对圆环和车库进行思路讲解。

在对所有元素进行判断前,我们总结通过第二章巡线所得到的一些判断条件:

right_lost_count;  //右丢线数目
left_lost_count;   //左丢线数目
l_start;           //左边界出现第一个黑点所在行数
r_start;           //右边界出现第一个黑点所在行数
road_width[];      //赛道宽度

(一)三岔路口:

 智能车图像处理(三)元素判断_第1张图片智能车图像处理(三)元素判断_第2张图片智能车图像处理(三)元素判断_第3张图片

这是我摄像头采集的三岔路口的图像,下面我主要将对第二幅图像讲解我的思路

 智能车图像处理(三)元素判断_第4张图片

 对于三岔的判断我主要寻找进入三岔时的两个拐点以及进三岔底部的那个点

1.找到进入三岔时的两个拐点:左边界列数先变大,再变小。同右边界列数先变小后变大,找到那   个大小变化的那个点。两拐点成立后判断左右两边界的丢线数目,当小于一定阈值后置为状态一。

 2.三岔底部的点:找到进三岔的两个拐点后,计算两拐点的行数,两者两加除以2,记录下来,再以固定摄像头正中间的列数向上找黑白的跳变点(也可以以刚才两拐点的列数相减除以2,我之前因为代码问题,进三岔后点被刷新掉了,就没用,后来也没改回来),找到底部的点后,记录所在行数,与拐点1/2所在行数相减,当两者之差小于一定阈值后,判断三岔成立。

//找左拐点
void Findchangepoint_l(changepoint *prt, unsigned char Start, unsigned char End,
                        uint8 RoadName)
{
  uint8 i;
  //初始化结构体变量
  prt->changepoint_start = Start; //设置扫描的起始行
  prt->changepoint_end = End;     //设置扫描的结束行
  prt->changepoint_row = 0;
  prt->changepoint_col = 0;
  prt->changepoint_flag = 0;

 if (RoadName == SANCHA)
  {
    for (i = prt->changepoint_start; i > prt->changepoint_end; i--)
    {
      if (leftline[i] != 0 && leftline[i - 1] != 0 && leftline[i + 1] != 0 
          && leftline[i - 2] != 0                       //连续4行不丢线,并且这4行都小于70
          && leftline[i] < 178 && leftline[i - 1] < 178 && leftline[i + 1] < 178
          && leftline[i - 2] < 178)
      {
        if ((leftline[i] - leftline[i - 1] >= 0) && (leftline[i] - leftline[i - 2] >= 0) 
            && (leftline[i] - leftline[i - 3] >= 2) 
            && (leftline[i] - leftline[i + 1] >= 0) 
            && (leftline[i] - leftline[i + 2] >= 0) 
            && (leftline[i] - leftline[i + 3] >= 0)) //找到拐点
        {
          prt->changepoint_row = i;           //记录该拐点的行
          prt->changepoint_col = leftline[i]; //记录该拐点的列
          prt->changepoint_flag = 1;          //标记找到左拐点
          break;                              //找到退出
        }
      }
    }
  } 
}

//找右拐点
void Findchangepoint_R(changepoint *prt, unsigned char Start, unsigned char End, 
                        uint8 RoadName)
{
  int i;
  //初始化结构体变量
  prt->changepoint_start = Start; //设置扫描的起始行
  prt->changepoint_end = End;     //设置扫描的结束行
  prt->changepoint_row = 0;
  prt->changepoint_col = 0;
  prt->changepoint_flag = 0;

  if (RoadName == SANCHA)
  {
    for (i = prt->changepoint_start; i >= prt->changepoint_end; i--) 
         //不能扫描太远,否则会误判
    {
      if ((rightline[i] != (cutCOL - 1) && rightline[i - 1] != (cutCOL - 1) 
           && rightline[i - 2] != (cutCOL - 1) 
           && rightline[i - 3] != (cutCOL - 1)) 
           && (rightline[i] > 10 && rightline[i - 1] > 10 
           && rightline[i + 1] > 10 && rightline[i - 2] > 10)) 
          //连续四行不丢线,并未为了防止跳变,这4行必须大于10
      {
        if ((rightline[i] - rightline[i + 1] <= 0) 
             && (rightline[i] - rightline[i + 2]) <= 0 
             && (rightline[i] - rightline[i + 3]) <= 0 
             && (rightline[i] - rightline[i - 1] <= 0) 
             && (rightline[i] - rightline[i - 2] <= 0) 
             && (rightline[i] - rightline[i - 3] <= -2))
        {
          prt->changepoint_row = i;            //记录拐点的行
          prt->changepoint_col = rightline[i]; //记录拐点的列
          prt->changepoint_flag = 1;           //标记找到右拐点
          break;                               //退出for
        }
      }
    }
  } 
}
/*
函数名称:Sancha_judge
函数功能: 判断三岔
*/
int point_flag;
int distance;
int Sancha_Num = 0; //记载进入三岔次数,滤掉偶然情况
void Sancha_judge(sancha *prt)
{
  int i;
  //  San.Sancha_In_Flag=0;

  Findchangepoint_l(&changepointL, 117, 60, SANCHA);
  Findchangepoint_R(&changepointR, 117, 60, SANCHA);

  if (changepointL.changepoint_flag && changepointR.changepoint_flag 
      && sum_lost_line < 40) //左右下方拐点存在
  {
    point_flag = 1;
    sancha_startrow = ((changepointL.changepoint_row + changepointR.changepoint_row)/2);
    sancha_startcol = ((changepointL.changepoint_col + changepointR.changepoint_col)/2);
  }
  if (point_flag == 1 && sum_lost_line > 70)
  {
    for (i = sancha_startrow; i > 50; i--)
    {
      if ((image_deal[i][sancha_startcol] == white) 
            && (image_deal[i - 1][sancha_startcol] == black))
      {
        sanchabutton_row = i;
        distance = sancha_startrow - sanchabutton_row;
        if (distance > 0 && distance <= 40 && sanchabutton_row > 55)
        {
          San.sanchabutton_flag = 1;
          San.Sancha_In_Flag = 1;
          special_LOCK = 1;
          Sancha_Num++;
          break;
        }
      }
    }
  }
}

 2.圆环判断:

判断圆环的条件开源的大佬有很多,这里我以左圆环为例,主要讲解两种判断圆环的方法,

 智能车图像处理(三)元素判断_第5张图片智能车图像处理(三)元素判断_第6张图片智能车图像处理(三)元素判断_第7张图片智能车图像处理(三)元素判断_第8张图片智能车图像处理(三)元素判断_第9张图片智能车图像处理(三)元素判断_第10张图片

智能车图像处理(三)元素判断_第11张图片智能车图像处理(三)元素判断_第12张图片智能车图像处理(三)元素判断_第13张图片

 智能车图像处理(三)元素判断_第14张图片智能车图像处理(三)元素判断_第15张图片

 方法一:通过寻找拐点判断

              1.判断右边界为连续直道

               2.找到图一和图二左下方的拐点,置为状态一

               3.if(状态一) 找左中拐点,置为状态二

               4.if(状态二) 找左上拐点,置为状态三  //进环后,此时对陀螺仪进行积分,辅助出环

               5.出环时,找右下拐点(图九)

               6.赛道宽度变宽,丢线数目大于阈值(图十)

 方法二:通过判断赛道黑白跳变点

              1.判断右边界为连续直道

               2.固定两行判断,在左下拐点的上方为全白                                                                                 if(全白),继续往下隔3行扫描,共扫描4行(这个行数的多少可以把图像放入                     上位机里查看),看这几行同一行是否存在由白到黑以及黑到白的跳变点,如果                      这4行有一行存在,即可置为状态一。(图二)

              3.找5行判断,当左边界的列数大于一阈值,置为状态二(图五)

              4.判断右边的黑色个数,随着车向左偏移 黑块个数由多->少->多(图六->图七)                        //此时对陀螺仪进行积分,辅助出环

              5.出环时,判断左右两边白色个数及赛道宽度

 3.车库判断:

 这里我以左车库为例进行讲解

 智能车图像处理(三)元素判断_第16张图片智能车图像处理(三)元素判断_第17张图片智能车图像处理(三)元素判断_第18张图片

 智能车图像处理(三)元素判断_第19张图片

1.既然为左车库,右边界就为直线,判断右边界为直线

2.在图二蓝线标注的框内,固定5行,对图像左边进行从第1列到左边蓝线列数的扫描,如果为全白,车库的状态为一

3.在图三紫色线标注的行数内,固定5行隔行从赛道右边界往左至最左边的斑马线所在的列数进行扫描,判断由黑到白以及白到黑的个数,如果大于6个,则判断车库成功

你可能感兴趣的:(智能车,算法)