线路检测:让自动驾驶汽车查看路线

2019-10-15 17:19:57 浏览数 (1)

作者 | Joanis Gatopoulos

来源 | Medium

编辑 | 代码医生团队

可以通过Computer Vision逐步将视频流转换为行检测器

动机

完全自动驾驶的乘用车并非“指日可待”。马斯克(Elon Musk)声称,特斯拉到2020年底将具备“完全自动驾驶”功能。特别是,他说,特斯拉的硬件已经为自动驾驶做好了准备,剩下的只是他们当前软件的更新,许多杰出的科学家正在研究它。

作为驾驶员,人类的本能是第一个本能,那就是朝我们前方看,并确定汽车应向何处移动。每辆自动驾驶汽车的前方都装有摄像头,这是一项非常重要的任务,它决定了汽车在其间移动的边界。对于人类,在道路上画线。现在,将教一辆自动驾驶汽车看这些线。保证这会很有趣的:)

议程

将逐步设计井眼管线,并在其中激励这样做的动机。

  • 灰度变换
  • 高斯模糊
  • Canny边缘检测
  • 遮盖感兴趣的区域
  • Hough线检测器
  • 查找道路线

完整的代码:

https://github.com/ioangatop/AutonomousCar

在这里,将逐步介绍它,提供整个代码的快照。但是某些部分被省略了,因为这会使职位变得很沉重,并分散对目标的关注。因此有关其他信息,请参阅上面的存储库。

步骤0:读取图像

在matplotlib帮助下,可以轻松地将Python脚本中的任何图像作为三维张量CHW加载(颜色通道,图像的高度和宽度)

代码语言:javascript复制
import matplotlib.image as mpimg
img_path = 'test_images/solidWhiteCurve'
img = mpimg.imread(img_path)
plt.imshow(img)
plt.show()

步骤1:灰度

首先,要使图像成为灰度图像。只有一个颜色通道。这将有助于识别边缘和拐角。

可以很容易地通过opencv

代码语言:javascript复制
import cv2
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
plt.imshow(gray_img, cmap='gray')
plt.show()

步骤2:高斯模糊

将高斯噪声添加到图像中,它非常有用,因为它可以平滑像素之间的插值,并且是超通过噪声和伪梯度的一种方法。越高kernel,结果图像将越模糊。

代码语言:javascript复制
kernel_size = 5
gauss_img = cv2.GaussianBlur(gray_img,(kernel_size, kernel_size), 0)

步骤3:Canny边缘检测

Canny Edge Detection提供了一种检测图像边界的方法。这是通过图像的渐变完成的。

后者不过是一个函数,其中每个像素的亮度与渐变的强度相对应。

将通过追踪遵循最强渐变的像素来找到边缘!通常,梯度显示函数变化的速度,像素之间的强烈密度变化将指示边缘。

代码语言:javascript复制
low_threshold, high_threshold = [200, 300]
canny_img = cv2.Canny(gauss_img, low_threshold, high_threshold)

如您所见,现在可以清楚地确定路线!(甚至可以看到汽车的形状!)

步骤4:遮盖感兴趣的区域

上图中有一些异常值;道路另一端的一些边缘,从风景(山)等,到边缘。当相机固定好后,可以在图像上放置一个遮罩,并仅保留这些对任务有趣的线条。因此,绘制梯形是很自然的,以便仅保留期望道路线所在的区域。再一次,cv2在这里

代码语言:javascript复制
# Setting the corners of the trapezium
vertices = np.array([[(0, img_line.shape[0]), (img_line.shape[1], img_line.shape[0]), (400, 260), (600, 260)]])
# make a blank/white image
mask = np.zeros_like(img)
mask_channels = (255,) * img.shape[2]
# Fill the area of interest with 0 and 255 these
# which lie outside of it, thoughout all color channels
cv2.fillPoly(mask, vertices, mask_channels)
# Keep only the pixels with 0 value of the canny_img
masked_img = cv2.bitwise_and(canny_img, mask)

选定区域

应用遮罩后

步骤5:霍夫线检测器

上面的图像仅代表边缘的点。剩下的就是连接边缘。在这种情况下,正在寻找行,将通过将图像传输到称为Hough Space的参数空间来实现这一点。现在,将处理极坐标(rho和theta),在其中搜索相交的线。

代码语言:javascript复制
import math
lines = cv2.HoughLinesP(img, rho=1, theta=math.pi/180,
                        threshold=15, np.array([]),        
                        minLineLength=30,
                        maxLineGap=40)
line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)

上面将返回许多小车道(最小长度是超参数minLineLength)。line_img将是一个列表,其元素是一个列表,并由图像空间{(x1,y1),(x2,y2)}中的两个点组成。众所周知,在2D空间中只有一条线经过两点。

这里自然而然地出现了问题。如何连接这些线路,并导致只有两条,它们将成为道路线路?这似乎是这篇文章中最具挑战性的部分。

步骤6:找到路线

策略如下:

  • 相对于x轴将图像分成两半
  • 将线性回归模型拟合到这些点,以找到一条平滑的线。

由于存在离群值,需要一种可以有效处理它们的回归模型。将使用HuberRegressor。然后,将图像限制在y轴的某个范围内,并借助它cv2.polylines绘制线。请记住,为了获得一条平滑的线,将通过给定的回归值绘制y给定的预测x 。

代码语言:javascript复制
import math
def draw_lines(line_img, lines):
   # CODE HERE
   pass
lines = cv2.HoughLinesP(img, rho=1, theta=math.pi/180,
                        threshold=15, np.array([]),        
                        minLineLength=30,
                        maxLineGap=40)
line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
draw_lines(line_img, lines)
plt.imshow(line_img)
plt.show()

这时,鼓励读者对以上功能进行编码。

步骤7:将线条与原始图片连接

通过对两个图像进行加权,可以将它们相加。请记住,黑色区域img_lines具有value 0,因此加法不会更改输出之一。

代码语言:javascript复制
out_img = cv2.addWeighted(img, 0.9, img_lines, 1.0, 0.0)
plt.imshow(out_img)
plt.show()

备注

瞧!设法找到了道路!视频只是一系列图像,因此,借助moviepy,可以在每帧中使用上述管线!视频管道如下所示:

代码语言:javascript复制
from moviepy.editor import VideoFileClip
in_video = 'test_videos_output/solidWhiteCurve.mp4'
output_video = 'test_videos_output/out.mp4'
clip = VideoFileClip(in_video).subclip(0, 8)
empty_clip = clip.fl_image(YOUR PIPELINE AS A FUNCTION THAT
                           RETURNS THE WEIGHTED IMAGE)
out_clip.write_videofile(output_video, audio=False)

如前所述,完整的代码可以在此处找到。随意使用参数,并提出检测路线的新方法。

https://github.com/ioangatop/AutonomousCar

0 人点赞