文章目录
概要
1.什么叫做车道线检测?
车道线检测是指在道路上自动检测和识别车道线的过程。车道线是道路上的标记,用于指示车辆行驶的方向和位置。
通过对车道线进行检测和识别,自动驾驶和智能驾驶系统可以实现车辆的自动导航、车道保持、车道偏离警告等功能。
2. 车道线的检测方式有哪些?
基于图像处理的方法:这是最常见的车道线检测方法之一。它通过对摄像头捕获的图像进行预处理、边缘检测、霍夫变换等图像处理技术,来检测并提取车道线。
基于机器学习的方法:这种方法使用机器学习算法,如支持向量机(SVM)、随机森林(Random Forest)或深度学习网络(如卷积神经网络)来训练模型,从而实现车道线检测。
基于传感器融合的方法:这种方法结合了多种传感器的数据,如摄像头、激光雷达、毫米波雷达等。通过融合各种传感器的信息,可以提高车道线检测的准确性和鲁棒性。
基于特征匹配的方法:这种方法通过提取车道线特征,并与预先定义的模板进行匹配来实现检测。常用的特征包括车道线的颜色、纹理和形状等。
基于深度学习的方法:深度学习在车道线检测中也取得了很大的成功。通过使用深度学习网络,如卷积神经网络(CNN),可以直接从图像中学习车道线的特征,并进行检测和跟踪。
整体架构流程
- 将图像转换为灰度图像。(简化图像处理的复杂性并提高算法的效率)
- 对灰度图像进行高斯模糊处理,以降低噪声的影响。(减少对车道线判定的干扰)
- 使用Canny边缘检测算法提取图像的边缘。
- 定义感兴趣区域,使用
region_of_interest
函数提取该区域的边缘。(这个区域的选取很重要)- 使用霍夫变换检测直线,得到车道线的坐标。(也很重要)
- 创建一个空白图像,并使用
draw_lines
函数在空白图像上绘制检测到的车道线。- 将绘制了车道线的图像与原图像叠加,得到最终结果。
以上ROI区域的选取,Canny的阙值控制和霍夫变换的阙值的控制,这些都是比较重要的取值,需要根据环境不断测试,直到达到一个较好的效果。
技术名词解释
ROI(Region of Interest):
ROI是指图像中的感兴趣区域,也就是我们希望在图像中进行特定处理或分析的区域。通过定义ROI,我们可以限制算法的作用范围,提高计算效率。
Canny:
Canny边缘检测算法是一种经典的边缘检测算法。它包含以下几个步骤:
- 对图像进行灰度化处理。
- 对灰度图像应用高斯模糊,以减少噪声。
- 计算图像中每个像素的梯度幅值和方向。
- 应用非最大抑制,将边缘像素细化为单像素线条。
- 应用双阈值处理,将边缘像素分类为强边缘、弱边缘和非边缘。
- 使用连接强边缘和弱边缘的过程来形成完整的边缘。
霍夫变换:
霍夫变换是一种用于检测图像中的直线、圆或其他形状的技术。对于检测直线,霍夫变换将每个像素点转换为参数空间中的曲线。当参数空间中的曲线相交时,表示图像中存在共线的像素点,从而检测出直线。对于检测圆或其他形状,霍夫变换会在参数空间中找到曲线的交点。
技术细节
1.定义一个提取ROI的函数
# 提取ROI,并与原图像取与 def region_of_interest(img, vertices): # 创建一个与输入图像相同大小的全黑掩膜图像 mask = np.zeros_like(img) # 在掩膜图像上绘制多边形ROI区域,填充为白色(255) cv2.fillPoly(mask, vertices, 255) # 对原图像和掩膜图像进行按位与操作,提取ROI区域 masked_image = cv2.bitwise_and(mask, img) # 返回提取的ROI图像 return masked_image
2.定义绘制车道线的函数
# 绘制车道线 def draw_lines(img, lines, color=(0, 0, 255), thickness=3): if lines is not None: # 遍历每条检测到的线段 for line in lines: # 提取线段的起点和终点坐标 for x1, y1, x2, y2 in line: # 在原图像上绘制直线 cv2.line(img, (int(x1), int(y1)), (int(x2), int(y2)), color, thickness)
其中第一个判断是重要的,你可以思考一下为什么。
3.车道线检测函数(将使用上边两个函数)
# 车道线检测 def lane_detection(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将图像转换为灰度图像 blur = cv2.GaussianBlur(gray, (5, 5), 0) # 对灰度图像进行高斯模糊处理,降低噪声影响 edges = cv2.Canny(blur, 175, 200) # 使用Canny边缘检测算法提取图像边缘 height, width = edges.shape # 获取边缘图像的尺寸 roi_vertices = [ (0, height), (width * 0.5, height * 0.4), (width * 0.5, height * 0.4), (width, height) ] roi_edges = regiong_of_interest(edges, np.array([roi_vertices], np.int32 )) # 提取感兴趣区域的边缘 # 使用霍夫变换检测直线 lines = cv2.HoughLinesP(roi_edges, rho=2, theta=np.pi / 180, threshold=100, minLineLength=0, maxLineGap=175) line_image = np.zeros_like(image) # 创建一个空白图像,用于绘制检测到的车道线 draw_lines(line_image, lines) # 绘制检测到的车道线 result = cv2.addWeighted(image, 0.8, line_image, 1, 0) # 将绘制了车道线的图像与原图像叠加 return result
4.程序的主循环控制,输入与输出
cap = cv2.VideoCapture(r"E:\User\素材\车道线识别素材\1-车道线识别素材.mp4") # 创建VideoCapture对象,打开视频文件或连接摄像头 while(cap.isOpened()): ret, frame = cap.read() # 读取当前帧 if not ret: print("1") break # 若读取失败,退出循环 result = lane_detection(frame) # 对当前帧进行车道线检测 cv2.imshow("Lane Detection", result) # 在窗口中显示结果图像 if cv2.waitKey(1) & 0xFF == 27: # 按下键盘上的'ESC'键退出循环 print("2") break cap.release() # 释放视频资源 cv2.destroyAllWindows() # 关闭显示窗口
按ESC退出视频播放环节
5.完整代码
import cv2 import numpy as np # 提取ROI,并与原图像取与 def regiong_of_interest(img, vertices): mask = np.zeros_like(img) cv2.fillPoly(mask, vertices, 255) masked_image = cv2.bitwise_and(mask, img) return masked_image # 绘制车道线 def draw_lines(img, lines, color=(0, 0, 255), thickness=3): if lines is not None: for line in lines: for x1, y1, x2, y2 in line: cv2.line(img, (int(x1), int(y1)), (int(x2), int(y2)), color, thickness) # 车道线检测 def lane_detection(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将图像转换为灰度图像 blur = cv2.GaussianBlur(gray, (5, 5), 0) # 对灰度图像进行高斯模糊处理,降低噪声影响 edges = cv2.Canny(blur, 175, 200) # 使用Canny边缘检测算法提取图像边缘 height, width = edges.shape # 获取边缘图像的尺寸 roi_vertices = [ (0, height), (width * 0.5, height * 0.4), (width * 0.5, height * 0.4), (width, height) ] roi_edges = regiong_of_interest(edges, np.array([roi_vertices], np.int32 )) # 提取感兴趣区域的边缘 # 使用霍夫变换检测直线 lines = cv2.HoughLinesP(roi_edges, rho=2, theta=np.pi / 180, threshold=100, minLineLength=0, maxLineGap=175) line_image = np.zeros_like(image) # 创建一个空白图像,用于绘制检测到的车道线 draw_lines(line_image, lines) # 绘制检测到的车道线 result = cv2.addWeighted(image, 0.8, line_image, 1, 0) # 将绘制了车道线的图像与原图像叠加 return result cap = cv2.VideoCapture(r"E:\User\素材\车道线识别素材\1-车道线识别素材.mp4") # 创建VideoCapture对象,打开视频文件或连接摄像头 while(cap.isOpened()): ret, frame = cap.read() # 读取当前帧 if not ret: print("1") break # 若读取失败,退出循环 result = lane_detection(frame) # 对当前帧进行车道线检测 cv2.imshow("Lane Detection", result) # 在窗口中显示结果图像 if cv2.waitKey(1) & 0xFF == 27: # 按下键盘上的'ESC'键退出循环 print("2") break cap.release() # 释放视频资源 cv2.destroyAllWindows() # 关闭显示窗口
6. 效果如下
视频链接在下边
弯道有点拉跨,不过直道还不错,素材可以自己搜着下,自己拍也行(手动滑稽)。
小结
在这篇文章里,我们不需要深入了解Canny算法,霍夫算法等算法背后的逻辑及处理,尽管理解算法原理是有帮助的,但在实际应用中,更重要的是掌握工具的使用方法。因此,在学习图像处理算法时,我们应该注重掌握工具的使用,并了解如何将它们应用到实际问题上。