1. 环境部署从零搭建Unet开发环境第一次接触车道线识别项目时环境配置是最容易卡住新手的环节。我清楚地记得自己第一次配置PyTorch环境时因为CUDA版本不匹配导致整整折腾了两天。为了避免大家重蹈我的覆辙这里分享一套经过实战验证的环境配置方案。首先需要准备的是conda环境管理工具。推荐使用miniconda而不是anaconda前者更加轻量且完全够用。安装完成后我们创建一个专门用于车道线检测项目的Python环境conda create -n unet python3.8 conda activate unet选择Python3.8版本是经过多次测试后的最佳选择既能兼容大多数深度学习框架又不会因为版本过高导致某些库无法安装。接下来安装PyTorch时有个关键细节需要注意 - 一定要先确认自己显卡支持的CUDA版本。可以通过nvidia-smi命令查看nvidia-smi假设你的CUDA版本是11.x那么对应的PyTorch安装命令应该是pip install torch2.1.0 torchvision0.16.0 torchaudio2.1.0 --index-url https://download.pytorch.org/whl/cu118这里有个实用技巧如果下载速度慢可以添加清华镜像源加速pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt环境配置完成后建议运行一个简单的PyTorch测试脚本验证环境是否正常import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.rand(2,3).cuda())如果这三行代码都能正常执行输出说明你的深度学习环境已经准备就绪。我曾经遇到过torch.cuda.is_available()返回False的情况后来发现是因为PyTorch版本与CUDA版本不匹配导致的。2. 获取与准备Unet模型直接从GitHub克隆项目是最简单的方式git clone https://github.com/AnshChoudhary/Lane-Detection-UNet cd Lane-Detection-UNet这个仓库包含了一个专门用于车道线检测的Unet实现。Unet之所以在语义分割任务中表现出色主要得益于它的编码器-解码器结构和跳跃连接设计。编码器部分通过连续的卷积和池化操作提取图像特征而解码器部分则通过上采样恢复空间分辨率。跳跃连接将编码器的特征图与解码器的特征图拼接帮助模型更好地定位目标。对于车道线检测任务Unet有几个关键优势能够处理不同宽度和形状的车道线对光照变化和遮挡有一定鲁棒性实时性较好适合部署在实际应用中模型结构主要在model.py文件中定义。如果你想要调整模型深度或宽度可以修改这里的参数。例如增加通道数可以提升模型容量但也会增加计算量。3. 数据集制作全流程详解3.1 labelme安装与使用技巧数据标注是项目中最耗时的环节但也是决定模型效果的关键因素。经过多个项目的实践我发现labelme是最适合车道线标注的工具。安装labelme需要特别注意Python版本问题conda create -n labelme python3.10 conda activate labelme pip install labelme安装完成后启动labelme界面labelme在标注过程中有几个提高效率的技巧开启Auto Save功能避免忘记保存使用快捷键CtrlR旋转图像便于标注不同角度的车道线按住Ctrl键可以微调控制点位置使用Edit Label功能批量修改标签名称我曾经标注过2000多张车道线图像总结出几个标注原则对于虚线车道线应该标注为连续的直线遇到遮挡情况根据可见部分合理推测完整车道线不同车道线类型实线、虚线、双黄线等最好用不同标签区分3.2 数据集结构与格式转换Unet模型需要特定的数据集结构。标准的目录结构如下data/ ├── train/ │ ├── images/ # 原始图像 │ └── masks/ # 标注掩码 └── val/ ├── images/ # 验证图像 └── masks/ # 验证掩码labelme生成的JSON标注文件需要转换为模型所需的掩码图像。这个转换过程有几个关键点需要注意掩码图像应该是单通道的灰度图不同类别的车道线应该使用不同的灰度值车道线宽度应该适当太细会导致训练困难下面是一个改进版的转换脚本增加了多类别支持import cv2 import numpy as np def json_to_mask(json_path, output_path, class_mapping{lane: 255}): with open(json_path) as f: data json.load(f) img cv2.imread(data[imagePath]) h, w img.shape[:2] mask np.zeros((h, w), dtypenp.uint8) for shape in data[shapes]: label shape[label] if label not in class_mapping: continue points np.array(shape[points], dtypenp.int32) cv2.polylines(mask, [points], False, class_mapping[label], thickness3) cv2.imwrite(output_path, mask)这个脚本可以处理多类别标注只需要在class_mapping字典中定义不同标签对应的灰度值即可。4. 模型训练技巧与参数调优4.1 训练脚本配置开始训练前需要检查train.py中的几个关键配置# 数据路径配置 train_dataset LaneDataset( img_dirdata/train/images, mask_dirdata/train/masks, transformtrain_transform ) # 模型参数 model UNet(n_channels3, n_classes1) optimizer torch.optim.Adam(model.parameters(), lr1e-4) criterion torch.nn.BCEWithLogitsLoss()几个需要特别注意的参数学习率(lr)车道线检测通常使用1e-4到1e-5之间的学习率损失函数BCEWithLogitsLoss适合二分类任务输入通道RGB图像设置为3灰度图像设置为14.2 训练过程监控启动训练命令CUDA_VISIBLE_DEVICES0 python train.py --epochs 100 --batch-size 8训练过程中要监控几个关键指标训练损失(train loss)应该稳步下降验证IoU(val IoU)应该逐步提升学习率可以根据验证集表现动态调整如果遇到损失不下降的情况可以尝试减小学习率增加数据增强检查标注质量调整模型容量我通常会在训练时添加TensorBoard日志方便可视化训练过程from torch.utils.tensorboard import SummaryWriter writer SummaryWriter() for epoch in range(epochs): # ...训练代码... writer.add_scalar(Loss/train, train_loss, epoch) writer.add_scalar(IoU/val, val_iou, epoch)4.3 数据增强策略适当的数据增强可以显著提升模型泛化能力。对于车道线检测推荐使用以下增强组合train_transform A.Compose([ A.HorizontalFlip(p0.5), A.RandomBrightnessContrast(p0.2), A.Rotate(limit10, p0.5), A.GaussNoise(var_limit(10.0, 50.0), p0.3), A.Normalize(mean(0.485, 0.456, 0.406), std(0.229, 0.224, 0.225)) ])注意增强的幅度不宜过大否则会导致车道线变形严重。我曾经因为旋转角度设置过大(30度)导致模型无法学习到正确的车道线特征。5. 模型测试与性能优化训练完成后可以使用inference.py脚本测试模型效果python inference.py --weight best_model.pth --image test.jpg测试阶段有几个实用技巧对输出概率图进行二值化时阈值通常设为0.5可以使用形态学操作(开运算、闭运算)后处理结果对于视频测试可以考虑添加时序平滑处理如果发现模型在某些场景表现不佳可以收集更多类似场景的数据进行微调调整模型输入分辨率尝试不同的后处理参数在实际部署时可以考虑使用TorchScript将模型导出为更高效的格式model.eval() example torch.rand(1, 3, 512, 512).cuda() traced_script_module torch.jit.trace(model, example) traced_script_module.save(unet_lane_detection.pt)这个导出的模型可以在C环境中高效运行适合部署到嵌入式设备或车载系统。