Python 自动驾驶图像识别,车道线/交通标志/车辆检测全流程
一、前置准备:环境搭建与核心库说明
1. 核心依赖库安装
自动驾驶图像识别依赖OpenCV(底层图像处理)、ultralytics(YOLOv8目标检测)、matplotlib(结果可视化)等库,推荐使用conda创建虚拟环境避免版本冲突,国内镜像加速安装提升效率。
# 1. 创建虚拟环境(Python 3.9-3.10兼容性最佳)
conda create -n auto_drive_env python=3.9
conda activate auto_drive_env
# 2. 安装核心库(国内清华镜像加速)
# 图像处理核心
pip install opencv-python==4.8.1.78 matplotlib scikit-image -i https://pypi.tuna.tsinghua.edu.cn/simple
# 深度学习目标检测(YOLOv8官方库)
pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple
# 数值计算辅助
pip install numpy pandas -i https://pypi.tuna.tsinghua.edu.cn/simple
2. 环境验证
运行以下代码,验证核心库是否正常导入,确保环境配置无误:
import cv2
import numpy as np
import matplotlib.pyplot as plt
from ultralytics import YOLO
print(f"OpenCV版本:{cv2.__version__}")
print(f"NumPy版本:{np.__version__}")
print("YOLOv8可正常调用")
print("自动驾驶图像识别环境配置成功!")
3. 数据集与测试素材准备
推荐下载公开自动驾驶数据集用于实战,测试素材可自行截取车载视频帧或使用公开样本:
- 车道线检测:
Udacity Self-Driving Car Dataset(包含晴天、雨天、夜间等多种场景) - 交通标志识别:
GTSRB(德国交通标志数据集,包含43类常见交通标志) - 车辆/行人检测:
KITTI(自动驾驶经典数据集,包含真实道路场景的目标标注) - 快速测试:直接使用本文示例代码中的本地图片(命名为
lane_test.jpg、sign_test.jpg、car_test.jpg)
二、实战1:车道线检测(传统计算机视觉,快速落地)
车道线检测是自动驾驶的基础任务,负责识别车辆行驶的车道边界,传统计算机视觉方法无需训练,实时性强,适合入门落地,核心流程为「图像预处理→边缘检测→感兴趣区域裁剪→霍夫变换直线检测→车道线拟合与绘制」。
1. 完整实战代码
# 文件名:lane_detection.py
import cv2
import numpy as np
import matplotlib.pyplot as plt
def preprocess_image(img):
"""
图像预处理:灰度化→高斯去噪→Canny边缘检测
"""
# 1. 灰度化(减少计算量,保留亮度信息)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 高斯模糊去噪(去除路面噪声,避免边缘检测误判)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# 3. Canny边缘检测(提取图像边缘信息)
canny = cv2.Canny(blur, 50, 150)
return canny
def region_of_interest(img):
"""
裁剪感兴趣区域(ROI):仅保留车道线区域,排除天空、树木等无关区域
"""
height, width = img.shape
# 定义ROI多边形顶点(根据车载摄像头视角调整,此处为梯形)
polygons = np.array([
[(width*0.1, height), # 左下
(width*0.45, height*0.6),# 左上
(width*0.55, height*0.6),# 右上
(width*0.9, height)] # 右下
], np.int32)
# 创建掩码
mask = np.zeros_like(img)
cv2.fillPoly(mask, polygons, 255)
# 掩码与边缘图像按位与,提取ROI区域
roi_img = cv2.bitwise_and(img, mask)
return roi_img
def detect_lane_lines(img, original_img):
"""
霍夫变换检测直线,拟合车道线并绘制到原始图像
"""
# 1. 霍夫变换检测直线
lines = cv2.HoughLinesP(
img,
rho=1, # 距离分辨率(像素)
theta=np.pi/180, # 角度分辨率(弧度)
threshold=50, # 检测阈值(投票数)
minLineLength=40, # 直线最小长度
maxLineGap=20 # 直线最大间隙
)
# 2. 分离左右车道线,计算斜率与截距
left_lines = [] # 左车道线(斜率为负)
right_lines = [] # 右车道线(斜率为正)
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
# 计算斜率(避免除零错误)
if x2 - x1 == 0:
continue
slope = (y2 - y1) / (x2 - x1)
# 计算截距
intercept = y1 - slope * x1
# 筛选左右车道线(根据斜率判断,可调整阈值)
if slope < -0.3:
left_lines.append((slope, intercept))
elif slope > 0.3:
right_lines.append((slope, intercept))
# 3. 平均拟合左右车道线(减少抖动)
left_lane = np.mean(left_lines, axis=0) if left_lines else None
right_lane = np.mean(right_lines, axis=0) if right_lines else None
# 4. 计算车道线端点,绘制到原始图像
height = original_img.shape[0]
lane_img = np.zeros_like(original_img)
if left_lane is not None:
slope, intercept = left_lane
# 计算车道线上端点(y=height*0.6)和下端点(y=height)的x坐标
y1 = int(height * 0.6)
x1 = int((y1 - intercept) / slope)
y2 = height
x2 = int((y2 - intercept) / slope)
cv2.line(lane_img, (x1, y1), (x2, y2), (0, 255, 0), 5)
if right_lane is not None:
slope, intercept = right_lane
y1 = int(height * 0.6)
x1 = int((y1 - intercept) / slope)
y2 = height
x2 = int((y2 - intercept) / slope)
cv2.line(lane_img, (x1, y1), (x2, y2), (0, 255, 0), 5)
# 5. 融合车道线图像与原始图像
result_img = cv2.addWeighted(original_img, 0.8, lane_img, 1, 0)
return result_img
# 主流程执行
if __name__ == "__main__":
# 1. 读取测试图像
img_path = "lane_test.jpg"
original_img = cv2.imread(img_path)
if original_img is None:
raise Exception("无法读取测试图像,请检查文件路径是否正确")
# 复制原始图像用于可视化对比
img_copy = np.copy(original_img)
# 2. 执行车道线检测流程
preprocessed_img = preprocess_image(img_copy)
roi_img = region_of_interest(preprocessed_img)
result_img = detect_lane_lines(roi_img, img_copy)
# 3. 可视化结果对比
plt.figure(figsize=(15, 10))
plt.subplot(2, 2, 1)
plt.title("原始图像")
plt.imshow(cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.subplot(2, 2, 2)
plt.title("预处理后(边缘检测)")
plt.imshow(preprocessed_img, cmap="gray")
plt.axis("off")
plt.subplot(2, 2, 3)
plt.title("感兴趣区域(ROI)")
plt.imshow(roi_img, cmap="gray")
plt.axis("off")
plt.subplot(2, 2, 4)
plt.title("车道线检测结果")
plt.imshow(cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.tight_layout()
plt.savefig("lane_detection_result.png", dpi=300, bbox_inches="tight")
plt.show()
# 4. 保存最终结果
cv2.imwrite("lane_detection_final.jpg", result_img)
print("车道线检测完成,结果已保存")
2. 关键优化技巧
- 光照适应性优化:加入自适应直方图均衡化(CLAHE),解决晴天强光、夜间暗光导致的边缘检测失效问题,在
preprocess_image函数中补充:clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) gray = clahe.apply(gray) - 车道线颜色优化:针对黄色车道线,可先转换到HSV色彩空间,提取黄色区域后再进行边缘检测,提升黄色车道线的检测精度。
- 抖动抑制:通过滑动窗口平均法,缓存前几帧的车道线参数,减少单帧图像的检测抖动,提升结果稳定性。
三、实战2:交通标志识别(YOLOv8,深度学习快速落地)
交通标志识别负责识别限速、禁止通行、转弯等交通标志,是自动驾驶遵守交通规则的核心,YOLOv8作为单阶段目标检测模型,兼具速度与精度,无需从头训练,直接使用预训练模型即可快速落地,适合快速实现交通标志检测需求。
1. 预训练模型快速推理(无需训练,直接使用)
# 文件名:traffic_sign_detection.py
from ultralytics import YOLO
import cv2
import matplotlib.pyplot as plt
# 1. 加载YOLOv8预训练模型(推荐使用yolov8s,平衡速度与精度)
# 注:YOLOv8预训练模型支持COCO数据集类别,包含"stop sign"等常见交通标志
# 如需识别更多交通标志(如限速标志),需使用GTSRB数据集微调
model = YOLO("yolov8s.pt")
# 2. 读取测试图像
img_path = "sign_test.jpg"
original_img = cv2.imread(img_path)
if original_img is None:
raise Exception("无法读取测试图像,请检查文件路径是否正确")
img_rgb = cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB)
# 3. 执行交通标志检测(推理)
# conf:置信度阈值,iou:NMS非极大值抑制阈值
results = model(img_rgb, conf=0.5, iou=0.45)
# 4. 可视化检测结果
# 方法1:使用YOLOv8自带可视化工具,直接保存结果
results[0].save(filename="traffic_sign_detection_result.jpg")
# 方法2:手动解析结果,自定义绘制(更灵活)
result_img = np.copy(original_img)
for result in results[0].boxes:
# 提取检测框坐标、类别、置信度
x1, y1, x2, y2 = map(int, result.xyxy[0])
class_id = int(result.cls[0])
confidence = float(result.conf[0])
class_name = model.names[class_id]
# 筛选交通标志相关类别(可根据需求扩展)
traffic_sign_classes = ["stop sign", "traffic light", "yield"]
if class_name in traffic_sign_classes:
# 绘制检测框
cv2.rectangle(result_img, (x1, y1), (x2, y2), (0, 0, 255), 3)
# 绘制类别与置信度标签
label = f"{class_name} {confidence:.2f}"
cv2.putText(
result_img,
label,
(x1, y1 - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 0, 255),
2
)
# 5. 可视化自定义结果
plt.figure(figsize=(10, 10))
plt.title("交通标志检测结果(自定义绘制)")
plt.imshow(cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.savefig("traffic_sign_custom_result.png", dpi=300, bbox_inches="tight")
plt.show()
# 6. 保存自定义结果
cv2.imwrite("traffic_sign_final.jpg", result_img)
print("交通标志检测完成,结果已保存")
2. 自定义交通标志训练(适配GTSRB数据集,识别更多标志)
若需识别限速、禁止左转等更多交通标志,需使用GTSRB数据集对YOLOv8进行微调,核心步骤如下:
- 数据集准备:下载GTSRB数据集,整理为YOLO格式,数据集结构如下:
gtsrb_dataset/ ├── images/ │ ├── train/ # 训练集图片 │ └── val/ # 验证集图片 ├── labels/ │ ├── train/ # 训练集标注文件(.txt,YOLO格式) │ └── val/ # 验证集标注文件(.txt,YOLO格式) └── gtsrb.yaml # 数据集配置文件 - 编写配置文件
gtsrb.yaml:names: 0: Speed limit 20km/h 1: Speed limit 30km/h # 省略其余41类,根据GTSRB数据集完整补充 nc: 43 # 类别总数 train: gtsrb_dataset/images/train val: gtsrb_dataset/images/val - 执行微调训练:
from ultralytics import YOLO # 加载YOLOv8s预训练模型 model = YOLO("yolov8s.pt") # 开始微调训练 results = model.train( data="gtsrb.yaml", epochs=50, batch=16, imgsz=640, lr0=0.01, device=0, # GPU编号,CPU用"cpu" save=True, project="runs/train/gtsrb" ) # 验证训练结果 model.val()
四、实战3:车辆与行人检测(YOLOv8,自动驾驶安全核心)
车辆与行人检测是自动驾驶的安全核心,负责识别道路上的其他车辆、行人、自行车等障碍物,为避障和跟车提供决策依据,YOLOv8在该任务上表现优异,支持实时检测,可直接落地到车载系统。
1. 完整实战代码(支持图片/视频/实时摄像头)
# 文件名:vehicle_pedestrian_detection.py
from ultralytics import YOLO
import cv2
import matplotlib.pyplot as plt
def detect_vehicles_pedestrians(img_path=None, video_path=None, camera_id=0):
"""
车辆与行人检测:支持图片、视频、实时摄像头
"""
# 1. 加载YOLOv8预训练模型
model = YOLO("yolov8m.pt") # yolov8m:比yolov8s精度更高,适合安全关键场景
# 2. 定义检测目标类别(自动驾驶核心障碍物)
target_classes = ["person", "car", "motorcycle", "bicycle", "truck", "bus"]
class_ids = [model.names.index(cls) for cls in target_classes if cls in model.names]
# 3. 分场景执行检测
if img_path is not None:
# 图片检测
img = cv2.imread(img_path)
if img is None:
raise Exception("无法读取图片文件,请检查路径是否正确")
# 推理检测
results = model(img, conf=0.5, iou=0.45, classes=class_ids)
# 可视化结果
result_img = results[0].plot()
# 保存并显示结果
cv2.imwrite("vehicle_pedestrian_img_result.jpg", result_img)
plt.figure(figsize=(12, 8))
plt.title("车辆与行人检测结果(图片)")
plt.imshow(cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.savefig("vehicle_pedestrian_img_plot.png", dpi=300, bbox_inches="tight")
plt.show()
elif video_path is not None:
# 视频文件检测
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise Exception("无法打开视频文件,请检查路径是否正确")
# 获取视频参数,准备写入结果视频
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
out = cv2.VideoWriter("vehicle_pedestrian_video_result.mp4", fourcc, fps, (width, height))
# 逐帧检测
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 推理检测
results = model(frame, conf=0.5, iou=0.45, classes=class_ids)
result_frame = results[0].plot()
# 写入结果视频
out.write(result_frame)
# 实时显示(按q退出)
cv2.imshow("Vehicle & Pedestrian Detection (Video)", result_frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()
print("视频检测完成,结果已保存为vehicle_pedestrian_video_result.mp4")
else:
# 实时摄像头检测
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
raise Exception("无法打开摄像头,请检查设备是否正常")
# 逐帧检测
while True:
ret, frame = cap.read()
if not ret:
break
# 推理检测
results = model(frame, conf=0.5, iou=0.45, classes=class_ids)
result_frame = results[0].plot()
# 实时显示(按q退出)
cv2.imshow("Vehicle & Pedestrian Detection (Camera)", result_frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
# 主流程执行(按需选择检测场景)
if __name__ == "__main__":
# 场景1:图片检测
detect_vehicles_pedestrians(img_path="car_test.jpg")
# 场景2:视频文件检测(注释场景1,取消注释此处即可)
# detect_vehicles_pedestrians(video_path="road_test.mp4")
# 场景3:实时摄像头检测(注释前两个场景,取消注释此处即可)
# detect_vehicles_pedestrians()
2. 实时性优化技巧
- 模型轻量化:使用
yolov8n或yolov8s轻量模型,牺牲少量精度换取更高帧率,满足车载实时性要求(目标帧率≥30fps)。 - 图像尺寸压缩:推理时设置
imgsz=480或imgsz=320,减少输入图像尺寸,提升推理速度。 - 硬件加速:将模型转换为ONNX格式,使用OpenVINO或TensorRT进行加速,在边缘设备(如Jetson Nano)上提升帧率。
- 感兴趣区域裁剪:与车道线检测类似,裁剪道路区域进行检测,排除天空、远处无关区域,减少计算量。
五、常见问题与避坑指南(自动驾驶图像识别专属)
- 车道线检测失效(光照/天气影响):
- 解决方案:加入HSV色彩空间分割、自适应阈值、去雾算法(如暗通道去雾),解决雨天、雾天、强光逆光场景的检测问题。
- 小交通标志检测不到:
- 解决方案:对图像进行局部放大、使用YOLOv8小目标优化模型、增加GTSRB数据集中小标志的样本数量,提升小目标检测精度。
- 实时检测帧率过低:
- 解决方案:使用轻量化模型、图像尺寸压缩、硬件加速、多线程推理,优先保证边缘设备的实时性(≥30fps)。
- 车辆检测漏检(遮挡/远距离):
- 解决方案:使用更高精度的模型(如yolov8l/yolov8x)、加入上下文信息融合、使用多帧跟踪算法(如ByteTrack),减少遮挡和远距离目标的漏检。
- 标注数据不足:
- 解决方案:使用数据增强(翻转、旋转、亮度调整、噪声添加)、迁移学习、生成式模型(GAN/Diffusion)生成模拟样本,扩充数据集。
浙公网安备 33010602011771号