文章目录
目录
系列文章目录
文章目录
前言
一、拐点
二、利用拐点补线
1.补线的应用
2.补线的方法
前言
前两篇文章介绍了扫线和图像预处理,而当图像的边界线出来之后,还需要通过边界线来找到一些特征。比如断行,拐点。这一章介绍一些元素处理的预备节根据拐点补线。
一、拐点
拐点就是边界线开始不按照正常斜率的那一点,比如十字,圆环等处发生边界断行,这时候断行的那一点我们称为拐点。识别拐点的方法有很多,这里介绍我用过的几种方法。
1.通过边界线连续三点差值来判断。
当连续3个点的差值大于设定阈值,就可以说明拐点存在。这个阈值取决于摄像头的角度和高度,不同的角度可能差的会比较大。这种方式在搜取拐点时效果挺好,不过因为一般情况下都是全图扫描,比较浪费。所以在第一种方法上我采用边线提取的同时,也进行拐点判断。
2.断行时搜索拐点。
在采用跟踪搜线时,遇到一些元素时会明显有断行存在或者边界线不按照原本的斜率。这时候边界线就不存在或者我们没有搜到,这时候我们就可以判断上拐点和下拐点了。
这里我是将按照边界的常规斜率搜线时没有搜到,比如正常我们不对图像进行逆透视变换时,边界线时一条斜线,赛道靠近车近处大,后面越来越小。这样当我们正常的提取边界时,当斜率发生变化了,就搜不到线。所以这时候我们向外搜线,如果存在边界,那么前一行我们就判断是下拐点。
简单来说就是边界连续时,边界线从向内倾斜变成了向外倾斜的情况的那一点,就是下拐点。
那么对于上拐点时,采用的方法也有相通的地方,当断行后,重新找到边界,这重新找到的一点就是上拐点。可以在搜寻拐点时,对拐点所在行进行限制,避免赛道外存在,或者拐点乱飞。
拐点存在的几种常见情况,A,B,C,a,b就是下拐点和上拐点。
二、利用拐点补线
1.补线的应用
对于正常弯道和直道,拐点一般不存在,但是在十字,三岔,圆环这里,就比较明显。尤其我们还需要利用拐点去进行补线,将空白的赛道拟合出我们需要的边界线。 这样我们经过这些元素时可以在我们需要的时候做出直行,打角等动作。
2.补线的方法
1.通过两点拉线补线
拉线正常理解就是通过已知的两点,不断在这两点之间填中线点。
已知A,B两点,第一次我们填上A,B中心点C,第二次填入D点,直到A,B之间所有行都填满。下面附上代码
/******************************************************************************
*
//曲线拟合 CommonRectificate(&P_LeftBlack[0],startPos-1,endPos+1);
******************************************************************************/
void CommonRectificate(unsigned char data[],unsigned char begin,unsigned char end)
{
unsigned char MidPos = 0;
if (end > 60-1)
{
end = 60-1;
}
if (begin == end)
{
data[begin] = (data[begin-1]+data[begin+1])>>1;
// BlackLineData[begin] = LeftBlack[begin] + (RightBlack[begin]-LeftBlack[begin])/2;
}
else if(begin < end)
{
MidPos = (begin+end)>>1;
data[MidPos] = (data[begin]+data[end])>>1;
//BlackLineData[MidPos] = LeftBlack[MidPos] + (RightBlack[MidPos]-LeftBlack[MidPos])/2;
if (begin+1 < MidPos)
{
CommonRectificate(data,begin,MidPos);
}
if (MidPos+1 < end)
{
CommonRectificate(data,MidPos,end);
}
}
}
2.通过最小二乘法补线
在一些情况下,我们只能知道一点的位置,这时候我们可以通过已知的几个连续点来预测接下来的几点位置。由最小二乘法求得斜率,可以通过简单的运算得到接下来几点的坐标。
附上最小二乘法求斜率代码
//最小二乘法拟合斜率
float Slope_Calculate(uint8 begin,uint8 end,uint8 *p)
{
float xsum=0,ysum=0,xysum=0,x2sum=0;
uint8 i=0;
float result=0;
static float resultlast;
p=p+begin;
for(i=begin;i<end;i++)
{
xsum+=i;
ysum+=*p;
xysum+=i*(*p);
x2sum+=i*i;
p=p+1;
}
if((end-begin)*x2sum-xsum*xsum) //判断除数是否为零
{
result=((end-begin)*xysum-xsum*ysum)/((end-begin)*x2sum-xsum*xsum);
resultlast=result;
}
else
{
result=resultlast;
}
return result;
}
补线结果实例