
简介行人实例分割数据集面向智能安防、自动驾驶感知、服务机器人交互及计算机视觉研究等场景为需要训练高精度行人识别与轮廓分割模型的开发者提供可直接使用的工业级数据。资源包共2000个文件以1226个txt标注文件、772张jpg图像为主另含1个yaml配置与1份docx说明文档压缩包约96.18MB原生YOLO实例分割格式可直接对接YOLOv5、YOLOv8等主流框架。数据按训练集1131张、验证集48张、测试集47张完整划分每个行人实例包含50余个多边形轮廓点能精确捕捉复杂姿态与遮挡情况并覆盖监控、航拍等多视角及不同光照、天气条件。标注经交叉校验保证一致性除实例分割外还可迁移至目标检测、姿态估计与行人重识别等任务。目前已有277人学习下载适合作为算法基准测试与项目落地的实用数据支撑。1. 行人实例分割数据集1131 张训练图能跑出什么名堂监控画面里两个人挨着走检测框叠在一起你根本分不清谁是谁——这是目标检测在人群场景下的经典翻车现场。实例分割要解决的就是这个问题不只告诉你这里有人还要把每个人的像素级轮廓勾出来。这份行人实例分割数据集训练集 1131 张、验证集 48 张、测试集 47 张标注格式是原生 YOLO 实例分割格式每个行人实例带 50 轮廓点坐标。它适合三类人想跑通 YOLOv8-seg 全流程的新手、需要行人精细轮廓做安防或自动驾驶感知的从业者、以及拿它做 Re-ID 或姿态估计前置处理的算法工程师。数据覆盖监控视角和航拍视角包含不同光照和天气条件文件名里能看到 FudanPed、PennPed、man、person、building 等来源说明它是从多个公开行人数据集整合而来。下面从目录结构开始一步步拆到训练和推理。2. 拆开压缩包目录结构、标注格式与选型理由2.1 拿到数据先看什么目录树与文件命名规律解压后你会看到图片和对应的标注文件。从项目正文给出的文件名来看图片命名遵循原始名_640_jpg.rf.哈希.jpg的规律其中640表示图片短边被缩放到 640 像素rf.后面是 Roboflow 导出时生成的唯一哈希。标注文件通常是同名的.txt放在labels/train、labels/val、labels/test三个子目录下。先跑一遍目录统计确认图片和标注一一对应# 统计各子集图片数量 find images/train -name *.jpg | wc -l # 预期 1131 find images/val -name *.jpg | wc -l # 预期 48 find images/test -name *.jpg | wc -l # 预期 47 # 检查是否有图片缺失对应标注 for f in images/train/*.jpg; do base$(basename $f .jpg) [ -f labels/train/$base.txt ] || echo 缺失标注: $base done这段脚本做两件事第一段用find wc -l核对三个子集的图片数是否与简介一致第二段遍历训练集图片检查每个.jpg是否有同名.txt。如果输出为空说明配对完整。常见问题是 Roboflow 导出时图片和标注分在不同文件夹解压后路径对不上这时候需要手动建软链接或调整data.yaml里的路径。2.2 YOLO 实例分割标注长什么样一行一个实例YOLO 实例分割的标注格式和目标检测不同。目标检测是class x_center y_center width height五个值实例分割是class x1 y1 x2 y2 ... xn yn第一个是类别索引后面是所有归一化到 0~1 的多边形顶点坐标。打开一个标注文件看看# 查看第一个训练标注文件的前两行 head -n 2 labels/train/FudanPed00010_png.rf.24bc61111192b90017b72ae025a6eaaa.txt输出大概是这样0 0.412 0.335 0.428 0.340 0.445 0.352 0.451 0.370 ... 0 0.712 0.520 0.725 0.531 0.738 0.545 0.741 0.560 ...每行代表一个行人实例0是类别索引这里只有 Person 一类后面是轮廓点坐标。简介说每个实例 50 轮廓点意味着每行大约有 100 个数值。这个密度足以刻画复杂姿态和遮挡边缘比矩形框信息量大得多。用 Python 快速验证一下每行的点数分布import os, glob point_counts [] for txt in glob.glob(labels/train/*.txt): with open(txt) as f: for line in f: parts line.strip().split() # 第一个是类别剩下的是 x,y 交替 n_points (len(parts) - 1) // 2 point_counts.append(n_points) print(f实例总数: {len(point_counts)}) print(f最少轮廓点: {min(point_counts)}) print(f最多轮廓点: {max(point_counts)}) print(f平均轮廓点: {sum(point_counts)/len(point_counts):.1f})如果平均点数在 50 以上说明标注精度符合简介描述。如果发现某些行只有 4 个点那可能是矩形框被误转成了多边形需要检查导出配置。2.3 为什么选 YOLO 格式而不是 COCO训练效率与框架兼容性COCO 格式用 JSON 存所有标注一个文件几十 MB每次训练前要全量加载解析内存占用高。YOLO 格式一行一个实例按需读取数据加载器可以并行解析训练时 I/O 瓶颈小。更重要的是YOLOv8-seg 原生支持 YOLO 分割格式不需要写自定义 Dataset 类。如果你后续要转 COCO 做基准测试用ultralytics自带的转换工具就行反过来从 COCO 转 YOLO 则容易在类别映射和坐标归一化上出错。这份数据直接给 YOLO 格式省掉了转换环节对新手友好。常见做法是先用 YOLOv8n-seg 小模型快速验证数据可用性再换更大的模型调精度。3. 从零跑通 YOLOv8-seg 训练配置、命令与参数调优3.1 环境准备与 data.yaml 配置先装 ultralytics建议用虚拟环境避免依赖冲突python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install ultralytics然后在数据集根目录建data.yaml这是 YOLO 训练的数据入口# data.yaml path: /absolute/path/to/dataset # 数据集根目录用绝对路径 train: images/train val: images/val test: images/test nc: 1 # 类别数这里只有 Person 一类 names: [Person] # 类别名称顺序必须和标注里的索引一致path一定要写绝对路径相对路径在不同工作目录下会找不到文件。nc和names必须和标注文件里的类别索引对应——如果标注里出现了1但你只定义了0训练时会报索引越界。验证配置是否正确from ultralytics import YOLO model YOLO(yolov8n-seg.pt) # 只做数据校验不训练 model.train(datadata.yaml, epochs1, imgsz640, batch4, dry_runTrue)dry_runTrue会加载数据但不实际训练能快速暴露路径错误和标注格式问题。3.2 启动训练关键参数怎么设确认数据没问题后正式启动训练yolo segment train \ datadata.yaml \ modelyolov8s-seg.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/segment \ nameperson_seg逐个说参数model选yolov8s-seg.pt而不是n版本因为 1131 张图不算多n容易欠拟合s在精度和速度之间平衡更好imgsz640和图片短边一致避免额外缩放损失batch16在 8GB 显存下能跑如果 OOM 就降到 8lr00.01是初始学习率小数据集建议比默认的 0.01 再低一点比如 0.005防止早期震荡patience20表示验证集指标 20 轮不提升就早停避免过拟合。训练过程中重点看mask mAP50和box mAP50两个指标实例分割任务里 mask 指标比 box 更能反映轮廓质量。3.3 训练日志怎么看损失曲线与指标解读训练开始后runs/segment/person_seg/下会生成results.csv和 TensorBoard 日志。用 pandas 快速看关键指标走势import pandas as pd df pd.read_csv(runs/segment/person_seg/results.csv) df.columns df.columns.str.strip() # 列名可能带空格 # 看最后 10 轮的 mask mAP print(df[[epoch, metrics/mAP50(M), metrics/mAP50-95(M)]].tail(10))metrics/mAP50(M)是 mask 在 IoU0.5 时的平均精度metrics/mAP50-95(M)是 IoU 从 0.5 到 0.95 的平均值。行人轮廓分割里如果 mAP50 能到 0.85 以上、mAP50-95 在 0.55 以上说明模型对轮廓的拟合不错。如果 box mAP 高但 mask mAP 低通常是轮廓点不够密或者标注边缘有噪声。损失曲线方面train/seg_loss应该稳步下降如果震荡剧烈把lr0再降一半或者把batch调大让梯度更平滑。4. 推理、验证与踩坑排查4.1 用训练好的模型跑推理单图与批量训练完成后用best.pt跑推理from ultralytics import YOLO model YOLO(runs/segment/person_seg/weights/best.pt) # 单张图片推理 results model(images/test/FudanPed00031_png.rf.92ab4d3aaacb8e0ddfbd96551f783e36.jpg, conf0.4) # 批量推理整个测试集 results model(images/test/, conf0.4, saveTrue, projectruns/predict)conf0.4是置信度阈值低于这个值的检测框会被过滤。行人场景下建议从 0.4 开始试如果漏检多就降到 0.25误检多就升到 0.5。saveTrue会把带掩码的可视化结果存到runs/predict下。检查推理结果里的掩码数量for r in results: if r.masks is not None: print(f{r.path}: 检测到 {len(r.masks)} 个行人实例) else: print(f{r.path}: 未检测到行人)如果测试集 47 张图里大部分都能检出合理数量的行人说明模型泛化能力可以。如果某些图完全没检出先确认这些图里确实有行人再检查是不是光照或视角太极端。4.2 避坑指南五条血泪经验现象一训练 loss 不下降一直卡在初始值附近。原因通常是data.yaml里的nc和标注类别数不一致或者标注文件里有空行导致解析失败。解决方法是先跑dry_runTrue校验数据再用脚本扫描所有标注文件统计出现的类别索引import glob classes set() for txt in glob.glob(labels/train/*.txt): with open(txt) as f: for line in f: if line.strip(): classes.add(int(line.split()[0])) print(f标注中出现的类别索引: {classes})如果输出不是{0}说明有异常类别需要清理或重新映射。现象二mask mAP 远低于 box mAP。原因可能是轮廓点太少或标注边缘不贴合目标。简介说 50 点但实际数据里可能有个别实例只有十几个点。解决方法是过滤掉点数少于 20 的实例或者用形态学操作平滑掩码边缘。另一个原因是imgsz设得太小轮廓细节在缩放中丢失把imgsz从 640 提到 960 试试。现象三验证集指标波动大时好时坏。验证集只有 48 张样本量太小单轮指标受个别难样本影响大。解决办法是看多轮移动平均或者把patience调大不要因为某一轮掉点就停。常见做法是训练结束后取最后 10 轮里 mask mAP 最高的权重而不是直接用最后一轮。现象四推理时显存溢出。批量推理整个测试集时如果图片分辨率不一致YOLO 会按最大尺寸 padding显存占用飙升。解决方法是推理时加imgsz640强制统一尺寸或者逐张推理而不是批量。现象五导出的 ONNX 模型推理结果和 PyTorch 不一致。这是实例分割模型导出时的经典坑。YOLOv8-seg 导出 ONNX 需要指定opset12以上且后处理里的 mask 系数计算在 ONNX 里可能有精度差异。解决方法是导出后用onnxruntime跑一遍验证对比掩码 IoU如果差异超过 2% 就检查导出参数yolo export modelruns/segment/person_seg/weights/best.pt formatonnx opset12 imgsz6404.3 用验证集做阈值扫描找到最佳 conf 和 iou默认conf0.25、iou0.7不一定适合你的场景。用验证集做一轮扫描from ultralytics import YOLO import numpy as np model YOLO(runs/segment/person_seg/weights/best.pt) best_f1, best_conf 0, 0 for conf in np.arange(0.1, 0.9, 0.1): metrics model.val(datadata.yaml, confconf, iou0.6, splitval) f1 metrics.seg.f1 if f1 best_f1: best_f1, best_conf f1, conf print(fconf{conf:.1f} mask F1{f1:.4f}) print(f最佳 conf{best_conf:.1f}, F1{best_f1:.4f})metrics.seg.f1是分割任务的 F1 分数综合了精度和召回。扫描后选 F1 最高的 conf 作为推理阈值。iou参数控制 NMS 的合并阈值人群密集场景下建议调到 0.5~0.6避免把相邻行人合并成一个实例。5. 进阶技巧把分割掩码转成 Re-ID 可用的裁剪图行人实例分割的一个高价值下游任务是 Re-ID行人重识别。Re-ID 需要把每个行人裁剪成独立小图再送进特征提取网络。用分割掩码做裁剪比矩形框裁剪干净得多因为背景像素被掩码过滤掉了。下面这段代码把测试集里每个行人实例抠出来存成带透明通道的 PNGimport cv2 import numpy as np from ultralytics import YOLO from pathlib import Path model YOLO(runs/segment/person_seg/weights/best.pt) out_dir Path(reid_crops) out_dir.mkdir(exist_okTrue) results model(images/test/, conf0.4, retina_masksTrue) for r in results: img r.orig_img if r.masks is None: continue masks r.masks.data.cpu().numpy() # shape: (N, H, W) boxes r.boxes.xyxy.cpu().numpy() for i, (mask, box) in enumerate(zip(masks, boxes)): x1, y1, x2, y2 map(int, box) # 把掩码缩放到原图尺寸 mask_resized cv2.resize(mask, (img.shape[1], img.shape[0])) mask_binary (mask_resized 0.5).astype(np.uint8) # 裁剪区域 crop img[y1:y2, x1:x2] crop_mask mask_binary[y1:y2, x1:x2] # 生成 RGBA 图背景透明 rgba cv2.cvtColor(crop, cv2.COLOR_BGR2BGRA) rgba[:, :, 3] crop_mask * 255 name Path(r.path).stem cv2.imwrite(str(out_dir / f{name}_person{i}.png), rgba) print(f保存 {name}_person{i}.png 尺寸 {crop.shape[:2]})retina_masksTrue让掩码输出保持原图分辨率避免缩放导致的边缘模糊。mask 0.5是二值化阈值如果边缘有锯齿可以改成 0.3 让掩码稍微膨胀。生成的 RGBA 图可以直接送进 Re-ID 模型背景透明意味着数据增强时不会引入背景噪声。这个流程跑完测试集 47 张图大概能产出 100~200 个行人裁剪图足够做小规模 Re-ID 验证。从那以后我每次拿到新的分割数据集都强制先跑一遍点数统计和类别索引扫描确认标注质量再开训练——这两步花不了五分钟但能省掉后面几小时的无效等待。希望帮到你。本文还有配套的精品资源点击获取