图0 印度泰米尔纳德邦安纳马莱森林公路上的车道检测
本文源码:https://github.com/KushalBKusram/AdvancedLaneDetection
计算机视觉在自动化系统观测环境、预测该系统控制器输入值等方面起着至关重要的作用。本文介绍了使用计算机视觉技术进行车道检测的过程,并引导我们完成识别车道区域、计算道路RoC 和估计车道中心距离的步骤。
摄像机校准(calibrateCamera.py)
几乎所有摄像机使用的镜头在聚焦光线以捕捉图像时都存在一定的误差,因为这些光线由于折射在镜头边缘发生了弯曲。这种现象会导致图像边缘的扭曲。以下视频用示例解释了两种主要的失真类型,强烈建议观看。
假设我们现在了解什么是径向失真,需要利用失真系数(k1、k2 和 k3)来校正径向失真。calibrateCamera.py是摄像机校准程序,默认情况下不运行该程序。建议在生成目标上的特征点和图像上的特征点的过程中至少使用20个棋盘图像。Main中的calibrate()将在/data/calibration中查找图像,但是我们也可以选择其他目录。
图1 左图:图像失真;右:未失真的图像
去除图像失真的整个过程是相当有趣的,OpenCV有一个很好的教程,解释了概念并举出一些例子。
透视变换(preprocess.py:8–19)
检测车道的第一步是调整我们的视觉系统,以鸟瞰的角度来观察前方的道路,这将有助于计算道路的曲率,因此将有助于我们预测未来几百米的转向角大小。自上而下视图的另一个好处是,它解决了车道线相交的问题。实际上只要沿道路行驶,车道线就是平行线。
鸟瞰图可以通过应用透视变换来实现,即将输入图像中车道区域四个点映射到所需点上,从而生成自顶向下的视图。这些点是根据个案确定,决定因素主要是摄像头在车辆中的位置及其视野。图2中的图片分别表示输入和转换后输出图像。
图2 左图:之前、右侧:之后
阈值(preprocess.py:22)
现在车道线是平行的,下一步将它们从输入图像上分割出来。输入图像包含RGB3个通道,车道线为白色或黄色。基于这个假设,输入图像可以转换为单个通道灰度图像,从而消除我们不需要的通道。另一个要转换为的颜色空间是HLS颜色空间,其中S通道可能会根据照明情况提供较好的结果。在以下示例中,将使用图像阈值,因为在给定的输入图像中它可以正常工作。图3在阈值处理后可视化输出。
图3 cv2.threshold(image, 220, 225, cv2.THRESH_BINARY)
下阈值(220)和上阈值(225)将根据输入图像手动调整。OpenCV有基于整体嵌套边缘检测的先进技术,而无需对阈值进行任何手动调整,但本文仍然使用的是简单的阈值技术。
车道像素查找(laneDetection.py:4~70)
预处理输入图像后,将在图像空间中确定并绘制车道。方法是在二进制图像(阈值图像)的下半部分绘制非零像素直方图,以观察模式:
图4直方图x=像素,y = 计数
由于像素值是二进制的,峰值代表大多数非零像素的位置,因此可以很好地指示车道线。直方图中的x坐标用作搜索相应通道的起点。滑动窗口方法的概念将应用在这里,以下视频说明了滑动窗口的概念,图5中是结果。
图5.滑动窗口的概念应用于图 4 的结果。
识别车道面积(laneDetection.py:85~149)
滑动窗口有助于估计每个车道区域的中心,使用这些 x 和 y 像素定位函数search_around_poly()可以适合二阶多项曲线。该函数适合 f(y)而不是 f(x),因为通道在图像中是垂直的。图6很好地说明了这一步。
图6 在这些通道上检测到二阶多项形
下一步是计算曲率半径,该半径可以使用与曲线局部部分附近的点紧密拟合的圆进行计算,如图 7 所示。曲线在特定点的曲率半径可以定义为近似圆的半径。此半径可以使用图 7 中的公式计算。
图7 曲率概念图的半径和用于计算 RoC 的方程
最后一步是在这些点之间放置一个多边形,并将其投影回原始图像,来突出显示车道区域。曲率的车道面积和半径是根据像素值计算的,像素值与真实世界空间不同,因此必须转换为现实世界的值,这涉及到测量我们投射扭曲图像的车道部分的长度和宽度。为简单起见,我们可以假设大多数车道通常长 30 米,宽 3.7 米,并且代码使用这些值将像素空间值转换为实际仪表测量值。
图 8 最终预期结果突出显示车道区域
结果
下面的视频显示,我们的结果还是非常不错的。