简介:面向监控场景中打架行为识别的目标检测数据集及配套训练方案,适合安防算法工程师、科研学习者用于打架检测模型训练与项目落地。数据集含约3000张真实监控场景图片,覆盖街道、酒吧、商店、公交车、监狱、空旷地等多样环境,并兼顾两人打架与多人斗殴情形;标注采用 labelimg 完成,提供 VOC、COCO、YOLO 三种标准格式,标签统一为 fight,可直接接入 YOLO 等常见算法训练。资源为1个PDF文件,大小5.63MB,内含数据集说明及获取方式,同时附赠支持 GPU(GPUs)、CPU、Mac(M芯片) 的平台一体化 YOLO11 一键训练脚本与博主训练日志,便于快速复现、对比调参并完整跑通监控场景打架检测流程。当前已有854人学习下载,适合作为监控场景通用打架检测数据的有力补充。
1. 打架检测数据集:监控场景里最该先跑通的单类目标检测
做监控视觉的人应该都有同感:打架检测比普通行人检测更吃数据。行人检测有大量公开数据集可以预训练,但打架这种动作类目标,样本少、场景杂、遮挡多,拿通用模型硬跑,漏检和误检都很明显。这份资源我拆过一遍,核心是 3000 张真实监控画面下的打架图片,统一标注为fight单类,同时给了 VOC、COCO、YOLO 三种格式标签,另附一套 YOLO11 一键训练脚本,覆盖 GPU、CPU、Mac M 芯片三平台。对正在做安防监控、智慧园区、街面治理项目的工程师来说,它可以作为训练集直接开工;对刚入门目标检测的开发者,它也是一套能完整跑通「数据 → 训练 → 验证」的闭环样例。下面按我实际拆包的顺序,把数据组织、脚本参数、训练日志和踩坑点一层层说清楚。
2. 数据集的底细:3000 张图、单类 fight,场景分布与三种标注格式的来龙去脉
2.1 场景构成与类别设计:单类标注的取舍
拿到资源先看数据分布。3000 张图不是简单从网上爬的,而是按监控真实视角组织的,街道、酒吧、商店、公交车、监狱、空旷地都有覆盖,既有两人打架,也有多人群体事件。这点很关键——监控摄像头通常架在高处俯拍,人和人重叠严重,如果数据全是平视角度,训练出来的模型换个视角就废。我抽查了部分图片,俯拍占比高,人物目标尺寸从大全身到半身不等,遮挡情况比常规 VOC 类数据集更接近实战。
类别只有fight一个。有人会觉得「单类是不是太浪费」,但从工程角度看完全合理:打架检测的本质是做异常事件告警,你只需要输出「有没有打架、打架的框在哪」,不需要区分拳击、推搡、摔倒这些子类。单类标注还能提升标注一致性,减少类间边界模糊带来的误检。真正要补的是负样本——也就是正常行走、拥抱、搬运的监控画面,如果只用这份数据集训练,建议额外补充一批普通行为数据做背景类,否则部署后容易把一些剧烈运动误报成打架。
2.2 labelimg 标注与三种格式的转换逻辑
资源里明确说用了 labelimg 标注。labelimg 默认产出的是 PASCAL VOC 格式的 XML 文件,每个目标一个<bndbox>节点。而 COCO 的 JSON 需要将 XML 里的filename、size、object信息重组为images、annotations、categories三个数组;YOLO 的 txt 格式则进一步把边界框转换成归一化的class_id center_x center_y width height五元组。这一圈转下来有几个易错点:
- XML 里坐标是绝对像素值,YOLO 里要除以图片宽高,且中心点坐标是
(xmin + xmax)/2算出再归一化; - COCO 的
bbox格式是[x, y, width, height],而 YOLO 的center_x是中心点,不是左上角,两者转换时经常有人写错; - 如果 labelimg 的 XML 里
difficult字段为 1,转 YOLO 时一般要跳过,否则会引入低质量正样本干扰训练。
我拆包时核对过三种格式的标签数量,3000 张图的fight框总数与 VOC 的<object>节点数、COCO 的annotations数组长度、YOLO 的 txt 行数是能对上的。这点很重要,因为我见过不少网上流传的数据集只给 YOLO txt,想转 COCO 还得自己逆向,坐标稍错就白训。这份资源直接给了三种格式,省掉转换时间,也方便你用不同框架做对比。
2.3 文件目录结构与格式对照
解压后目录大致如下:
fight_dataset/ ├── images/ # 原始 JPEG 图片 │ ├── train/ # 训练集图片 │ └── val/ # 验证集图片 ├── labels/ # YOLO 格式 txt(与 images 子目录一一对应) │ ├── train/ │ └── val/ ├── VOC/ # VOC 格式 xml(按 train/val 划分子目录) ├── COCO/ # COCO 格式 json(train.json / val.json) └── yolo11_train_scripts/ # 一键训练脚本 + data.yaml + 训练日志提示:VOC 和 COCO 目录只作为标签交付,实际训练 YOLO11 时,
labels目录下的 txt 才是直接使用的标注。如果你后续要跑 Faster R-CNN 或 DETR,再用 VOC/COCO 格式导入即可。
需要特别说明的是,训练集和验证集的划分是随机的,但划分比例合理(常见是 8:2 或 9:1,资源内以实际为准)。我建议在动手前先看一眼两集里的场景分布是否均衡,避免酒吧场景全在训练集、公交场景全在验证集,那样验证 mAP 会虚高或失真。
3. 把三种格式接到 YOLO11 训练:脚本参数与数据组织
3.1 YOLO11 需要的目录结构与 data.yaml 写法
实际用资源里的脚本训练前,需要理解 YOLO11(ultralytics 库)对数据组织的要求。它不直接读取 VOC 或 COCO,而是读取 YOLO txt 标注,并通过data.yaml指定图片路径和类别表。资源里的data.yaml大概长这样:
# data.yaml path: ./fight_dataset # 数据集根目录 train: images/train # 训练图片相对路径 val: images/val # 验证图片相对路径 nc: 1 # 类别数量 names: 0: fight # 类别名,必须与 txt 标签中的 class_id 对应逻辑说明:path是根路径,train和val相对于path拼接;nc为 1 是因为只有 fight 一个类;names的索引必须从 0 开始,与 YOLO txt 文件里的第一个数字一致。如果 txt 里写的是0 0.5 0.4 0.2 0.3,这里的names就把索引 0 映射到fight。
参数说明:如果你的图片不放在images/train而是自定义目录,比如./data/frames,需要同步改train和val的相对路径;如果是绝对路径,也可以直接写/absolute/path/to/images/train。切忌把标签路径写进data.yaml——YOLO 训练时默认认为标签与图片同目录,或者自动在labels子目录里找同名 txt。
3.2 一键训练脚本:GPU/CPU/Mac 三平台差异
资源里给的脚本,核心是一个 Python 文件,内部用ultralytics做训练,同时针对不同平台调整参数。这在实战中非常实用,因为 YOLO11 的默认参数是为 GPU 设计的,直接拿到 Mac M 芯片上跑,动不动就因内存不足或算子不支持而崩。我简化后的脚本逻辑如下:
# train_script.py import platform import torch from ultralytics import YOLO if __name__ == "__main__": device = "0" # 默认用第一张 GPU batch = 16 workers = 4 # 判断 Mac M 芯片(Apple Silicon) is_apple_silicon = (platform.system() == "Darwin") and (platform.machine() in ("arm64", "arm64e")) # 判断纯 CPU(无可用 CUDA 设备) has_cuda = torch.cuda.is_available() if is_apple_silicon: device = "mps" # 使用 Apple Metal 加速 batch = 8 # 显存/内存有限,减小 batch workers = 2 print("[INFO] Apple Silicon detected, use MPS backend.") elif not has_cuda: device = "cpu" batch = 4 workers = 0 # CPU 模式下多进程反而拖慢 print("[INFO] No GPU found, use CPU backend.") # 加载预训练权重(可选) model = YOLO("yolo11n.pt") # 开始训练 model.train( data="data.yaml", epochs=100, batch=batch, imgsz=640, device=device, workers=workers, project="runs/fight_detect", name="exp_fight", patience=20, save_period=10, verbose=False, )逻辑说明:脚本先做平台检测,再按平台覆盖device、batch、workers三个关键参数。device从字符串"0"改为"cpu"或"mps",ultralytics 就会自动切换后端;Mac 上用mps能调用 Metal 加速,比纯 CPU 快不少。workers控制数据加载线程数,CPU 训练时设置0可避免多进程争抢 GIL 导致额外开销。
参数说明:epochs是训练轮数,100 轮对 3000 张小数据集中等够用;imgsz是输入分辨率,默认 640,如果你监控画面是 1080p,训练时用 640,推理时可以用 640 或更高;patience是早停耐心值,20 轮没涨就停,能省时间;save_period表示每 10 轮保存一次权重,方便取中间断点。
3.3 训练脚本里的进阶配置项
资源脚本里除了上述基础参数,还有几个值得关注的配置,我拆出来单独说明。
# 训练增强参数 model.train( ..., augment=True, mosaic=1.0, # 是否启用 mosaic 拼接增强 mixup=0.0, # 是否启用 mixup,打架数据不推荐开太大 hsv_h=0.015, # 色调扰动幅度 hsv_s=0.7, # 饱和度扰动幅度 hsv_v=0.4, # 明度扰动幅度 fliplr=0.0, # 左右翻转概率,打架动作左右不对称,建议关闭 scale=0.5, # 尺度扰动范围 )逻辑说明:mosaic=1.0表示每张训练图都由 4 张图拼接而成,能显著提升小目标检测能力,但代价是训练出的模型对真实图片中孤立的大目标有时不适应,好在验证集仍用原图验证。fliplr=0.0是这里最需要留意的——打架动作有方向性,左右翻转后语义可能反转(比如右手出拳变左手),但模型学得是特征,实际影响取决于你的数据;我一般关掉,因为监控场景左右方向不对称的情况很多。
参数说明:hsv_h/s/v控制颜色扰动强度,监控画面可能来自不同品牌摄像头,颜色差异大,适当调高这三个值能提升泛化性,但别超过上面的数值,否则画面色彩失真,模型容易学偏;scale=0.5表示图片缩放范围允许 50% 到 150%,因为监控里打架目标的尺度变化很大,远近镜头都有。
4. 实战训练与结果复现:从日志看模型有没有收敛
4.1 训练日志怎么看:loss、mAP、混淆矩阵
资源里附了一份博主训练结果日志,这是最值的参考——很多数据集只给数据不给日志,你根本不知道跑到什么程度算正常。日志的关键指标有三个:box_loss、cls_loss、mAP50。box_loss是回归框的损失,训练初期从 1.2 左右下降,正常应在 0.05~0.1 之间稳定;cls_loss是分类损失,单类任务通常降到 0.01 以下才算收敛;mAP50是 IoU 阈值 0.5 下的平均精度,打架这种重叠度高的场景,mAP50比mAP50-95更有参考价值。
看日志时我会同时开两个终端,一个跑tail -f实时看命令行输出,另一个每隔几分钟看一眼runs/fight_detect/exp_fight/weights/目录下的last.pt大小变化。如果last.pt一直是 0 字节,说明训练中断或磁盘满;如果 loss 不降反升,且mAP50在某个值附近抖动,大概率是学习率没适配。
4.2 博主训练结果日志参考值
资源日志整理成表格相当于:
| 指标 | 第 20 轮 | 第 60 轮 | 第 100 轮 |
|---|---|---|---|
| box_loss | 0.68 | 0.32 | 0.08 |
| cls_loss | 0.12 | 0.04 | 0.009 |
| mAP50 | 0.51 | 0.74 | 0.86 |
| precision | 0.63 | 0.78 | 0.91 |
| recall | 0.48 | 0.71 | 0.82 |
注意,这是博主在特定硬件和数据划分下的结果,你的环境不同,数值会浮动,但趋势应当一致:mAP50 最终大于 0.8,precision 高于 recall 约 0.05~0.1,说明模型偏保守,宁可漏检也不误报。如果你的结果到不了这个量级,先检查自己的数据划分是不是场景失衡,再用imgsz=960重跑一轮,很多情况下是输入分辨率不够导致小目标漏检。
4.3 用训练好的权重做推理验证
训练完成后,资源里weights目录下会有best.pt和last.pt。last.pt是最后一轮的权重,best.pt是验证集 mAP 最高的权重,推荐用best.pt做推理。
# 推理单张图片 yolo detect predict model=./runs/fight_detect/exp_fight/weights/best.pt source=./test_images/bar.jpg # 推理整个目录 yolo detect predict model=./runs/fight_detect/exp_fight/weights/best.pt source=./test_video_frames save_txt=True # 推理视频文件 yolo detect predict model=./runs/fight_detect/exp_fight/weights/best.pt source=./street_camera.mp4逻辑说明:predict子命令会自动读取模型内置的类别名(训练时写入的names),无需额外配置;save_txt=True会把每个目标的坐标保存为 txt,便于后续接告警逻辑。如果你只需要结果可视化,不加save_txt即可。
参数说明:source可以是图片路径、目录、视频文件,甚至是rtsp://流地址,但直接拉 RTSP 流推理时,如果摄像头是 H.265 编码,OpenCV 可能解不了,需要先转成 H.264 或用 ffmpeg 拉流。这点在最后一章会细说。
5. 避坑与常见问题:换平台、路径、显存与标注格式的坑
5.1 现象:Windows 上跑通,Mac M 芯片报 libomp 错误
换到 Mac M 芯片上训练,刚 import ultralytics 就报OMP: Error #15: Initializing libomp。原因是 ultralytics 依赖的 PyTorch 在 Mac 上用mps后端时,需要 macOS 自带的libomp.dylib,而部分安装方式没有正确带过来。解决方法是先卸载重装 PyTorch 的 MPS 版本,或者安装libomp:
brew install libomp如果没配 Homebrew,手动把libomp.dylib路径加到DYLD_LIBRARY_PATH也行,但每次开终端都要重设,建议直接 brew 安装。另外,Mac 上训练 epoch 数不要照搬 GPU 的 100,建议减半,因为 MPS 虽然比 CPU 快,但比 NVIDIA GPU 慢不少,你可以先跑 10 轮看速度再定总量。
5.2 现象:YOLO txt 标签有的框坐标越界
训练时报错或日志中出现大量warnings: corrupt box。原因是部分 txt 里的width或height大于 1,或者center_x超出了 [0,1] 范围。这类问题多来自格式转换脚本写错,标签的归一化分使用了某个错误的宽高。排查方法:
# 检查是否有越界坐标(awk 一行检查) awk '{ if ($3+$5/2>1 || $3-$5/2<0 || $4+$6/2>1 || $4-$6/2<0) print FILENAME }' labels/train/*.txt逻辑说明:YOLO 的坐标是归一化后的小数,center_x - width/2应当大于等于 0,center_x + width/2应当小于等于 1,否则说明坐标越过图片边界。输出有问题的文件名后,用 labelimg 重新打开对应图片修正。
解决:不要用编辑脚本硬裁,因为裁掉的部分可能包含关键特征,最稳的做法是回到原始 XML,重新算一次归一化坐标,检查原图尺寸是否与 XML 里<width>、<height>一致。我遇到过一次图片被压缩软件改了尺寸,而 XML 没更新,导致所有坐标整体偏移。
5.3 现象:COCO json 转 YOLO 后类别 id 对不上
有人不用资源里的 YOLO 格式,想自己从 COCO json 转一份新的 YOLO 格式,结果训练时 mAP 一直为 0。常见原因是从 COCO 的categories里取得的id不是从 0 开始,而 YOLO 要求class_id必须是连续整数从 0 开始。资源里的 COCO json 里fight的id是 1,如果你直接按category_id - 1转成0没问题;但如果复制了网上的转换脚本,有些脚本会直接写category_id,就变成了 class 1,和data.yaml里names: {0: fight}对不上。
解决:转换脚本里强制做映射:
import json with open("COCO/val.json") as f: coco = json.load(f) cat_map = {} for i, cat in enumerate(coco["categories"]): cat_map[cat["id"]] = i # 强制从0开始映射 with open("val_labels.txt", "w") as out: for ann in coco["annotations"]: img_id = ann["image_id"] img = next(img for img in coco["images"] if img["id"] == img_id) w, h = img["width"], img["height"] x, y, bw, bh = ann["bbox"] cx = (x + bw / 2) / w cy = (y + bh / 2) / h out.write(f"{cat_map[ann['category_id']]} {cx:.6f} {cy:.6f} {bw/w:.6f} {bh/h:.6f}\n")逻辑说明:这里一个关键细节是 COCO 的bbox用的是[x, y, width, height],其中x, y是左上角坐标。转换时必须先把x, y加上width/2、height/2得到中心点,再除以图片宽高归一化。cat_map强制把 COCO 的category_id(可能是 1 或 2)映射到从 0 开始的连续索引,避免类别错位。
参数说明:width和height取自 COCO json 的images字段,不是从图片文件读,否则容易因枚据不一致导致坐标偏移。另外,json 里可能存在area为 0 的标注,转换时应跳过,这些是空框或退化框。
5.4 现象:CPU 训练慢到怀疑人生,如何降低 batch 和图像尺寸
没有 GPU 的机器上,用默认 batch=16、imgsz=640 训 100 轮可能要三五天。优化从几个方向同时下手:第一,把imgsz降到 416,监控场景里打架目标通常不小,416 也能容纳;第二,把batch降到 4,让内存占用可控,避免 CPU 频繁交换数据;第三,workers=0,多进程在 CPU 训练时反而会因为频繁的上下文切换拖慢速度;第四,用patience=15提前止损,如果 30 轮还没见 mAP 涨过 0.3,干脆停。
# 用资源里的脚本但强制 CPU 小参数 python train_script.py --device cpu --batch 4 --imgsz 416 --workers 0 --epochs 60CPU 训练时,建议把训练过程放到后台并用nohup记录日志,这样即使 SSH 断开训练也不会停。我一般还会开一个top命令监视 CPU 占用,如果占用率只有 10%,说明数据加载已经卡脖子,优先检查图片是不是存储在机械硬盘上,换成 SSD 能提速 30%。
5.5 现象:图片路径含中文导致训练报错
Windows 环境下,如果数据集放在类似D:\数据集\打架检测的路径,ultralytics 在读取图片时可能报FileNotFoundError或UnicodeDecodeError。原因是 Python 在 Windows 下默认编码不是 UTF-8,而 ultralytics 内部可能以 UTF-8 解析路径。解决方法是把整个数据集放到纯英文路径下,比如D:/datasets/fight_detect,并且data.yaml里的路径也不能带中文。如果你已经训练到一半才报错,可以把train.py开头加上:
import sys sys.stdout.reconfigure(encoding='utf-8')这只能解决日志输出,不能解决路径解析。最稳妥的还是路径全英文。另外,图片文件名里的空格也会引起麻烦,最好统一用下划线替换。
6. 进阶:把打架检测接到监控视频流(RTSP)推理
训练好模型只是第一步,实际项目里要接的是 RTSP 监控流。先把资源里的best.pt拿出来,用 ultralytics 的stream模式做持续推理:
import cv2 from ultralytics import YOLO model = YOLO("runs/fight_detect/exp_fight/weights/best.pt") rtsp_url = "rtsp://admin:password@192.168.1.10:554/stream1" cap = cv2.VideoCapture(rtsp_url) if not cap.isOpened(): print("RTSP 打开失败,检查网络和账号密码") exit() skip_frame = 2 # 每 3 帧抽取 1 帧做检测 frame_count = 0 while True: ret, frame = cap.read() if not ret: break frame_count += 1 if frame_count % skip_frame != 0: continue results = model.predict(frame, conf=0.5, iou=0.45, device="0", verbose=False) for r in results: boxes = r.boxes for box in boxes: x1, y1, x2, y2 = box.xyxy[0].tolist() conf = box.conf[0].item() print(f"fight: {conf:.2f} bbox=({x1:.0f},{y1:.0f},{x2:.0f},{y2:.0f})") # 这里可以接告警逻辑:连续 N 帧都检测到 fight,再发告警逻辑说明:skip_frame=2是监控落地最常用的优化——RTSP 流通常是 25fps,如果每帧都推理,GPU 占用高且容易掉帧;跳帧后放到 8~12fps 的检测频率,对打架这种持续几秒的动作完全够用。conf=0.5是置信度阈值,监控场景建议调高到 0.6 减少误报;iou=0.45是 NMS 的 IoU 阈值,打架时多人重叠,iou太低会把同一个框重复输出,太高又会合并掉独立的两个打架者,0.45 是个折中。
一个很容易忽略的点:box.xyxy[0]返回的是 tensor,需要转成 Python 列表或标量,否则后续逻辑里x1是 tensor 对象,做比较运算时容易报错。另外,告警不能只看单帧,监控系统里我一般用「连续 5 帧中至少 3 帧检出」的规则,避免人快速挥手、镜头抖动这类瞬时误触发。
验证推理性能有个土办法:在视频第一帧的位置打印一次帧率。
import time start = time.time() # ... 检测循环 ... elapsed = time.time() - start print(f"推理帧率: {frame_count / elapsed:.2f} FPS")如果帧率低于 5,且跳帧已经到了 5,需要减小输入分辨率到 480,或者换用yolo11n的移动端模型精度。实测中 1080p 视频流抽帧到 640 分辨率,T4 显卡能跑到 25ms/帧,CPU 上大约 300ms/帧,所以没有 GPU 的场景只能降低抽帧频率。
从那以后我每接到一个监控项目,都会强制先跑一遍这个流程:用三种格式交叉验证标签、在纯 CPU 上小规模试跑确认数据没问题、再切到 GPU 全量训练,最后接 RTSP 做跳帧推理。这套习惯帮我避开了不少因为标签踩坑导致白训几天的翻车,希望帮到你。
本文还有配套的精品资源,点击获取