基于KITTI数据集的无人驾驶感知与传感器融合实现—(4)—颜色空间&梯度空间结合
学习前言
最近看MSI直播有点上头,哈哈哈哈~ 之前我们不是对比了不同的颜色空间和不同的梯度空间对车道线检测能力哪个更好吗,这次我们将这两者结合一下~ 老样子,我还是把原作者的项目连接放上面啦~ 连接.
一、代码实现&效果图
颜色空间中在s通道车道线是最明显的,所以就在s通道基础上进行梯度边缘检测
import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
image = mpimg.imread('test_image/test6.jpg')
# 定义像素点梯度总和函数
def mag_thresh(img, sobel_kernel=3, mag_thresh=(30, 100)):
# 分别计算x,y方向梯度
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
# 计算梯度和
# absolute 对数组中的每一个元素求其绝对值
gradmag = np.sqrt(np.absolute(sobelx) ** 2 + np.absolute(sobely) ** 2) # 平方根计算
# 计算梯度角
theta = np.arctan2(np.absolute(sobely), np.absolute((sobelx)))
# 转换到 8-bit (0 - 255) 并转换为type = np.uint8
scaled_gradmag = (gradmag / (np.max(gradmag) / 255)).astype(np.uint8)
# 根据梯度阈值,创建一个二进制掩膜
binary_output = np.zeros_like(scaled_gradmag)
# 将原图中高于阈值的像素点在掩膜中的对应位置置为1
binary_output[(scaled_gradmag >= mag_thresh[0]) & (scaled_gradmag <= mag_thresh[1])] = 1
return binary_output
# 梯度空间和颜色空间结合Pipeline
def pipeline(img, s_thresh=(170, 255), sx_thresh=(20, 100), sobel_kernel=9):
img = np.copy(img)
# 装换为HLS空间,并提取各个通道
hls = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
l_channel = hls[:, :, 1]
s_channel = hls[:, :, 2]
h_channel = hls[:, :, 0]
# 计算s_binary
s_binary = np.zeros_like(s_channel)
s_binary[(s_channel >= s_thresh[0]) & (s_channel <= s_thresh[1])] = 1
# 利用S通道计算sobelx
sobelx = cv2.Sobel(s_channel, cv2.CV_64F, 1, 0)
abs_sobelx = np.absolute(sobelx)
scaled_sobel = np.uint8(255 * abs_sobelx / np.max(abs_sobelx))
# Sobelx梯度筛选
sxbinary = np.zeros_like(scaled_sobel)
sxbinary[(scaled_sobel >= sx_thresh[0]) & (scaled_sobel <= sx_thresh[1])] = 1
# 利用S通道计算梯度总和
mag_binary = mag_thresh(s_channel, sobel_kernel=sobel_kernel, mag_thresh=(30, 100))
# 将Sx梯度空间,Mag梯度空间和s_channel颜色空间堆叠起来,作为最后边缘检测效果,分别为RGB三通道
color_binary = np.dstack((mag_binary, sxbinary, s_binary)) * 255
# 将检测结果转换为二进制图像
combine_binary = np.zeros_like(s_channel)
combine_binary[(sxbinary == 1) | (s_binary == 1) | (mag_binary == 1)] = 1
return color_binary, combine_binary
color_binary, combine_binary = pipeline(image)
# 可视化结果
f, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 9))
f.tight_layout()
ax1.imshow(image)
ax1.set_title('Original Image', fontsize=30)
ax2.imshow(color_binary)
ax2.set_title('color_binary', fontsize=30)
ax3.imshow(combine_binary, cmap='gray')
ax3.set_title('combine_binary', fontsize=30)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
plt.show()
二、函数解析
代码中的主要函数就是pipeline()
这个函数了,这个函数主要是将图片的S通道单独提取出来然后进行两个方向的处理。
- 为什么要选择S通道,我们之前在做 图像的颜色空间特征提取.的时候就得出的结论:S通道对车道线和车辆目标的检测效果要由于其它通道。所以用S通道。
- 为什么使用Soble算子进行x方向的梯度处理:我个人觉得是方便坚持到车道线的特征,因为车道线是竖着的呗,相比y方向要更加容易检测到车道线。
- 为什么第三部处理采用的是大kernel(kernel_size=9),s,y方向上的Sobel算子的梯度总和图片呢,应该是我们之前得出来的kernel_size加大会使图片保留更大尺度的边缘,降低对小尺度边缘的敏感性,一定程度抑制了噪点。
- 为什么要进行维度叠加和或运算两种方法,我觉得将三种带有梯度特征的图片进行维度叠加可以加强边缘效果,而将三张梯度特征图片进行或运算,可以让三张图片的特征进行融合(简单的说就是三种方法的互补)。