ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

YOLOv5 VOC2007开箱即用目标检测最小可行系统

YOLOv5 VOC2007开箱即用目标检测最小可行系统 简介本资源是一套开箱即用的YOLOv5目标检测实践项目面向计算机视觉初学者、AI课程设计者及算法工程师聚焦人物与动物两类典型目标的端到端识别任务。资源包含完整PyTorch实现代码、预配置数据处理脚本如voc_annotation.py、kmeans_for_anchors.py、训练/预测/评估模块train.py、predict.py、get_map.py以及配套的VOC格式标注数据集、模型权重.pth、锚点配置.txt和可视化截图等支撑从环境搭建、数据准备、模型训练到结果评估的全流程。压缩包共64个文件含24个核心Python源码、10个文本配置与说明文件、5个XML标注、3个Markdown文档及图像/字体/缓存等辅助文件整体20.2MB结构清晰、模块分工明确便于快速复现与二次开发。已有2873人学习下载提供可直接运行的工程框架、常见问题汇总与环境适配说明显著降低YOLOv5入门门槛助力实战能力快速提升。1. 这不是又一个YOLOv5“跑通即止”的Demo它自带VOC07人物动物双标签数据、可复现的KMeans聚类锚点、完整训练-验证-评估闭环新手照着train.py改两行就能出mAP老手能直接抠出kmeans_for_anchors.py和get_map.py嵌进自己pipeline你肯定见过太多标着“YOLOv5目标检测”的压缩包——解压后README.md里写着“请自行下载COCO”“环境需torch1.7”“训练前请修改config.yaml”结果配环境卡3小时、改路径报17个KeyError、跑完发现test集没标注根本没法算mAP……而这个yolov5-pytorch.rar从文件名到截图都透着一股“我真跑过”的踏实感。它不靠文档画饼而是把VOC2007_train/val拆分脚本voc_annotation.py、适配人物动物双类别的anchor聚类kmeans_for_anchors.py生成yolo_anchors.txt、带COCO-style评估的get_map.py、甚至训练日志logs/和预测示例predict.py全塞进一个包里。它解决的不是“YOLOv5能不能跑”而是“怎么让YOLOv5在你本地机器上用真实标注数据跑出可验证的mAP值”。适合两类人刚学CV想拿个看得见结果的入门者改classes [person, bird]就能训以及需要快速验证新数据增强策略或轻量化模块的工程师utils_coco/里封装了标准COCO eval逻辑比官方val.py更易调试。别被“人物动物识别”字面意思骗了——它本质是一套开箱即用的VOC格式目标检测最小可行系统MVP所有文件都在yolov5-pytorch-main/根目录下没有隐藏子模块没有requirement版本陷阱连requirements.txt都贴心地给了“你自己环境生成的”和“官方的”两个版本。2. 从零启动为什么选VOC而非COCO如何用voc_annotation.py把原始图片转成YOLOv5可训格式2.1 VOC数据结构与YOLOv5输入要求的硬性对齐YOLOv5官方默认吃的是images/labels/的扁平目录结构每张图对应一个.txt标签文件内容为class_id center_x center_y width height归一化坐标。但VOC2007原始数据是JPEGImages/Annotations/ImageSets/Main/三层嵌套XML标注里存的是绝对像素坐标。直接扔给YOLOv5会报错IndexError: list index out of range——因为train.py读2007_train.txt时每行是/path/to/VOCdevkit/VOC2007/JPEGImages/000001.jpg但找不到对应的labels/000001.txt。voc_annotation.py就是干这个桥接的它读取ImageSets/Main/下的train.txt和val.txt按行解析图片路径再根据Annotations/里的同名XML提取object的name映射到classes[person,bird]和bndbox四元组最后写入labels/。关键不是它做了什么而是它强制校验了三件事XML中name必须在classes列表里否则跳过该object避免KeyErrorbndbox坐标必须满足xmin xmax and ymin ymax否则丢弃防止负宽高导致loss nan图片实际尺寸必须大于bbox否则按比例缩放后归一化会溢出。提示voc_annotation.py第42行classes [person, bird]是你唯一需要改的地方。若要加cat类必须同步改三处此处列表、model_data/voc_classes.txt用于predict.py加载、以及train.py里的num_classes。漏一处训练时CrossEntropyLoss就报target 2 is out of bounds。2.2 执行voc_annotation.py的实操命令与输出验证先确保你的VOCdevkit目录结构正确VOCdevkit/ ├── VOC2007/ │ ├── Annotations/ # .xml文件 │ ├── JPEGImages/ # .jpg文件 │ └── ImageSets/ │ └── Main/ │ ├── train.txt # 每行一个图片ID如000001 │ └── val.txt # 同上然后进入yolov5-pytorch-main/目录执行python voc_annotation.py成功后你会看到新建VOCdevkit/VOC2007/ImageSets/Main/train_val_split.txt记录划分生成2007_train.txt和2007_val.txt绝对路径列表在VOCdevkit/VOC2007/下创建labels/目录内含与JPEGImages/同名的.txt文件如000001.txt。验证是否成功打开任意一个生成的.txt应类似0 0.523 0.387 0.214 0.456 # person类中心点(0.523,0.387)宽高(0.214,0.456) 1 0.812 0.654 0.132 0.298 # bird类注意0和1是classes列表索引不是原始XML里的字符串。如果看到2或负数说明voc_annotation.py里classes没对齐。2.32007_train.txt和2007_val.txt的深层作用不只是路径列表这两个文件是YOLOv5数据加载器的“契约”。train.py里dataset LoadImagesAndLabels(...)会逐行读取2007_train.txt对每行路径做三件事用cv2.imread()读图根据路径推导labels/xxx.txt路径并读取对图像做mosaic、random_perspective等增强utils/datasets.py里定义。所以它们必须是绝对路径voc_annotation.py已自动处理且labels/必须与JPEGImages/在同一级目录。常见翻车点有人把VOCdevkit放在D盘而yolov5-pytorch-main在C盘voc_annotation.py生成的路径是D:/VOCdevkit/...但train.py运行时工作目录是C:/yolov5-pytorch-main/导致open(D:/...)失败。解决方案要么把VOCdevkit移到yolov5-pytorch-main/同级目录推荐要么在voc_annotation.py第35行手动拼接相对路径不推荐易错。3. 锚点不是玄学用kmeans_for_anchors.py生成适配人物动物尺度分布的yolo_anchors.txt3.1 为什么YOLOv5不能直接用官方COCO anchorsYOLOv5官方发布的yolov5s.yaml里anchors是基于COCO数据集80类含小物体如cup、remote聚类得到的典型值如[10,13, 16,30, 33,23]第一层小anchor。但VOC2007里person平均宽高约200x400pxbird约50x35px尺度分布比COCO更集中、小物体更少。直接套用COCO anchors会导致小鸟检测召回率暴跌小anchor匹配不上大anchor IoU太低被过滤compute_loss()里obj_loss异常高正样本anchor匹配失败训练后期box_loss下降缓慢anchor与gt bbox形状不匹配。kmeans_for_anchors.py就是为VOC2007定制的——它读取所有labels/xxx.txt里的width height归一化前的像素值用KMeans聚类出9个anchorYOLOv5的3个检测头各3个输出yolo_anchors.txt供模型加载。3.2 运行kmeans_for_anchors.py的参数控制与结果解读执行前确认两点VOCdevkit/VOC2007/labels/已由voc_annotation.py生成kmeans_for_anchors.py第12行cluster_number 9保持默认YOLOv5固定9 anchor。然后运行python kmeans_for_anchors.py成功后生成yolo_anchors.txt内容为9个数字一行如12,15, 21,32, 34,28, 45,62, 68,52, 89,102, 112,87, 135,142, 168,189这9个数按顺序分成3组对应YOLOv5的P3/P4/P5三个检测头检测头anchor索引典型用途P3 (80x80)1,2,3小物体小鸟P4 (40x40)4,5,6中等物体半身人P5 (20x20)7,8,9大物体全身人看你的yolo_anchors.txt如果前3个数都30如12,15,21说明聚类认可小鸟是主要小物体如果后3个150如168,189说明人群体较大。这不是调参是数据说话——你的数据里小鸟多anchor自然小人多且大anchor自然大。3.3 如何把yolo_anchors.txt喂给YOLOv5模型YOLOv5的PyTorch实现里anchor加载在models/yolo.py的Model.__init__()中。关键代码段yolo.py第128行附近# 读取yolo_anchors.txt with open(model_data/yolo_anchors.txt) as f: anchors f.read().strip().split(,) anchors [float(x) for x in anchors] self.anchors torch.tensor(anchors).view(3, -1, 2) # shape: (3,3,2)注意路径model_data/yolo_anchors.txt。所以你必须把生成的yolo_anchors.txt复制到model_data/目录下原包里已有但内容是空的或旧的。切记不要手动改yolov5s.yaml里的anchors字段——这个包的train.py是直接读文件的yaml里的anchors只是占位符。注意kmeans_for_anchors.py默认读VOCdevkit/VOC2007/labels/如果你的labels在别处改第22行label_path VOCdevkit/VOC2007/labels/。另外它会跳过width0 or height0的bbox防除零但不会跳过widthimg_width的错误标注——这种脏数据得靠voc_annotation.py的校验提前过滤。4. 训练-验证-评估闭环train.py核心参数详解与get_map.py的COCO-style mAP计算4.1train.py里必须改的5个参数不是全部是保底能跑通的打开train.py找到if __name__ __main__:下方的parser.add_argument部分。新手只需动这5个参数默认值必须改说明--datadata/voc.yaml✅改为model_data/voc.yaml原包里model_data/下有适配双类的yaml--cfgmodels/yolov5s.yaml✅确保路径存在若用yolov5m改为此路径--weights从头训⚠️首次训留空续训填logs/last.pt--epochs50✅VOC2007数据量小30轮足够收敛--batch-size16✅根据显存调2080Ti可设321080Ti设16GTX1660设8其他参数如--imgsz输入尺寸默认640对VOC够用--name日志名建议改成voc_person_bird方便区分。4.2get_map.py为什么它比val.py更适合VOC评估YOLOv5官方val.py输出的是P/R/mAP0.5但VOC社区公认指标是mAP0.5:0.95IoU阈值0.5到0.95步长0.05的平均。get_map.py正是为此设计它读2007_val.txt里的图片用训练好的模型如logs/best.pt推理生成detection-results/下每个图片的.txt格式class confidence xmin ymin xmax ymax再读VOCdevkit/VOC2007/Annotations/里的XML生成ground-truths/下对应.txt最后调用utils_coco/里的voc_eval.py按VOC标准计算mAP0.5。执行命令python get_map.py成功后输出VOC07 metric: person: AP 0.782 bird: AP 0.653 mAP0.5: 0.718这才是VOC论文里写的mAP。而val.py输出的mAP0.5通常高2-3个百分点因计算方式不同不可直接对比。4.3logs/目录里的秘密如何从results.txt反推训练问题train.py每轮保存logs/results.txt格式为# Epoch GPU_mem box obj cls total targets img_size 0/49 3.20G 0.07234 0.02156 0.01245 0.10635 128 640 1/49 3.20G 0.06821 0.01987 0.01123 0.10031 128 640关键看三列box: 定位损失越低越好0.05算健康obj: 置信度损失反映前景背景分离能力0.02正常cls: 分类损失双类任务0.015合理。如果box一直0.08可能是anchor不匹配回看kmeans_for_anchors.py如果obj远高于cls说明正样本少检查voc_annotation.py是否漏标了bird如果total在30轮后不降反升大概率过拟合加--augment或减--epochs。提示get_map.py依赖model_data/voc_classes.txt里的类别顺序。若你改了classes[person,bird]必须确保voc_classes.txt也是person bird顺序错一位mAP就会全乱——person的AP算到bird头上。5. 避坑指南训练/预测中90%的报错都来自这5个边界条件5.1 现象train.py报错FileNotFoundError: [Errno 2] No such file or directory: VOCdevkit/VOC2007/labels/000001.txt原因voc_annotation.py没运行或运行后labels/目录不在VOCdevkit/VOC2007/下或2007_train.txt里路径写错了比如少了VOCdevkit/前缀。解决进入yolov5-pytorch-main/目录ls ../VOCdevkit/VOC2007/labels/ | head -n 3确认文件存在head -n 5 2007_train.txt看第一行路径是否以VOCdevkit/开头若路径是/home/user/VOCdevkit/...而你Windows系统删掉/home/user只留VOCdevkit/...。5.2 现象predict.py运行后img/下无结果图控制台卡住不动原因predict.py第28行image cv2.imread(img_path)读不到图常见于img_path是相对路径如img/test.jpg但当前工作目录不是yolov5-pytorch-main/图片格式非.jpg/.jpeg/.pngYOLOv5默认只读这三种OpenCV版本太低4.0不支持某些编码。解决运行前cd yolov5-pytorch-main把测试图放img/目录重命名为test.jpg在predict.py第28行后加print(fReading {img_path}, exists: {os.path.exists(img_path)})调试。5.3 现象kmeans_for_anchors.py报错ValueError: Input contains NaN原因labels/xxx.txt里有0 0.5 0.5 0 0宽高为0KMeans遇到NaN。解决grep -r 0 0$ VOCdevkit/VOC2007/labels/找出所有宽高为0的txt手动删除这些行或用脚本清理# clean_zero_anchors.py import os for txt in os.listdir(VOCdevkit/VOC2007/labels/): with open(fVOCdevkit/VOC2007/labels/{txt}, r) as f: lines [l for l in f if not l.strip().endswith( 0 0)] with open(fVOCdevkit/VOC2007/labels/{txt}, w) as f: f.writelines(lines)5.4 现象get_map.py输出mAP0.5: 0.000但predict.py能画出bbox原因detection-results/和ground-truths/里的文件名不一致。get_map.py要求000001.txt必须对应000001.jpg的预测结果和000001.xml的真实标注。解决ls detection-results/ | head -n 3和ls ground-truths/ | head -n 3对比文件名若detection-results/里是000001.jpg.txt而ground-truths/里是000001.txt批量重命名cd detection-results rename s/\.jpg\.txt$/.txt/ *.jpg.txt5.5 现象train.py报错RuntimeError: CUDA out of memory即使batch-size1原因--imgsz设太大如1280或--workers设太高如8或显存被其他进程占满。解决先nvidia-smi看显存占用杀掉无关进程--imgsz 416VOC分辨率够用--workers 0Windows必须设0Linux可设2-4加--cache参数把数据预加载进内存减少GPU等待。6. 进阶技巧用summary.py可视化模型结构用utils_coco/复用COCO评估逻辑以及我每次训完必做的三件事6.1summary.py5行代码看清YOLOv5的“黑匣子”YOLOv5模型像俄罗斯套娃——models/yolo.py里Model类继承nn.Module但内部self.model是动态构建的。summary.py就是解构它的手术刀。运行python summary.py --cfg models/yolov5s.yaml --weights --imgsz 640输出关键信息Model Summary: 225 layers, 7.2M parameters, 15.8M gradients, 16.5 GFLOPs但真正有用的是每层的input_size和output_size找到Detect层通常是最后一层看output_size是否为[1, 3, 80, 80, 6]P3头——6514 bbox 1 obj 1 cls找到Conv层看weight形状是否为[32, 3, 3, 3]输入3通道RGB输出32通道如果output_size里出现None说明模型构建失败常因--cfg路径错。这比print(model)直观10倍——你知道P3头输出80x80网格P4是40x40P5是20x20就知道为什么小物体要靠P3检测。6.2utils_coco/把VOC评估逻辑迁移到自己的数据集utils_coco/里voc_eval.py是VOC标准实现但它依赖get_map.py生成的detection-results/和ground-truths/。如果你想在自定义数据集如my_dataset/上用只需三步写my_dataset_to_voc.py把你的JSON标注转成VOC XML参考voc_annotation.py的XML生成逻辑用voc_annotation.py的逻辑生成my_dataset/labels/和my_dataset_train.txt修改get_map.py第32行voc_devkit_path my_dataset/然后跑python get_map.py。这样你就不用重写mAP计算——utils_coco/已经帮你把VOC的PR曲线、AP积分全实现了。6.3 我每次训完必做的三件事血泪经验立刻备份logs/和model_data/logs/best.pt是模型权重logs/results.txt是训练曲线model_data/yolo_anchors.txt是数据指纹。我用tar -czf voc_person_bird_$(date %Y%m%d).tar.gz logs/ model_data/自动打包命名含日期永不混淆。用predict.py在img/里跑3张图截图存logs/predict_demo.png不是为了好看而是验证best.pt能否加载、NMS是否生效、类别名是否对齐。一张图错后面全白忙。把2007_val.txt里前10张图单独拎出来人工核对detection-results/的txt打开000001.txt看confidence是否0.5xmin是否xmax。曾有一次confidence全为0.001查出是model_data/voc_classes.txt里多了一个空行导致类别索引偏移。从那以后我每次训完都强制走一遍这三步——不是仪式感是给自己的后悔药。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进