
简介面向翻越围栏检测任务的目标检测数据集包含1680张已标注图片覆盖climbing(翻越)与person两类目标共计2454个边界框。这类数据可直接用于训练行人越界识别模型适用于安防监控、园区周界防范、公共场所行为分析等场景也适合需要在真实场景中验证检测算法的开发者与研究人员。压缩包共2000个文件主要以VOC格式XML和YOLO格式TXT标注文件为组成部分并附带说明文档压缩后整体约100.25MB格式规整无需额外转换即可接入常见目标检测训练框架。所有标注均使用labelImg绘制矩形框完成标注类别清晰、框位置合理内含部分增强图片可帮助提升模型泛化性能介意增强数据影响的用户请酌情考虑。目前已有598人学习下载对翻越栏杆场景的检测建模与实验对比具有实用参考价值。1. 翻越围栏检测数据集1680 张样本里藏着姿态识别与标注验证两件事智慧园区和工地监控里「翻越围栏」报警是最容易翻车的场景之一。普通人体目标检测只能输出 person 框而「翻越」是一个姿态动作——人挂在栏杆上、跨腿、翻身这些瞬间的宽高比和正常行走完全不同。直接拿行人检测模型硬套要么漏报要么误报到没法用。这份名为「翻越栏杆围栏数据集」的包解决的就是这个问题它把 1680 张图片同时给了 Pascal VOC 和 YOLO txt 两套标注标注类别固定为climbing和person两类其中 climbing 独立框出「正在翻越」的人体区域用来专门训练动作检测分支。适合的目标很明确做安防巡检、工地边界预警、园区周界防护的目标检测模型训练或者给已有行人检测模型加一路 climbing 检测头。需要提醒的是包里混有部分增强图片训练前要先做一轮数据体检否则增强图会悄悄拉低精度。2. 先拆文件与标注xyxr_ship 系列命名的数据包构成2.1 jpg、xml、txt 三类文件的一一对应关系解压后目录里的组成和大多数目标检测数据集包一致图片、VOC 标注 XML、YOLO 标注 txt 三个平铺目录文件名前缀统一为xyxr_ship_数字。从命名能看出这批数据来自某个巡检视频序列抽帧数字编号是帧号或原始图片 ID。jpg、xml、txt 三者按文件名严格一一对应共 1680 组。对这类「图文标」三件套我的第一动作永远是跑一遍对应关系检查防止某张图缺标注或标注文件空转。常见做法是用一个简短脚本来数数import os jpg_dir JPEGImages xml_dir Annotations txt_dir labels jpgs {f.replace(.jpg, ) for f in os.listdir(jpg_dir) if f.endswith(.jpg)} xmls {f.replace(.xml, ) for f in os.listdir(xml_dir) if f.endswith(.xml)} txts {f.replace(.txt, ) for f in os.listdir(txt_dir) if f.endswith(.txt)} print(jpg:, len(jpgs), xml:, len(xmls), txt:, len(txts)) print(缺xml:, jpgs - xmls) print(缺txt:, jpgs - txts) print(多标注:, (xmls | txts) - jpgs)这段脚本用文件主名去重后做集合差能直接暴露「有图没标」「有标没图」两类问题。注意集合运算要求三个目录在同一层路径按实际解压位置改。执行结果应当是三组数量都等于 1680差集为空。如果出现了差集非空优先怀疑文件名大小写不一致或 Windows 解压时产生了隐藏副本。2.2 两类标注框数盘点climbing 2060 框、person 394 框为何差距大包说明里给了明确统计climbing 框 2060 个person 框 394 个总框 2454 个。也就是说平均每张图 1.46 个框且绝大多数框属于 climbing。这个比例在一个翻越检测场景里是合理的——标注规则是「对类别进行画矩形框」一个正在翻越围栏的人通常同时具备 climbing 和 person 两个属性。但实际标注时如果标注员认为攀爬动作已经足够表达人物位置就只给 climbing 框只有姿态不明显、仅作为行人出现时才单独补 person 框。于是 person 类被压缩到了 394 框成了小样本类别。这个框数分布直接影响模型训练策略。climbing 框数充足可以按正常权重训person 框只有 394如果直接用 YOLOv8 默认配置训练person 类的召回率大概率上不去。我一般会做两件事第一训练时给 person 类提高 loss 权重第二在验证时单独看 person 类的 PR 曲线而不是只盯 mAP 均值。如果打算把 person 当作「正常行人」负样本用那另一个思路是保留 climbing 单类训练把 person 框当作难负例参与背景抑制这在后文第 4 章再展开。2.3 增强图片混入的影响如何识别并隔离增强图包说明特别标注「含部分增强图片」。增强图是混在 1680 张里一起交付的不是独立目录。常见做法是增强脚本在保存时给文件名加_aug或_flip后缀但这个包的文件清单里并没有这类后缀说明生成增强图时保留了原名或只改编号。所以想靠文件名区分行不通只能从像素和标注坐标两个维度做体检。增强手段不外乎水平翻转、亮度调整、加噪声、随机裁剪。其中水平翻转对翻越检测影响最大——翻越动作有左右方向性翻转后坐标要在 XML 里同步做镜像处理。如果增强脚本只翻转了图片、忘记改 bndbox你会在某几张 XML 里看到 xmin 大于 xmax或者框的位置和图上目标不重合。快速检查办法是对每张图的标注框计算宽高比再用宽高比分布做聚类明显偏移的样本基本就是翻转后坐标没同步的产物。更保险的做法是直接抽样可视化标注框这在第 5 章避坑里会展开细讲。3. 把 VOC 转成 YOLO 格式XML 解析脚本与边界坐标坑3.1 坐标读取与归一化xmin/xmax 要除以图像实际宽高这个包本身已经同时给了 VOC XML 和 YOLO txt严格说不需要你自己转格式。但拿到手第一件事我建议用脚本把 XML 重新解析一遍用解析结果和自己手里已有的 txt 做交叉验证。因为网上转来转去的数据集最容易出事的就是 VOC 到 YOLO 的坐标换算。先写一个解析 XML 并输出 YOLO 格式文本的脚本逻辑上完全复用 labelImg 导出的规则import os import xml.etree.ElementTree as ET voc_dir Annotations yolo_dir labels class_map {climbing: 0, person: 1} for xml_name in os.listdir(voc_dir): if not xml_name.endswith(.xml): continue tree ET.parse(os.path.join(voc_dir, xml_name)) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) txt_lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: continue box obj.find(bndbox) x_min float(box.find(xmin).text) y_min float(box.find(ymin).text) x_max float(box.find(xmax).text) y_max float(box.find(ymax).text) x_center (x_min x_max) / 2.0 / img_w y_center (y_min y_max) / 2.0 / img_h box_w (x_max - x_min) / img_w box_h (y_max - y_min) / img_h txt_lines.append(f{class_map[name]} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(os.path.join(yolo_dir, xml_name.replace(.xml, .txt)), w) as f: f.write(\n.join(txt_lines))这个脚本有几个关键点。root.find(size/width)是路径式查找避免逐层 find 的繁琐坐标全部转成 float 再算中心点防止整数除法丢精度输出格式固定六位小数和 YOLO 惯例保持一致。class_map 里climbing设定为 0、person设定为 1这个顺序必须和后续训练用的数据集 yaml 完全一致否则类别会错位。脚本循环里没有做越界裁剪这是故意的——目的是让越界框真实暴露出来而不是被静默修复。3.2 用脚本验证已有 txt 与 XML 是否矛盾包里自带的 txt 不一定和 XML 完全匹配尤其是增强图混入后。验证的核心思路是用 3.1 的脚本生成一份新 txt和包内自带的 txt 逐文件逐行比对import os gen_dir labels_converted src_dir labels_original for name in os.listdir(src_dir): if not name.endswith(.txt): continue with open(os.path.join(src_dir, name)) as f: origin_lines sorted(f.read().strip().splitlines()) with open(os.path.join(gen_dir, name)) as f: conv_lines sorted(f.read().strip().splitlines()) if origin_lines ! conv_lines: print(不一致:, name) print( 原始:, origin_lines) print( 转换:, conv_lines)注意排序后再比较因为 XML 里 object 顺序和 txt 行序未必一致。如果有不一致项多数情况下是增强图的镜像翻转坐标没同步其次是某些文件里存在类别名大小写错误比如Climbing带了大写。此时需要手动翻看对应图片确认不能盲目选择信任任意一边。这里要特别提示这个包的说明里特意写了「不包含分割路径的 txt 文件仅仅包含 jpg 图片以及对应的 VOC 格式 xml 文件和 yolo 格式 txt 文件」。这句话的意思是txt 里只有类别 x_center y_center width height这五行式不会有指向分割掩码的文件路径不要在做语义分割时误当成 segmentation label 用。3.3 越界与退化坐标检查宽高为 0、负值、超出图像范围归一化坐标有个天然缺陷坐标一旦越界视觉上不容易发现。因为 1.5 和 0.5 在文本层面没有任何异常特征必须靠程序判断。下列检查项是我拿到任何数据集都会强制跑一遍的bad 0 for name in os.listdir(labels): path os.path.join(labels, name) with open(path) as f: for line in f: parts line.strip().split() cls int(parts[0]) xc, yc, w, h map(float, parts[1:]) if w 0 or h 0: print(非正宽高:, name, line) bad 1 if xc 0 or xc 1 or yc 0 or yc 1: print(中心点越界:, name, line) bad 1 print(异常行数:, bad)中心点越界是最致命的因为 YOLO 训练时中心点跑到图外模型会学到「目标在画面外」这种错误先验。宽高为 0 的退化框通常来自标注时误点了同一点两次这类样本不删掉的话会让 loss 出现 NaN 或异常震动。检查时注意box 略微超出图像边缘不一定会被判为越界因为中心点在框内、w/h 大于 1 也可能发生更严格的做法是把 box 的左边界 x_min (xc - w/2) 也校验一遍。对这份数据集而言由于增强图的存在越界风险主要集中在翻转后坐标未同步的文件上。4. 用 YOLOv8 训练翻越检测数据集配置与超参建议4.1 目录组织与数据集 yaml 配置训练前先把数据重新组织成 YOLO 标准目录结构。不管保不保留原来的平铺目录我习惯新建一个干净的文件夹按 train/val 划分后放入 images 和 labels这是 YOLOv8 的默认布局方便后续跑验证脚本。划分时优先保证 climbing 框和 person 框在两个集合里的比例接近整体分布不能简单随机切否则 val 集里可能完全没有 person 框。path: /workspace/climbing_fence train: images/train val: images/val names: 0: climbing 1: personyaml 里path是绝对路径或相对路径的根目录train和val都相对path而言。names 的序号顺序必须和前面 class_map 保持一致climbing 是 0person 是 1。如果顺序反了训练出的模型会把两类目标完全对调推理结果直接报废。我见过不止一次有人把 names 写成{0: person, 1: climbing}导致部署时才发现检测框类别全部互换。4.2 类别失衡处理给 person 单独调 loss 权重接下来是训练命令模型选 yolov8s 还是 yolov8n根据推理设备决定。安防场景一般部署在 Jetson 或边缘盒子我推荐用 yolov8s 起步精度和速度比较均衡。命令行里加cls参数控制分类 loss 权重对 person 小样本类别单独加权yolo detect train \ dataclimbing_fence.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ patience20 \ cls0.7 \ seed2024imgsz640是输入分辨率翻越动作发生在围栏附近目标尺寸通常不大640 是稳妥选择追求小目标精度可以上 960但显存占用会明显上升。batch16在 16G 显存上比较安全如果 OOM 就降到 8。patience20表示连续 20 个 epoch 验证集指标不提升就早停防止无效空转。cls0.7是分类 loss 系数比默认的 0.5 略高作用是让模型在分类层面更关注样本少的 person 类。这个值不要调太高太高会让定位 loss 权重被稀释框的位置反而不准。还有一个细节这个数据集里绝大部分图只有 climbing 框person 框只出现在少数图中。这意味着多数训练批次里完全没有 person 正样本模型容易在前期快速倾向 climbing后期再纠偏就很难。常见做法是用 Ultralytics 提供的class_weight或自定义采样器但更省事的方式是把 person 框所在的图片在训练列表里复制两份用重复曝光弥补样本不足。注意要同时复制对应的 label 文件并在数据集划分时保证这些图只进入 train 不进入 val避免验证集被复制样本污染。4.3 验证时机用 val 集逼近真实监控场景训练过程中不要只看 train loss。YOLOv8 每个 epoch 结束会自动在 val 集上计算 mAP50 和 mAP50-95两个指标都要盯。翻越检测场景里mAP50 比 mAP50-95 更有参考价值因为监控报警只看 IoU 是否够得上阈值iou 0.5 的定位精度已经足够触发联动。训练到 120 epoch 左右如果 mAP50 曲线开始走平而 mAP50-95 还在缓慢爬升说明模型在精定位上还有余量可以继续训反过来如果 mAP50 掉头向下说明过拟合开始早停会介入。验证时还有一个容易被忽略的点val 集里也要保留一部分包含 person 单独框的图片。因为部署场景是「翻越的人 正常路过的人」同时出现模型如果只会报 climbing 不会报 person报警逻辑里「climbing 出现且 person 不在附近」这类规则就没法实现。我在训练时会把 val 集做成混合样本保证每个 batch 的验证结果里两类框都有出现。5. 避坑与常见问题增强图、坐标越界与类别失衡5.1 现象增强图片导致模型误检左右镜像动作训练初期模型在验证集上把「人从栏杆左侧跨过」识别成「从右侧跨过」或者一个未翻越的人被报成 climbing。原因水平翻转的增强图没有同步修改标注坐标。标注框跟着图片镜像后应该左右互换但如果增强脚本只对图片做了cv2.flip忘了解析 XML 并更新 xmin/xmax那么标注框还停留在原位置实际目标已经在镜像后的位置。模型在训练时反复看到「图片里的人在左边框却在右边」学到了错误的语义映射。解决按第 3.2 节的脚本对全部文件做一致性比对找出不一致项后删除或重新标注。如果增强工具用的是 Albumentations它对 bbox 有自动同步功能但需要确认bbox_params里设置了formatpascal_voc且label_fields正确。对于这个数据集最简单可靠的做法是把确认有问题的增强图整张剔除保留原图训练。5.2 现象模型对普通行人产生高置信度 climbing 输出部署后正常走路、蹲下系鞋带、搬东西的人被误报成翻越。原因person 类只有 394 框模型没有足够样本学会「这是一个行人」的语义于是把所有直立人体都推向 climbing 类。尤其在增强图加入后人体姿态被拉伸或裁剪进一步模糊了两类的边界。解决第一优先策略是补充 person 类样本把爬楼梯、跳台阶、搬运等相似姿态图片加入负样本集第二是调高 cls 权重如 4.2 节第三是在后处理逻辑里加高度/位置规则——翻越动作发生时人体框通常横跨围栏区域可以要求检测框与围栏 ROI 区域重叠达到一定比例才触发报警。这个数据集的标签里没有围栏本身的标注所以 ROI 需要自己在部署工程里画。5.3 现象txt 文件被误当作分割标注或路径文件使用有开发者把包内 txt 读进分割模型或者期望 txt 里包含 segment 坐标导致训练直接报错。原因YOLO 检测格式和分割格式都叫 txt但内容结构完全不同。检测 txt 每行只有 5 个数分割 txt 每行是类别 x1 y1 x2 y2 ...不定长。这个包的说明已经明确「不包含分割路径的 txt」且只在矩形框标注模式下产物是 5 列。误用的本质是没读说明直接套了别的框架。解决无论是 VOC 训练还是 YOLO 训练加载前先检查第一行的列数。检测格式固定 5 列多于 5 列说明格式不对。另外 txt 文件路径不要作为数据集的segments参数传入只用于detect任务。5.4 现象某些 XML 里出现 xmin 大于 xmax 或坐标带小数使用 labelImg 打开部分文件时提示 bndbox 格式异常训练脚本读取时报assert错误。原因labelImg 手动标注时误操作或者增强脚本修改坐标时做了不合适的坐标改写。bbox 坐标在 VOC 标准里是整数像素但增强后的坐标可能是浮点。xmin 大于 xmax 说明翻转同步逻辑写反了直接导致 IoU 计算为 0训练 loss 异常跳动。解决批量修复这类文件把 xmin 和 xmax 重新排序xmin, xmax sorted([xmin, xmax]) ymin, ymax sorted([ymin, ymax])修复后重新输出 txt。同时跑一遍 3.3 的越界检查确保坐标都在 [0,1] 区间内。这个修复必须在训练之前完成YOLO 框架对负宽高坐标的处理策略不一有的直接跳过该标注有的会报错中断训练。6. 进阶验证置信度阈值曲线与场景外测试6.1 用置信度-召回曲线反推部署阈值训练结束后best.pt 里默认的置信度阈值是 0.25但在翻越检测这类安防场景0.25 往往太低会导致大量低置信度误报。正确做法是从验证集结果里导出置信度-召回曲线找到精确率和召回率的平衡点。YOLOv8 的 val 模式可以直接输出 JSON 格式的详细评估结果from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) metrics model.val(save_jsonTrue, conf0.001)conf0.001是故意调低让模型输出所有可能的检测候选之后分析每个置信度档位的表现。打开 JSON 里每个类别的f1_curve或pr_curve数据找到 F1 分数最高的阈值点。对 climbing 类别我会额外要求该阈值下召回率不低于 0.9哪怕牺牲一些精确率对 person 类精确率优先避免把行人全部报成 climbing。这个分析能直接指导部署参数。比如 f1 最优阈值是 0.52就把它写进推理脚本的conf参数。如果发现两个类的最优阈值差异很大可以拆成两路输出climbing 用低阈值person 用高阈值避免用同一个 conf 值约束两类。6.2 场景外测试用未参与训练的监控片段检验泛化数据集验证指标再好也不代表现场能用。我的习惯是训练结束后找几段室内外监控视频做实景测试测试片段必须包含三类内容正常行人行走、在围栏附近弯腰停留、真正翻越动作。不要求这些片段里有标注只看模型输出的行为是否符合预期。测试时关注两个指标翻越动作的检出延迟和误报频率。把视频按帧推理统计从动作开始到模型第一次给出 climbing 高置信度输出之间的帧数误报频率则统计非翻越片段里平均每分钟出现多少次 conf 超过阈值的 climbing 输出。翻越动作通常持续 1 到 3 秒如果检出延迟超过 10 帧说明 imgsz 可以调大或者模型可以换重一档。我做这类数据集的习惯流程是先用脚本做完整性检查再抽样可视化标注然后才进训练。可视化标注这步能发现所有自动检查发现不了的语义错误比如框没有贴住目标、把栏杆本身框进 climbing。对这份数据集增强图的混入让这一步格外重要。从那以后我每次拿到含增强的数据集都强制走一遍「解析 XML 重算坐标 → 对比原 txt → 抽样画框目检」的流程宁可多花一小时也不在训练完才发现数据有问题。希望帮到你。本文还有配套的精品资源点击获取