智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 10318|回复: 21

关于摄像头斜入十字的一些想法

  [复制链接]

7

主题

61

帖子

0

精华

高级会员

Rank: 4

积分
979
威望
522
贡献
271
兑换币
333
注册时间
2015-11-1
在线时间
93 小时
毕业学校
UPC
发表于 2016-2-1 17:49:01 | 显示全部楼层 |阅读模式
对于摄像头来说,天然的优势是一次可以扫描很多行,这使得在赛道处理方面要比线性CCD简单得多,其实黑线采集本身是非常简单的,不过感觉对于新手来说,斜入十字或许会有点难,这些天我一直在考虑这个问题,今天终于有了一些想法,我们都知道,斜入十字是一定会有一个突变点的,许多人认为难就难在提取这个突变点上,我认为由于镜头失真,导致摄像头采集的数据是梯形的,也就是左边的那条黑线一般是向右倾斜的,而右边的那条黑线一般是向左倾斜的,那么什么时候会出现异常呢,当然是弯道了,各种弯道都可能,其实斜入十字误判就是当弯道处理,而我们只不过是把弯道在进行判断看是不是十字,那么我正常采集黑线的过程中,当出现左边黑线向左倾斜或者右边黑线向左倾斜的时候我就继续采集三行数据,比较这三行的斜率与前三行,这里的前是指靠近车的部分,当斜率突变,则认为是斜入十字。到这里似乎斜入十字就解决了,可是最重要的是补线,那么怎么补线呢,我的处理方法是当我找到斜入十字的时候,我从突变点的哪一行开始,就突变点所在的那一列开始向上搜线,即远处,当搜到黑线的时候结束,这个时候我在向右寻找,当我找到由黑色向白色的跳变的时候,则认为找到了十字的结束行,通过十字开始行(即突变点所在行)到十字结束行的斜率进行补线即可。
回复

使用道具 举报

7

主题

61

帖子

0

精华

高级会员

Rank: 4

积分
979
威望
522
贡献
271
兑换币
333
注册时间
2015-11-1
在线时间
93 小时
毕业学校
UPC
 楼主| 发表于 2016-2-1 20:21:22 | 显示全部楼层
°Destiny 发表于 2016-2-1 20:18
楼主可以把计算斜率那儿的代码贴一下吗,谢谢
zxec_slope_calculate()

float zxec_slope_calculate(int8 begin,int8 end,int8 *array)  
{  
  int xsum=0,ysum=0,xysum=0,x2sum=0;
  uint8 i=0;
  float result=0;
  static float result_last;//开辟静态区间,保存上一次的结果
  array=array+begin;//定位开始地址
  for(i=begin;i<=end;i++)
  {
  xsum+=i;
  ysum+=*array;
  xysum+=i*(*array);
  x2sum+=i*i;
  array=array+1;
}
  if((end-begin)*x2sum-xsum*xsum) //除数不为零
  {
    result=(float)((end-begin+1)*xysum-xsum*ysum)/((end-begin+1)*x2sum-xsum*xsum);
    result_last=result;
  }
  else//除数等于零
    result=result_last;//保留上一次不为零时的计算结果
  return result;
}
回复 支持 1 反对 0

使用道具 举报

4

主题

52

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1228
威望
629
贡献
347
兑换币
379
注册时间
2015-4-20
在线时间
126 小时
毕业学校
未毕业
发表于 2016-2-1 17:58:17 | 显示全部楼层
来点实际实现代码呗
回复 支持 0 反对 1

使用道具 举报

7

主题

61

帖子

0

精华

高级会员

Rank: 4

积分
979
威望
522
贡献
271
兑换币
333
注册时间
2015-11-1
在线时间
93 小时
毕业学校
UPC
 楼主| 发表于 2016-2-1 17:51:04 | 显示全部楼层
打错了,第8行应该是出现左线向左倾斜右线向右倾斜的时候
回复 支持 反对

使用道具 举报

7

主题

61

帖子

0

精华

高级会员

Rank: 4

积分
979
威望
522
贡献
271
兑换币
333
注册时间
2015-11-1
在线时间
93 小时
毕业学校
UPC
 楼主| 发表于 2016-2-1 18:02:14 | 显示全部楼层
q15920078530 发表于 2016-2-1 17:58
来点实际实现代码呗

自己看吧,不想单独写了,直接从我程序中提取的
void search_line(void)
{
  int8 Row_Ptr=0;//行计数参量
  int8 Col_Ptr=0;//列计数参量
  int8 Left_End=0;//寻左线列截止数
  int8 Right_End=0;//寻右线列截止数
  track.Left_Valid_Count=0;//默认左边沿有效连续计数值为0
  track.Right_Valid_Count=0;//默认右边沿有效连续计数值为0
  track.Left_Invalid_Count=0;//默认左边沿无效连续计数值为0
  track.Right_Invalid_Count=0;//默认右边沿无效连续计数值为0
  Cross_Flag=0;//默认无十字
  /*
   *由于最近三行图像非常靠谱,利用从中间向两边分别寻找能找到靠谱的黑线
   */
  for(Row_Ptr=ROW-1;Row_Ptr>ROW-3;Row_Ptr--)
  {
    track.Left_Line[Row_Ptr]=1;//初始化左黑线为1
    track.Right_Line[Row_Ptr]=COLUMN-2;//初始化右黑线为COLUMN-2
    track.Left_Valid[Row_Ptr]=0;//默认左边未找到黑线
    track.Right_Valid[Row_Ptr]=0;//默认右边未找到黑线
    track.Center_Line[Row_Ptr]=COLUMN/2;//默认中线为图像中间
    //从中间开始往左寻线
    for(Col_Ptr=COLUMN/2;Col_Ptr>0;Col_Ptr--)
    {
   if(img[Row_Ptr][Col_Ptr]==0 && img[Row_Ptr][Col_Ptr-1]==1)
   {
    track.Left_Line[Row_Ptr]=Col_Ptr-1;//黑线位置
    track.Left_Valid[Row_Ptr]=1;//此行左黑线有效位置1
    track.Left_Valid_Count++;//连续有效行+1
        track.Left_Invalid_Count=0;
    break;
   }
    }
    if(track.Left_Valid==0)
    {
      track.Left_Valid_Count=0;
      track.Left_Invalid_Count++;
    }
    //从中间开始往右寻线
    for(Col_Ptr=COLUMN/2;Col_Ptr<COLUMN;Col_Ptr++)
    {
   if(img[Row_Ptr][Col_Ptr]==0 && img[Row_Ptr][Col_Ptr+1]==1)
   {
    track.Right_Line[Row_Ptr]=Col_Ptr+1;
    track.Right_Valid[Row_Ptr]=1;
    track.Right_Valid_Count++;
        track.Right_Invalid_Count=0;
    break;
   }
    }
    if(track.Right_Valid==0)
    {
      track.Right_Valid_Count=0;
      track.Right_Invalid_Count++;
    }
  }
  /*
   *由于梯形失真导致左边的黑线是从下往上向右收敛,右边的黑线是从下往上向左收敛(除非
   *弯道,左黑线向左收敛可能是S弯道或者左拐弯还有十字,右黑线向右收敛可能是S弯或者右
   *拐弯还有十字),利用这也特点,当出现相反情况时判断是否是突变点,可以识别斜入十字
   *,而直入十字判断则用连续白行即可
   */
  if(track.Left_Valid_Count==3&&track.Right_Valid_Count==3)//最近三行左右均找到黑线
  {
    for(Row_Ptr=ROW-4;Row_Ptr>Drop_Row;Row_Ptr--)
    {
      track.Left_Line[Row_Ptr]=1;//初始化为1
      track.Left_Valid[Row_Ptr]=0;//初始化每行无效
      Col_Ptr=track.Left_Line[Row_Ptr+1]+6;//具体数值还需视情况而定
      Left_End=track.Left_Line[Row_Ptr+1]-6;
      for(;Col_Ptr>Left_End;Col_Ptr--)
      {
        if(img[Row_Ptr][Col_Ptr]==0 && img[Row_Ptr][Col_Ptr-1]==1)
        {
          track.Left_Line[Row_Ptr]=Col_Ptr-1;//黑线位置
          track.Left_Invalid_Count=0;//左线连续无效值清零
          if(track.Left_Line[Row_Ptr]<track.Left_Line[Row_Ptr+1])//出现左线异常不向右收敛
          {
            Left_Turn_Count++;//左线收敛方向异常连续计数+1
            track.Left_Valid[Row_Ptr]=1;//暂时标记此行左黑线有效位置1
            break;
          }
          else//左线正常向右收敛
          {
            Left_Turn_Count=0;//左线收敛方向异常连续计数值清零
            track.Left_Valid[Row_Ptr]=1;//此行左黑线有效位置1
            break;
          }
        }
      }
      if(track.Left_Valid==0)//此行没有找到左黑线
        track.Left_Invalid_Count++;
      if(Left_Turn_Count==3)//左黑线收敛方向异常进一步判断是否为斜入十字
      {
        if(zxec_slope_calculate(Row_Ptr,Row_Ptr+3,track.Left_Line)*
            zxec_slope_calculate(Row_Ptr+3,Row_Ptr+6,track.Left_Line)<-2)//要改
        {
          //通过此条件进一步确定为斜入十字
          Cross_Flag=2;
          //Left_Turn_Count=0;
          Left_Turn_Row=Row_Ptr+3;
          track.Left_Valid[Row_Ptr]=0;
          track.Left_Valid[Row_Ptr+1]=0;
          track.Left_Valid[Row_Ptr+2]=0;
          //接下来应该利用竖直的线向上搜,找到十字结束行,这里用Left_Turn_End表示
          for(;Row_Ptr>Drop_Row;Row_Ptr--)
          {
            track.Left_Valid[Row_Ptr]=0;
            if(img[Row_Ptr][track.Left_Line[Left_Turn_Row]]==0 && img[Row_Ptr-1][track.Left_Line[Left_Turn_Row]]==1)
            {
              Left_Turn_End=Row_Ptr;
              for(Col_Ptr=track.Left_Line[Left_Turn_Row];Col_Ptr<COLUMN;Col_Ptr++)
              {
                if(img[Row_Ptr][Col_Ptr]==1 && img[Row_Ptr][Col_Ptr+1]==0)
                {
                  track.Left_Line[Left_Turn_End]=Col_Ptr;
                  track.Left_Valid[Row_Ptr]=1;
                }
                break;
              }
              for(Row_Ptr=Left_Turn_Row;Left_Turn_Row<Left_Turn_End;Row_Ptr--)//斜入十字补线
              {
                track.Left_Line[Row_Ptr]=track.Left_Line[Left_Turn_Row]+
                 (track.Left_Line[Left_Turn_End]-track.Left_Line[Left_Turn_Row])/ (Left_Turn_End-Left_Turn_Row)*(Row_Ptr-Left_Turn_Row);
                track.Left_Valid[Row_Ptr]=1;
              }
              break;
            }
          }
          if(Left_Turn_End==0)//向上搜线未找到结束行
          {
            for(Row_Ptr=Left_Turn_Row;Left_Turn_Row<Drop_Row;Row_Ptr--)//斜入十字补线
            {
              track.Left_Line[Row_Ptr]=track.Left_Line[Left_Turn_Row]+
                 (track.Left_Line[Left_Turn_Row]-track.Left_Line[Left_Turn_Row+3])/ (Left_Turn_Row-(Left_Turn_Row+3))*(Row_Ptr-Left_Turn_Row);
              track.Left_Valid[Row_Ptr]=1;
            }
          }
        }        
      }
      if(track.Left_Invalid_Count==3)
      {
        track.Left_Break=Row_Ptr+3;//左边黑线断点行记录
        break;//跳出大循环,停止搜线
      }
    }
  }
}
回复 支持 反对

使用道具 举报

7

主题

47

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1714
威望
876
贡献
516
兑换币
549
注册时间
2014-11-14
在线时间
161 小时
发表于 2016-2-1 20:18:43 | 显示全部楼层
楼主可以把计算斜率那儿的代码贴一下吗,谢谢
zxec_slope_calculate()
回复 支持 反对

使用道具 举报

17

主题

363

帖子

0

精华

常驻嘉宾

超级菜

Rank: 8Rank: 8

积分
4481
威望
2165
贡献
1450
兑换币
1435
注册时间
2014-1-16
在线时间
433 小时
发表于 2016-2-2 21:54:59 | 显示全部楼层
楼主中石油?青岛还是北京啊
回复 支持 反对

使用道具 举报

7

主题

61

帖子

0

精华

高级会员

Rank: 4

积分
979
威望
522
贡献
271
兑换币
333
注册时间
2015-11-1
在线时间
93 小时
毕业学校
UPC
 楼主| 发表于 2016-2-2 22:14:53 | 显示全部楼层
从容阳光℡ 发表于 2016-2-2 21:54
楼主中石油?青岛还是北京啊

当然青岛的啊
回复 支持 反对

使用道具 举报

0

主题

35

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
338
威望
131
贡献
67
兑换币
88
注册时间
2015-8-12
在线时间
70 小时
毕业学校
安徽师范大学
发表于 2016-2-12 12:30:54 | 显示全部楼层
楼主有试试实际跑起来效果怎么样吗?
回复 支持 反对

使用道具 举报

26

主题

210

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2300
威望
1261
贡献
701
兑换币
815
注册时间
2015-10-17
在线时间
169 小时
发表于 2016-2-18 13:56:34 | 显示全部楼层
谢谢楼主,楼主好人
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-12-27 18:18 , Processed in 0.050323 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表