python基于opencv的车道线检测左右转弯原理详解

该项目的目标/步骤如下:

  • 给定一组棋盘图像计算相机校准矩阵和畸变系数。
  • 对原始图像应用失真校正。
  • 使用颜色变换、渐变等来创建阈值二值图像。
  • 应用透视变换来校正二进制图像(“鸟瞰图”)。
  • 检测车道像素并拟合以找到车道边界。
  • 确认检测到的线与现实和之前的线一致,即它们具有相似的曲率,水平距离在3.7m左右等。
  • 确定车道的曲率和车辆相对于中心的位置。
  • 将检测到的车道边界变形回原始图像。
  • 输出车道边界的视觉显示以及车道曲率和车辆位置的数值估计。

校准图像的过程使用棋盘图案并从对象点的定义开始(现实世界中奶酪图案上的已知点以 xyz 坐标给出,其中 z=0 因为图案位于平面上)和图像点(在图像上找到的点,使用函数:cv2.findChessboardCorners)。对于文件夹“/camera_cal”中的每个图像,这些点存储在 numpy 数组中。通过匹配图像和目标点(使用函数 cv2.calibrateCamera),我们可以获得相机矩阵和畸变参数,这将允许我们使用“cv2.undistort”函数对图像进行去畸变。然后将这些参数保存在 pickle 文件中以备将来使用。

 图。1。扭曲的棋盘图案

python基于opencv的车道线检测左右转弯原理详解_第1张图片

 图 2。未扭曲的棋盘图案

管道

在这里,我总结了我的车道数据操作管道。

1.畸变校正

应用相机不失真(功能不失真(img,mtx,dist,None,mtx)),我们可以从失真图像(img):到未 

python基于opencv的车道线检测左右转弯原理详解_第2张图片

 失真图像:  通过使用相机矩阵(mtx)和失真系数(dist) .

2. 得到一个阈值化的二值图像

我结合使用了颜色和渐变阈值来生成二值图像(用于渐变和颜色阈值的不同函数在文件的project.py第 25 行和第 76 行之间)。

为了确定哪些通道更适合做阈值处理,我显示了几个图像的所有通道: 

很明显,来自 RGB 的通道 R、来自 HLS 的通道 S 和来自 HSV 的通道 V 是车道线似乎更加突出的通道。所以现在,为了定义我实际要使用的那些,我通过将 X 边缘与 Y 边缘和 XY 边缘与边缘梯度阈值相结合来对这些通道执行边缘检测: 

python基于opencv的车道线检测左右转弯原理详解_第3张图片

和颜色阈值: 

通过混合、边缘和颜色阈值化,从这些通道我们可以得到: 

这清楚地显示了预期的车道线。/project.py用于在这 3 个通道上获取二进制阈值图像的代码可以在第 82 行和 171 行之间的文件中找到

3.透视变换

为了获得透视变换矩阵和逆矩阵,我重复使用了第一个项目中的一些代码,以便在我知道包含直线的图像上获得直线车道线: 

python基于opencv的车道线检测左右转弯原理详解_第4张图片

我得到的源点和目标点如下:

来源 目的地
587、455 300, 100
230、712 300, 720
1098, 712 980, 720
698, 455 980, 100

有了这些点,我使用函数计算了矩阵 M 和 M_invcv2.getPerspectiveTransform(src, dst)

通过取 4 个点(每行 2 个点)并定义边距,我可以将图像从正常视角转换(使用 jupyter notebook 第五块上的代码)到鸟瞰图(使用函数/P2_advanced_line_detection.ipynbcv2 .warpPerspective()): 

在获得 M 和 M_inv 矩阵后,我将它们保存在 pickle 文件中以备将来与函数一起使用。

然后可以将二进制边缘图像转换为扭曲的二进制图像,如下所示: 

在尝试了几张图片后,我注意到在某些情况下(阴影、人行道上的颜色变化),很难为 S 通道找到一个不产生极端噪音的合适阈值,这就是我决定工作的原因R 和 V 通道的组合。这种组合产生如下二进制扭曲图像:

python基于opencv的车道线检测左右转弯原理详解_第5张图片

为了使用阴影产生的噪声圆顶,我决定使用称为开运算的形态学操作: python基于opencv的车道线检测左右转弯原理详解_第6张图片

车道线识别

用于拟合二阶多项式的函数在文件的/project.py第 178 行到第 408 行之间。对于第一张图像以及在轨道丢失的情况下(由完整性检查确定),我使用了“windows”方法: python基于opencv的车道线检测左右转弯原理详解_第7张图片

当轨道被锁定时,最好简单地检测前一个多项式周围的车道线: python基于opencv的车道线检测左右转弯原理详解_第8张图片

计算曲率

/project.py我使用课程中给出的公式在代码的第 502 行到 516 行中执行了此操作。

def measure_curvature_real(actual_fit, ploty):
    '''
    Calculates the curvature o
    f polynomial functions in meters.
    '''
    ym_per_pix = 30/700 # meters per pixel in y dimension
    xm_per_pix = 3.7/700 # meters per pixel in x dimension
    # Define y-value where we want radius of curvature
    # We'll choose the maximum y-value, corresponding to the bottom of the image
    y_eval = np.max(ploty) * ym_per_pix
 
    ##### Implement the calculation of R_curve (radius of curvature) #####
    curvature = ((1 + (2*actual_fit[0]*y_eval + actual_fit[1])**2)**1.5) / np.absolute(2*actual_fit[0])
    return curvature * actual_fit[0]/abs(actual_fit[0])

健全性检查

为了决定是否应该考虑检测,我决定检查 3 个基本的东西

  1. 实际曲率应与前一帧的曲率相似
  2. 左右线曲线至少应具有相同的方向符号(二阶导数),除非线几乎是直的(高曲率)
  3. 线应该是相对平行的。在这里,我在以下函数中测量了水平距离平均值(应该在 3.7m 左右)和标准偏差:
#====Function to measure horizontal position's average and standard deviation====#
#==========between lines. The function also measures the car's position==========#
def horizontal_distance(left_fit,right_fit,ploty):
    xm_per_pix = 3.7/700
    left_fitx = (left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]) * xm_per_pix
    right_fitx = (right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]) * xm_per_pix
    average_distance = np.average(right_fitx - left_fitx)
    std_distance = np.std(right_fitx - left_fitx)
    
    x_der = right_fitx[0]
    x_izq = left_fitx[0]
    center_car = (1280*xm_per_pix/2.0)
    center_road = ((x_der+x_izq)/2.0)
    position = center_car-center_road
    return average_distance, std_distance, position

结果

一旦检测到车道线并通过健全性检查,就会计算曲率,并使用逆透视变换在原始图像中显示线条。

python基于opencv的车道线检测左右转弯原理详解_第9张图片python基于opencv的车道线检测左右转弯原理详解_第10张图片

效果视频:

python基于opencv的车道线检测车道线识别输出车道边界的视觉显示以及车道曲率和车辆位置的数值估计

项目下载:
https://download.csdn.net/download/babyai996/87738691

你可能感兴趣的:(计算机视觉,人工智能)