零基础实战基于YOLO与Darknet的Cityscapes街景语义分割全流程解析第一次接触语义分割时我被那些能将街景照片中每个像素精确分类的算法深深吸引。Cityscapes数据集作为业界公认的街景理解基准其复杂的场景和精细的标注为算法开发提供了绝佳素材。但当我真正尝试用YOLO和Darknet复现语义分割时却发现从数据准备到模型训练处处是坑——标签映射不清晰、配置文件参数晦涩、可视化工具匮乏。本文将用最直白的语言带你一步步打通整个流程。1. 环境配置与数据准备1.1 开发环境搭建推荐使用Ubuntu 20.04 LTS系统配合NVIDIA显卡驱动建议版本≥470。先安装CUDA 11.3和cuDNN 8.2.1# 安装基础依赖 sudo apt-get install build-essential git cmake libopencv-dev # 验证CUDA安装 nvcc --version # 输出应显示CUDA 11.3接着编译OpenCV 4.5.5需开启CUDA支持cmake -D WITH_CUDAON -D OPENCV_DNN_CUDAON .. make -j$(nproc) sudo make install1.2 Cityscapes数据集处理下载数据集后目录结构应如下cityscapes/ ├── leftImg8bit/ │ ├── train/ # 2975张训练图像 │ ├── val/ # 500张验证图像 │ └── test/ # 1525张测试图像 └── gtFine/ ├── train/ # 精细标注 ├── val/ └── test/关键步骤是34类到19类的标签映射。使用官方脚本转换python cityscapesscripts/preparation/createTrainIdLabelImgs.py常见问题处理报错No module named cityscapesscripts解决export PYTHONPATH$PYTHONPATH:/path/to/cityscapesScripts警告忽略polygons.json文件它们仅用于标注工具2. Darknet框架深度适配2.1 源码修改要点从Darknet官方仓库fork后需进行以下关键修改网络结构在src/parser.c中增加分割头处理逻辑损失函数修改src/segmentation_layer.c实现像素级交叉熵数据加载调整src/data.c支持Cityscapes的PNG标签读取典型修改示例片段// segmentation_layer.c void forward_segmentation_layer(...) { for(i 0; i l.batch*l.inputs; i){ int class max_index(truth i*l.classes, l.classes); float delta (pred[i*l.classes class] - 1); l.delta[i*l.classes class] delta * l.scale; } }2.2 配置文件详解创建maskyolo.data指定数据路径classes19 traindata/cityscapes/train.txt validdata/cityscapes/val.txt namesdata/maskyolo.names backupbackup/网络配置segment.cfg关键参数[net] batch8 subdivisions4 width512 height256 [segmentation] filters19 # 对应19个类别3. 训练优化与调试技巧3.1 高效训练策略启动训练命令./darknet segmenter train cfg/maskyolo.data cfg/segment.cfg -gpus 0,1推荐采用以下超参数组合参数推荐值作用说明learning_rate0.001初始学习率burn_in1000学习率预热步数max_batches50000最大迭代次数policysteps学习率调整策略steps30000学习率衰减节点3.2 常见报错排查CUDA out of memory降低batch_size或增加subdivisions添加-clear参数释放显存碎片标签值越界检查maskyolo.names是否包含全部19类验证标签转换脚本是否正确执行Loss震荡不收敛尝试-dont_show关闭实时显示调整momentum0.9和decay0.00054. 结果可视化与性能优化4.1 Python可视化方案替代Matlab的Python可视化代码import cv2 import numpy as np def visualize_segmentation(image_path, pred_path): # 加载Cityscapes官方调色板 palette np.array([ [128, 64, 128], # road [244, 35, 232], # sidewalk [70, 70, 70], # building ... # 其他18类颜色 ], dtypenp.uint8) pred cv2.imread(pred_path, cv2.IMREAD_GRAYSCALE) colored palette[pred.flatten()].reshape(*pred.shape, 3) cv2.imwrite(result.png, colored)4.2 模型量化加速使用TensorRT优化推理速度./darknet export cfg/segment.cfg segment_final.weights segment.engine性能对比方法分辨率FPS (Titan RTX)mIoU原始Darknet512x2564558.2TensorRT FP32512x2568358.1TensorRT FP16512x25612157.95. 进阶技巧与扩展应用5.1 类别不平衡处理Cityscapes中road类占比高达30%需在损失函数中加入类别权重float class_weights[] {0.8, 1.2, ..., 2.0}; // 19个权重值 for(i 0; i l.batch*l.inputs; i){ int class max_index(truth i*l.classes, l.classes); float delta (pred[i*l.classes class] - 1) * class_weights[class]; l.delta[i*l.classes class] delta * l.scale; }5.2 多模型集成方案结合YOLOv4的检测结果提升分割精度先用YOLOv4检测交通标志等小物体将检测框区域输入分割网络融合两个网络的输出结果集成后的mIoU可提升3-5个百分点尤其改善小物体识别效果。
保姆级教程:手把手教你用YOLO和Darknet搞定Cityscapes街景语义分割(附数据集处理避坑指南)
发布时间:2026/6/4 14:16:45
零基础实战基于YOLO与Darknet的Cityscapes街景语义分割全流程解析第一次接触语义分割时我被那些能将街景照片中每个像素精确分类的算法深深吸引。Cityscapes数据集作为业界公认的街景理解基准其复杂的场景和精细的标注为算法开发提供了绝佳素材。但当我真正尝试用YOLO和Darknet复现语义分割时却发现从数据准备到模型训练处处是坑——标签映射不清晰、配置文件参数晦涩、可视化工具匮乏。本文将用最直白的语言带你一步步打通整个流程。1. 环境配置与数据准备1.1 开发环境搭建推荐使用Ubuntu 20.04 LTS系统配合NVIDIA显卡驱动建议版本≥470。先安装CUDA 11.3和cuDNN 8.2.1# 安装基础依赖 sudo apt-get install build-essential git cmake libopencv-dev # 验证CUDA安装 nvcc --version # 输出应显示CUDA 11.3接着编译OpenCV 4.5.5需开启CUDA支持cmake -D WITH_CUDAON -D OPENCV_DNN_CUDAON .. make -j$(nproc) sudo make install1.2 Cityscapes数据集处理下载数据集后目录结构应如下cityscapes/ ├── leftImg8bit/ │ ├── train/ # 2975张训练图像 │ ├── val/ # 500张验证图像 │ └── test/ # 1525张测试图像 └── gtFine/ ├── train/ # 精细标注 ├── val/ └── test/关键步骤是34类到19类的标签映射。使用官方脚本转换python cityscapesscripts/preparation/createTrainIdLabelImgs.py常见问题处理报错No module named cityscapesscripts解决export PYTHONPATH$PYTHONPATH:/path/to/cityscapesScripts警告忽略polygons.json文件它们仅用于标注工具2. Darknet框架深度适配2.1 源码修改要点从Darknet官方仓库fork后需进行以下关键修改网络结构在src/parser.c中增加分割头处理逻辑损失函数修改src/segmentation_layer.c实现像素级交叉熵数据加载调整src/data.c支持Cityscapes的PNG标签读取典型修改示例片段// segmentation_layer.c void forward_segmentation_layer(...) { for(i 0; i l.batch*l.inputs; i){ int class max_index(truth i*l.classes, l.classes); float delta (pred[i*l.classes class] - 1); l.delta[i*l.classes class] delta * l.scale; } }2.2 配置文件详解创建maskyolo.data指定数据路径classes19 traindata/cityscapes/train.txt validdata/cityscapes/val.txt namesdata/maskyolo.names backupbackup/网络配置segment.cfg关键参数[net] batch8 subdivisions4 width512 height256 [segmentation] filters19 # 对应19个类别3. 训练优化与调试技巧3.1 高效训练策略启动训练命令./darknet segmenter train cfg/maskyolo.data cfg/segment.cfg -gpus 0,1推荐采用以下超参数组合参数推荐值作用说明learning_rate0.001初始学习率burn_in1000学习率预热步数max_batches50000最大迭代次数policysteps学习率调整策略steps30000学习率衰减节点3.2 常见报错排查CUDA out of memory降低batch_size或增加subdivisions添加-clear参数释放显存碎片标签值越界检查maskyolo.names是否包含全部19类验证标签转换脚本是否正确执行Loss震荡不收敛尝试-dont_show关闭实时显示调整momentum0.9和decay0.00054. 结果可视化与性能优化4.1 Python可视化方案替代Matlab的Python可视化代码import cv2 import numpy as np def visualize_segmentation(image_path, pred_path): # 加载Cityscapes官方调色板 palette np.array([ [128, 64, 128], # road [244, 35, 232], # sidewalk [70, 70, 70], # building ... # 其他18类颜色 ], dtypenp.uint8) pred cv2.imread(pred_path, cv2.IMREAD_GRAYSCALE) colored palette[pred.flatten()].reshape(*pred.shape, 3) cv2.imwrite(result.png, colored)4.2 模型量化加速使用TensorRT优化推理速度./darknet export cfg/segment.cfg segment_final.weights segment.engine性能对比方法分辨率FPS (Titan RTX)mIoU原始Darknet512x2564558.2TensorRT FP32512x2568358.1TensorRT FP16512x25612157.95. 进阶技巧与扩展应用5.1 类别不平衡处理Cityscapes中road类占比高达30%需在损失函数中加入类别权重float class_weights[] {0.8, 1.2, ..., 2.0}; // 19个权重值 for(i 0; i l.batch*l.inputs; i){ int class max_index(truth i*l.classes, l.classes); float delta (pred[i*l.classes class] - 1) * class_weights[class]; l.delta[i*l.classes class] delta * l.scale; }5.2 多模型集成方案结合YOLOv4的检测结果提升分割精度先用YOLOv4检测交通标志等小物体将检测框区域输入分割网络融合两个网络的输出结果集成后的mIoU可提升3-5个百分点尤其改善小物体识别效果。