ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

TinyPerson+YOLO实战:小目标检测数据集格式转换与训练调参全指南

TinyPerson+YOLO实战:小目标检测数据集格式转换与训练调参全指南 简介TinyPerson数据集是专为小目标检测设计的图像数据集共1532个样本全部提供VOC xml与YOLO txt双格式标注可直接服务于YOLO系列算法的小目标检测训练适合计算机视觉研究人员、算法工程师及相关专业学生使用。资源包共2000个文件包含1532个txt标签文件、467个xml标注文件及1个data.yaml配置文件共78.69MB其中YOLO txt已按训练集、验证集、测试集划分完毕并配备data.yaml可无缝接入YOLO训练流程省去繁琐的数据转换与配置工作。数据集聚焦于小型人物目标标注精细对安防监控、无人车、机器人视觉等领域的小目标识别任务具有实用价值尤其适用于人群计数、行为分析等场景。已有736人学习下载适合希望快速获取高质量小目标检测数据并开展模型训练与评估的开发者。1. 从TinyPerson数据集说起小目标检测的硬骨头做目标检测的朋友应该都有这种感受大目标怎么测都顺手一旦遇到小目标模型就像老花眼一样漏检、误检轮着来。TinyPerson数据集就是专门冲着这个问题来的它收录了大量远距离、低分辨率的人体目标很多目标在整张图里只有几个像素。这类场景在安防监控、无人机航拍、体育赛事直播里太常见了所以这个数据集在行业内口碑一直不错。我最初接触TinyPerson是在做一个高空巡检项目需要在无人机视角下检测人员目标。常规COCO预训练权重一上来小目标几乎全部漏掉mAP惨不忍睹。后来换成TinyPerson数据集做微调效果立竿见影。更关键的是这套数据集的标注本来就是公开的而且有人将其整理成了YOLO格式拿来就能直接训练省去了大量转换格式的体力活。今天这篇博文我就结合自己跑通TinyPerson YOLO的完整经历把数据集特点、格式转换、训练参数、常见坑一次说清楚。内容适合正在做小目标检测、想用YOLO微调提升精度的朋友也适合刚接触数据集标注格式转换的新手。我会把每一步的“为什么”讲透而不是扔给你一堆命令就完事。2. 数据集深挖TinyPerson为什么能打2.1 它到底特殊在哪TinyPerson数据集最早由远距离人体检测研究公开图像主要采集自海岸、海边、山地等开放场景人员目标密集且尺度极小。和COCO、VOC这类常规数据集相比它的核心特点是目标宽高通常在20像素以下甚至只有5到10像素。传统检测器在训练时容易把这些小目标当成噪点忽略掉而TinyPerson正是逼着模型去学会捕捉微弱的纹理和轮廓信息。数据量方面官方版本包含数百张高分辨率图像标注了数以万计的人体实例。虽然绝对数量和COCO的20万张没法比但它的“小目标密度”极高。一张4096x2160的大图里可能分布上百个人每个人都只占很小一块区域。这个分布特点决定了它特别适合做小目标检测的专项训练也适合用来验证YOLO系列在不同分辨率下的性能差异。2.2 为什么YOLO格式这么受欢迎YOLO格式本质上就是一个txt文件每行代表一个目标格式是class_id x_center y_center width height其中四个坐标都是相对于图片宽高的归一化值。这种格式的最大好处是不依赖图像尺寸缩放图片后标签依然有效训练时省去了很多预处理。而且Ultralytics YOLO的代码原生支持这种格式数据准备好之后直接改一个yaml文件就能开始训练。对比一下COCO格式JSON如果你用过Labelbox或者CVAT标注工具导出的往往是COCO格式那你就得写脚本把JSON里的bbox字段转换成归一化的xywh。这个转换本身不难但特别容易出错比如COCO的bbox是[x, y, width, height]而YOLO需要中心点坐标很多人在这里踩坑。所以TinyPerson数据集如果直接提供YOLO格式相当于是帮你把最脏最累的活干掉了。3. 动手准备把TinyPerson整理成YOLO能吃的格式3.1 目录结构这样建最省心不管你是从官方源下载原始标注还是直接获取YOLO格式的版本建议先统一目录结构。dataset/ ├── images/ │ ├── train/ │ ├── val/ ├── labels/ │ ├── train/ │ ├── val/ ├── data.yaml把所有训练图片放到images/train对应标签放到labels/train。图片和标签的文件名要严格一一对应不带后缀否则Ultralytics会直接跳过这些样本。我见过不少初学者把标签文件名写错或者一张图漏标一个txt训练时silence不说mAP还莫名低排查半天才发现是数据没对齐。3.2 从COCO或其他格式转YOLO格式如果你手里的TinyPerson是COCO标注别慌转格式的核心就三件事读JSON、算坐标、写txt。COCO标注中目标框是bbox: [x, y, width, height]左上角坐标和宽高。要转成YOLO的x_center y_center width height公式如下x_center (x width / 2) / image_width y_center (y height / 2) / image_height norm_width width / image_width norm_height height / image_height我用Python脚本处理过一次关键代码长这样import json import os def convert_coco_to_yolo(coco_json, img_dir, label_dir): with open(coco_json, r) as f: data json.load(f) images {img[id]: img for img in data[images]} categories {cat[id]: idx for idx, cat in enumerate(data[categories])} # 初始化每个图片的标签列表 img_labels {img_id: [] for img_id in images.keys()} for ann in data[annotations]: img_id ann[image_id] img_info images[img_id] img_w img_info[width] img_h img_info[height] cat_id ann[category_id] cls_id categories[cat_id] x, y, w, h ann[bbox] # 防止越界 w min(w, img_w - x) h min(h, img_h - y) x_center (x w / 2) / img_w y_center (y h / 2) / img_h nw w / img_w nh h / img_h # 过滤掉完全在图像外的目标 if x_center 0 or x_center 1 or y_center 0 or y_center 1: continue img_labels[img_id].append(f{cls_id} {x_center:.6f} {y_center:.6f} {nw:.6f} {nh:.6f}) for img_id, lines in img_labels.items(): img_info images[img_id] img_name img_info[file_name] label_name os.path.splitext(img_name)[0] .txt with open(os.path.join(label_dir, label_name), w) as f: f.write(\n.join(lines))这里有几个容易忽略的细节类别ID一定要从0开始。COCO原始category_id可能是1到80YOLO要求从0起连续编号所以必须做一次映射。转换时要做越界保护。有些标注框会超出图像边界虽然图上看不出来但归一化后坐标会大于1训练时YOLO会报错或者直接过滤影响数据量。空标签文件必须存在。如果一张图没有目标也要生成一个空txt否则训练时容易报列表越界。3.3 配置文件这么写data.yaml是YOLO训练的入口内容很简单path: /your_absolute_path/dataset train: images/train val: images/val nc: 1 names: [person]注意path尽量写绝对路径避免相对路径在不同环境下跑不通。nc要和类别数一致names列表里的顺序必须和标签txt里的class_id对应。4. 训练实操让YOLO在小目标上不再“瞎”4.1 环境搭建和基础命令我用的是Ultralytics YOLOv8安装太简单了一行命令pip install ultralytics如果要用GPU训练提前装好CUDA和PyTorch。然后直接跑yolo train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16这里modelyolov8s.pt用的是COCO预训练权重在小目标上已经有一定基础再用TinyPerson微调收敛速度快很多。如果你完全从零训练也可以换成yolov8s.yaml但对小目标检测来说预训练权重基本是必需品纯随机初始化很难训出理想效果。4.2 针对小目标调整的关键参数如果你直接跑默认参数大概率会失望因为TinyPerson里大量目标在640x640输入下只有几个像素YOLO的下采样倍数太高V8是32倍特征图上一个网格对应原图32x32区域小目标很容易被“平均”掉。这里有三个我实测有效的调整方向第一增大输入分辨率。把imgsz从640调到1280甚至1536小目标在特征图上占的像素数一下子多出4倍。代价是显存占用飙升训练速度变慢。我的实践是先用640预训练几个epoch再在1280上微调这样既省时间又能提升精度。如果你的显卡显存不够可以降低batch或者用rectTrue按比例统一边长尽可能利用显存。第二使用SAHI切片辅助。SAHI的意思是Slicing Aided Hyper Inference简单说就是把原图切成多张小图分别检测再合并结果。在推理阶段特别有效。训练阶段也可以在数据加载时自动切片Ultralytics的ultralytics.data里没有内置SAHI但我自己写过一个预处理脚本先把大图按固定步长切块过滤掉目标过小的区域再送入YOLO训练。实测mAP能提升5个点以上。第三数据增强不要开太猛。YOLO默认的hsv_h、hsv_s这些色彩增强对小目标影响不大但scale如果设得太大会把小目标缩到几个像素甚至消失导致标签失效。我建议把scale限制在0.3到0.5mosaic可以保留因为它能增加目标上下文信息但mixup对小目标不太友好容易把目标搅糊可以关掉。4.3 训练过程的监控与判断训练时不要只盯着loss曲线YOLO每个epoch还会输出box_loss、cls_loss、dfl_loss以及mAP50、mAP50-95。你需要重点看mAP50-95因为它对小目标更敏感数值越低越说明模型在小目标上挣扎。我自己训练时的典型曲线是前20个epoch mAP50快速上升之后小目标类的mAP50-95涨幅变缓这时可以加大epochs或者降低学习率继续磨。如果发现训练到一半loss不降反升很可能是学习率过大或者数据增强过度这时候优先调低lr0或者把mosaic关掉再试。还有一个细节Ultralytics训练结束后会在runs/detect/train目录下生成weights/best.pt和last.pt。很多人直接拿来用last.pt其实应该用best.pt——它是验证集上最优的结果泛化能力更好。5. 避坑实录那些能让你血压飙升的问题5.1 训练时参数量统计不一致是怎么回事这个问题在社区里经常被问“为什么训练一开始打印的参数量和训练完保存的模型参数量不一样”其实这不是Bug而是因为Ultralytics在训练开始时显示的是预训练权重的总参数包括检测头等所有模块而训练过程中如果你设置了freeze冻结某些层或者模型结构中有Detect模块里的某些层在训练过程中被静态量化或剪枝最终保存的best.pt可能包含的是经过EMA指数移动平均的权重整体统计时会略有差异。但绝大多数情况下总数应该是保持一致的。如果发现明显不一致多半是你在训练脚本里改动了模型结构比如替换了主干网络导致参数量本身就变了。可以用torchinfo打印每一层的参数来核对。5.2 重叠框和重复检测怎么处理小目标检测里重叠框很常见因为目标密集两个相邻的人可能边界重叠。YOLO默认的NMS阈值是0.5也就是两个框重叠超过50%时只保留一个。当你发现一个目标被输出两个框时可以降低conf阈值或提高iou阈值。在预测代码里这样调from ultralytics import YOLO model YOLO(best.pt) results model.predict(sourcetest.jpg, conf0.25, iou0.6)conf0.25表示阈值以上才保留iou0.6表示重叠超过60%才合并。小目标因为置信度普遍偏低如果conf设太高会漏检设太低会误检需要自己调一个平衡点。我的经验是0.3左右比较稳再配合max_det参数限制输出数量防止一张图输出几百个框导致后处理卡顿。5.3 小目标漏检严重怎么办如果你训练完还是漏检优先排查三个方向是不是输入分辨率太低把推理时的imgsz也调大训练和推理的分辨率应该保持一致。是不是类别不平衡TinyPerson里小目标多但如果你自己采集的数据里目标尺寸分布不均衡可以考虑对只有小目标的图片做过采样。是不是NMS把低级联输出过滤掉了小目标的置信度天然偏低可以在后处理时对低于阈值的框再按类别单独设一个更低的阈值。另外我强烈建议用SAHI做推理切片。TinyPerson的测试图像动辄4000x3000直接一次性送入YOLO就算调大分辨率也不够。用SAHI切成512x512的小块每一块独立检测再合并效果提升非常直观。5.4 模型导出后怎么给QT调用这个热词也被问烂了训练好的YOLO模型如何导出方便QT调用不管你是做桌面端还是嵌入式标准做法都是先把.pt转成ONNX再根据目标平台转成TensorRT或OpenVINO。Ultralytics一行命令导出ONNXyolo export modelbest.pt formatonnx导出后在QT里用ONNX Runtime加载运行核心代码就是初始化session预处理图像到640x640然后取输出做解码。如果你用的是TensorRT还要在导出ONNX时固定输入尺寸比如opset12再通过trtexec转成engine。这里有个坑TensorRT要求输入输出维度是静态的所以导出ONNX时要注意dynamicTrue和dynamicFalse的区别。QT里如果用动态维度每次推理都要重新分配内存性能很差建议导出静态维度。5.5 常见问题速查表现象可能原因解决方法训练loss不降学习率过大、数据标签错误降低lr0检查txt标签是否越界、类别ID是否正确验证mAP很低数据集划分不当、图片和标签不对应重建目录结构确认train/val无交集推理时大量重复框NMS阈值过低提高iou阈值合理设置conf导出ONNX失败模型包含动态尺寸或自定义算子固定imgsz更新ultralytics版本显存不足输入分辨率太高、batch太大降低batch使用rectTrue或梯度累积目标太小测不出来下采样倍数过大使用SAHI切片、提升分辨率、尝试P2层特征6. 最后的实操心得在把TinyPerson和YOLO结合的过程中我最大的感受是小目标检测不是单纯靠堆模型就能解决的事数据、分辨率、后处理缺一不可。TinyPerson数据集之所以受欢迎是因为它把“小”这件事做到了极致让你的模型不得不去关注细节。而YOLO格式的便捷性则让训练门槛降低了很多。如果你打算在这个方向继续扩展我建议把TinyPerson当成基础训练集再混入你自己场景的少量数据做二次微调。比如你要做道路裂缝检测可以先在TinyPerson上让模型学会捕捉小纹理再用裂缝数据微调往往比直接用裂缝数据训练效果更好。这个迁移思路是我在多个场景里验证过的属于典型的“先让小目标检测能力入脑再学具体业务”的路线。最后再提醒一句训练之前务必打开几张标签可视化图看看确认标注框和目标的贴合度。这一步花不了几分钟但能避开百分之八十的数据问题。数据这关过了后面的路就顺多了。本文还有配套的精品资源点击获取
返回列表