透视变换
透视变换是将成像投影到一个新的视平面(鸟瞰图)。车载相机拍摄到的图像中,由于受相机角度和高度的影响往往会将平行的车道线拍成梯形,这样的图像会给后续检测带来较大难度,所以需要我们对原图进行透视变换,从而得到一张鸟瞰图。
具体思路是,先读取两组坐标(例如原图像的四点坐标和目标图像的四点坐标),计算变换矩阵;然后根据变换矩阵对图像进行透视变换,并输出到目标图像。
相机标定
由于一般相机都多少存在畸变,而自动驾驶需要准确的车道曲率以执行正确的方向控制,因此需要对相机进行校正。首先读取两个坐标数组,计算变换矩阵;然后根据变换矩阵对原图进行透视变换,并输出到目标画布。
确定相机内参和畸变参数的过程就叫做相机标定。一般只需要一幅图像(国际象棋棋盘图像较为常用)就可以进行相机标定。标定时只需要从不同角度拍摄棋盘图案,通过检测棋盘图案中的角点,得到角点像素,并且我们已知真实世界中的对象角点坐标 ,便可进行相机校正。若要进行精确的标定,通常从不同角度对同一棋盘拍摄多张照片(10-20张)。
直方图滤波
简单来说,就是沿着X轴统计每列像素的数值,并用直方图表示。其中峰值位置的x坐标则对应左右两侧的车道线。通过这种方式,来获取车道线位置信息。
图片来自Udacity无人驾驶课程
初级车道线检测算法--直线
颜色阈值处理
读取图片,对颜色RGB分别设置阈值,将高于所设阈值的像素(较亮的白色部分)分离出来。# 读取图片image = mpimg.imread('test.jpg')ysize = image.shape[0]xsize = image.shape[1]color_select = np.copy(image)
# 对RGB通道分别设置阈值red_threshold = 200 #Tuninggreen_threshold = 200 #Tuningblue_threshold = 200 #Tuning
# 将所设阈值以下的任何像素都设置为0rgb_threshold = [red_threshold, green_threshold, blue_threshold]thresholds = (image[:,:,0] < rgb_threshold[0]) | (image[:,:,1] < rgb_threshold[1]) | (image[:,:,2] < rgb_threshold[2])
color_select[thresholds] = [0,0,0]
提取ROIPython# 首先定义一个空图像mask = np.zeros_like(image)
# 设置ROI区域坐标(任意多边形)vertices = np.array([[image.shape[1]*.12, image.shape[0]], [image.shape[1]*.25,(image.shape[0]+image.shape[0]*.65)/2], [image.shape[1]*.42, image.shape[0]*.63], [image.shape[1]*.6,image.shape[0]*.63], [image.shape[1]*.8,(image.shape[0]+image.shape[0]*.65)/2], [image.shape[1]*.95,image.shape[0]]]) #Tuning
# 设置颜色通道,并填充ROIif len(image.shape) > 2: channel_count = image.shape[2] # i.e. 3 or 4 depending on your image ignore_mask_color = (255,) * channel_countelse: ignore_mask_color = 255
cv2.fillPoly(mask, vertices, ignore_mask_color)
# 合并得到ROI,其余部分为零masked_image = cv2.bitwise_and(image, mask)
Canny边缘检测
# 将图像转换为灰度图gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# 进行高斯模糊,去除噪声kernel_size = 3 #Tuningblur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size), 0) # 参数kernel_size可以是任何奇数
# 计算梯度(Canny边缘检测)low_threshold = 50 #Tuninghigh_threshold = 150 #Tuningedges = cv2.Canny(gray,low_threshold,higy_threshold) # 参数:灰度图,低阈值,高阈值。输出为边缘图。
霍夫变换
rho = 2 theta = np.pi/180 threshold = 15 min_line_length = 50 max_line_gap = 20
# rho和theta是霍夫空间的距离和夹角# threshold是通过同一交点的曲线个数最小值# min_line_length是直线的最小像素长度# max_line_gap是线与线之间的最大像素长度。输出为多条直线
lines = cv2.HoughLinesP(masked_edges, rho, theta, threshold, np.array([]), min_line_length, max_line_gap)