实战:使用 OpenCV 的自动驾驶汽车车道检测(附代码)
点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达

我们将使用 Canny 进行边缘检测。如果你不确定这是什么,请查阅相关资料,对于后文的阅读会有帮助。
def canyEdgeDetector(image):edged = cv2.Canny(image, 50, 150)return edged
驾驶时,为了让汽车保持在车道上,只关注当前道路的下一个100米。此外,也不关心分隔线另一侧的道路。这就是我们定义的区域。我们隐藏图像中不必要的细节,只显示有助于我们找到车道的区域。

def getROI(image):height = image.shape[0]width = image.shape[1]# Defining Triangular ROI: The values will change as per your camera mountstriangle = np.array([[(100, height), (width, height), (width-500, int(height/1.9))]])# creating black image same as that of input imageblack_image = np.zeros_like(image)# Put the Triangular shape on top of our Black image to create a maskmask = cv2.fillPoly(black_image, triangle, 255)# applying mask on original imagemasked_image = cv2.bitwise_and(image, mask)return masked_image


4. 在我们的原始图像上应用蒙版以获得只有我们的 ROI 的裁剪图像。


下一步是通过 ROI 以获取图像中的所有直线。cv2.HoughLinesP()可以实现这一目标,此函数返回它可以在输入图像中找到的所有直线的列表,每条线由 [x1, y1, x2, y2] 表示。
def getLines(image):lines = cv2.HoughLinesP(image, 0.3, np.pi/180, 100, np.array([]), minLineLength=70, maxLineGap=20)return lines

以下实用程序函数获取图像和线条列表,并在图像上绘制线条。(此步骤不接受来自 Step3 的任何输入。相反,这只是一个将从 Step5 调用的实用步骤,因此首先查看 Step5,并在需要时访问此步骤)。
def displayLines(image, lines):if lines is not None:for line in lines:x1, y1, x2, y2 = line.reshape(4) #converting to 1d arraycv2.line(image, (x1, y1), (x2, y2), (255, 0, 0), 10)return image
我们定义了另一个效用函数来从它的参数(斜率和截距)中获取线坐标。需要注意的是:一条线由y=mx+c表示,其中 m 是斜率,c 是截距。
def getLineCoordinatesFromParameters(image, line_parameters):slope = line_parameters[0]intercept = line_parameters[1]y1 = image.shape[0]y2 = int(y1 * (3.4 / 5))x1 = int((y1 - intercept) / slope)x2 = int((y2 - intercept) / slope)return np.array([x1, y1, x2, y2])

一旦我们从步骤 3 中获得了线条,在这一步中,我们将这些线条分成 2 组(左和右)。如果你们注意到Step3的输出图像,则此步骤会将Line1和Line 2放入左侧组,将Line3放入右侧组。

分组后,我们找到该组的平均斜率(m)和截距(c),并尝试通过调用 getLineCoordinatesFromParameters() 并传递平均值 m 和平均值 c 为每个组创建一条线。
以下是完成所有这些工作的函数:
def getSmoothLines(image, lines):left_fit = [] # will hold m,c parameters for left side linesright_fit = [] # will hold m,c parameters for right side linesfor line in lines:y1, x2, y2 = line.reshape(4)parameters = np.polyfit((x1, x2), (y1, y2), 1)slope = parameters[0]intercept = parameters[1]if slope < 0:intercept))else:intercept))left_fit_average = np.average(left_fit, axis=0)right_fit_average = np.average(right_fit, axis=0)# now we have got m,c parameters for left and right line, we need to know x1,y1 x2,y2 parametersleft_line = getLineCoordinatesFromParameters(image, left_fit_average)right_line = getLineCoordinatesFromParameters(image, right_fit_average)return np.array([left_line, right_line])
这是线条分组后图像的外观:

image = cv2.imread("3.jpg") #Load Imageedged_image = canyEdgeDetector(image) # Step 1roi_image = getROI(edged_image) # Step 2lines = getLines(roi_image) # Step 3smooth_lines = getSmoothLines(image, lines) # Step 5image_with_smooth_lines = displayLines(image, smooth_lines) # Step 4cv2.imshow("Output", image_with_smooth_lines)cv2.waitKey(0)
输出将如下所示:

Github代码链接:
https://github.com/pdhruv93/computer-vision/tree/main/lane-detection-self-driving
交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

