简介:面向游泳监控与溺水预警场景,这份数据集提供4599张真实场景图片,标注框总数为6017个,覆盖drowning与swimming两个目标类别,可直接用于训练YOLO、SSD、Faster R-CNN等目标检测模型。数据格式兼顾Pascal VOC与YOLO两种主流标准,图片与XML、TXT标注一一对应,采用labelImg工具以矩形框逐张人工标注,类别框数分别为drowning 2578个、swimming 3439个,便于进行类别均衡分析和数据增强。资源包共2000个文件,主要由1999个XML标注文件和1个使用说明TXT文件构成,压缩包整体约156.75MB,结构清晰,无需复杂预处理即可接入常用深度学习框架。目前已有521人学习下载,适合计算机视觉初学者、安防算法工程师以及水上安全监测项目开发者作为算法验证和模型迭代的基础数据。拿到后可直接划分训练与验证集,快速启动训练实验;内含标注统计与使用说明,能够帮助快速了解数据分布,减少数据清洗时间,聚焦模型本身优化。
1. 游泳者溺水检测数据集:先别急着找模型,先弄懂这份VOC+YOLO双格式的4599张图
做泳池安防或者水域监控的人,大概率都遇到过同一个尴尬:模型结构选好了,训练脚本写好了,结果卡在“数据不够”或者“标注格式对不上”上。这份“游泳者溺水检测数据集VOC+YOLO格式4599张2类别.7z”解决的正是这个卡点——它不是给你一个现成的端到端推理系统,而是给你一份可以直接喂进YOLO训练流程的标注数据,同时保留了VOC格式作为中间交换。4599张图、2个类别,这个规模对从零训练来说不算大,但对迁移学习、微调预训练权重、验证检测pipeline来说,是恰到好处的量级。适合谁?想用yolov8训练自己的数据集的新手,以及需要快速验证“溺水检测到底能不能做”的从业者。这份数据集的真正价值不在图多,而在它同时提供了两种主流标注格式,可以少踩很多格式转换的坑。
2. VOC与YOLO双格式拆解:4599张图里的目录结构和标注差异
2.1 为什么是2个类别:游泳者与溺水者的分类边界
这个数据集只有2个类别,常见的命名是“swimmer”(游泳者)和“drowning”(溺水者)。这里有个容易忽略的点:这两个类别不是“有人”和“没人”的区别,而是同一个目标在不同状态下的区分。换句话说,模型要学习的不是“目标有没有出现”,而是“这个人的姿态、位置、运动轨迹是否符合溺水特征”。
这就带来一个现实问题:类别的语义边界不像COCO数据集里“人”和“自行车”那么清晰。某个泳姿可能就是“看起来像在划水但实际在挣扎”,某个人仰面漂着可能是在休息而不是溺水。数据集的标注质量直接决定模型的精度上限,算法反而是次要的。所以拿到这份数据后的第一件事不是改网络结构,而是把图片和标注过一遍,搞清楚标注者定义的“溺水”到底是什么样的标准。
2.2 VOC版目录结构:JPEGImages与Annotations的字段对照
VOC格式(Pascal VOC)是目标检测领域最通用的标注交换格式。这份数据集如果用VOC版组织,典型目录结构如下:
dataset_root/ ├── JPEGImages/ # 所有jpg图片,文件名与标注文件一一对应 │ ├── swimmer_001.jpg │ ├── swimmer_002.jpg │ └── ... ├── Annotations/ # 每张图对应的xml标注文件 │ ├── swimmer_001.xml │ └── ... └── ImageSets/ └── Main/ ├── train.txt └── val.txt单个XML标注文件的核心结构如下:
<annotation> <filename>swimmer_001.jpg</filename> <size> <width>1920</width> <height>1080</height> <depth>3</depth> </size> <object> <name>drowning</name> <bndbox> <xmin>312</xmin> <ymin>287</ymin> <xmax>658</xmax> <ymax>712</ymax> </bndbox> </object> </annotation>注意这里几个关键字段:filename对应JPEGImages里的实际文件名;size里的宽高必须跟图片真实尺寸一致,否则后面转YOLO格式时归一化坐标会错位;object里的name就是类别名称,这份数据应该是“swimmer”和“drowning”二选一。VOC格式的优点是人眼可读、字段规范、几乎所有检测框架都提供解析工具,缺点是每张图一个XML文件,文件数量多,而且标注信息有冗余,处理起来比YOLO的txt慢。
2.3 YOLO版每行标注的含义:中心点、宽高和归一化
YOLO格式的标注是每个图片对应一个txt文件,放在labels目录下,每一行代表一个目标框:
class_id x_center y_center width height具体来说,x_center和y_center是目标框中心点的归一化坐标,width和height是归一化的宽和高。所有数值都在0到1之间,计算方式是:
x_center = (xmin + xmax) / 2 / image_width y_center = (ymin + ymax) / 2 / image_height width = (xmax - xmin) / image_width height = (ymax - ymin) / image_height举个例子,前面XML里的标注框,在1920x1080的图上转成YOLO格式就是:
1 0.2526 0.4625 0.1802 0.3935其中class_id为1表示drowning,0表示swimmer(具体编号要看数据集自带的类别映射)。YOLO格式的优势是每行一个目标,读取快、占用空间小,训练时几乎不解析XML。但缺点也很明显:txt里不包含图片尺寸信息,一旦用错尺寸做归一化,坐标就全乱了。另外txt文件里没有类别名称,只有编号,编号顺序错了模型就学反了。所以这份数据集同时提供VOC和YOLO格式,本质上是给了你一条退路:VOC格式用来核对语义,YOLO格式直接训练。
2.4 4599张图算什么规模:迁移学习的题材
4599张图、2个类别,如果按类别平均分,每个类别约2300张图。这个规模在目标检测领域属于“中小型数据集”。直接随机初始化权重从零训练,效果大概率不理想,因为检测模型动辄上千万参数,2300张图远不够拟合。但有两个有利条件:一是泳池场景的视觉变化相对可控,不像自动驾驶那样有极端多样的光照和背景;二是目标类别只有2个,模型需要学习的特征区分度比80类COCO简单得多。
常见做法是采用迁移学习,用COCO预训练的YOLO权重做初始化,冻结骨干网络训练前几十个epoch,然后解冻全部层微调。这样4599张图是够用的。另外要注意类别不平衡问题,如果swimmer和drowning的数量悬殊,训练时需要调整类别损失权重或者做采样策略,后面会讲具体参数。
3. 从.7z到可训练目录:解压、校验、格式归一化三件事
3.1 解压和环境准备:先看目录再写脚本
拿到“游泳者溺水检测数据集VOC+YOLO格式4599张2类别.7z”这样的压缩包,第一步不是急着解压,而是确认压缩包内部结构。.7z格式用7-Zip或Linux下的p7zip解压,命令如下:
# Ubuntu/Debian系安装p7zip sudo apt install p7zip-full # 解压到指定目录,保持原有目录结构 7z x swimming_drowning.7z -o/path/to/dataset参数说明:x表示解压并保留完整路径,-o指定输出目录,注意-o和路径之间没有空格。解压完成后,先进入目录看一下层级:
ls -la /path/to/dataset这里提醒一个常见的坑:很多打包者会把数据集再套一层上级目录,比如解压后出现dataset/然后里面才是JPEGImages/。后面的训练脚本路径全都要基于实际解压层级来写,建议解压后直接以JPEGImages所在的目录作为DATASET_ROOT,避免后续脚本里出现dataset/dataset/JPEGImages这种路径错误。
3.2 校验图片和标注:统计类别分布和无效框
训练前必须做一轮数据体检,检查三件事:图片数量是否等于标注数量、每个类别的目标框数量、有没有宽高为0或超出图片边界的非法框。下面这个Python脚本可以一次完成统计:
import os from collections import Counter from PIL import Image DATASET_ROOT = "/path/to/dataset" IMAGES_DIR = os.path.join(DATASET_ROOT, "JPEGImages") LABELS_DIR = os.path.join(DATASET_ROOT, "labels") # 如果数据集已含YOLO格式 # 类别映射,这里假设编号0=swimmer, 1=drowning CLASS_NAMES = {0: "swimmer", 1: "drowning"} def check_yolo_labels(): total_boxes = Counter() invalid_files = [] for label_file in os.listdir(LABELS_DIR): if not label_file.endswith(".txt"): continue img_file = label_file.replace(".txt", ".jpg") img_path = os.path.join(IMAGES_DIR, img_file) if not os.path.exists(img_path): invalid_files.append(f"{label_file}: 对应图片不存在") continue with Image.open(img_path) as img: img_w, img_h = img.size with open(os.path.join(LABELS_DIR, label_file), "r") as f: for line in f: parts = line.strip().split() if len(parts) != 5: invalid_files.append(f"{label_file}: 字段数不对") continue cls, x_center, y_center, w, h = parts x_center, y_center, w, h = map(float, (x_center, y_center, w, h)) cls = int(cls) # 检查坐标是否在[0,1]范围内,以及宽高是否为正 if w <= 0 or h <= 0 or not (0 <= x_center <= 1 and 0 <= y_center <= 1): invalid_files.append(f"{label_file}: 坐标异常 [{cls} {x_center} {y_center} {w} {h}]") continue total_boxes[CLASS_NAMES.get(cls, f"未知类{cls}")] += 1 print("各类别目标框数量:", dict(total_boxes)) print("异常文件数:", len(invalid_files)) for item in invalid_files[:10]: print(" -", item) if __name__ == "__main__": check_yolo_labels()脚本的核心逻辑是逐行解析txt标注,同时打开对应图片做尺寸校验。total_boxes用Counter统计每个类别的框数,这能直接暴露类别不平衡问题。invalid_files收集三类异常:图片缺失、字段数不对、坐标越界或宽高非正。只要出现未知类的计数,说明类别编号跟预期不一致,需要查看数据集自带的类别说明文件。
3.3 VOC转YOLO:自己动手写转换脚本比找现成工具更靠谱
虽然这份数据集已经提供了YOLO格式,但实际使用中你很可能需要把VOC转成YOLO,原因有两个:一是官方给的划分可能不合你的场景,你要重新划分train/val;二是你想增加自己的图片,新标注的xml要转成yolo才能跟这份数据合并训练。网上有很多转换脚本,但多数没做异常处理。我一般会自己写一个,逻辑完全可控:
import os import xml.etree.ElementTree as ET from collections import defaultdict VOC_ROOT = "/path/to/dataset/voc" YOLO_ROOT = "/path/to/dataset/yolo" CLASS_MAPPING = {"swimmer": 0, "drowning": 1} # 按数据集的类别定义调整 def voc_to_yolo(xml_path, output_txt_path): tree = ET.parse(xml_path) root = tree.getroot() img_width = int(root.find("size/width").text) img_height = int(root.find("size/height").text) lines = [] for obj in root.findall("object"): name = obj.find("name").text if name not in CLASS_MAPPING: print(f"跳过未知类别 {name} in {xml_path}") continue cls_id = CLASS_MAPPING[name] bbox = obj.find("bndbox") xmin = int(bbox.find("xmin").text) ymin = int(bbox.find("ymin").text) xmax = int(bbox.find("xmax").text) ymax = int(bbox.find("ymax").text) # 归一化计算 x_center = (xmin + xmax) / 2.0 / img_width y_center = (ymin + ymax) / 2.0 / img_height w = (xmax - xmin) / img_width h = (ymax - ymin) / img_height # 夹紧到[0,1],防止边界标注越界 x_center = min(max(x_center, 0.0), 1.0) y_center = min(max(y_center, 0.0), 1.0) w = min(max(w, 0.0), 1.0) h = min(max(h, 0.0), 1.0) lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}") with open(output_txt_path, "w") as f: f.write("\n".join(lines)) os.makedirs(os.path.join(YOLO_ROOT, "labels"), exist_ok=True) for xml_file in os.listdir(os.path.join(VOC_ROOT, "Annotations")): if not xml_file.endswith(".xml"): continue base = xml_file.replace(".xml", "") xml_path = os.path.join(VOC_ROOT, "Annotations", xml_file) txt_path = os.path.join(YOLO_ROOT, "labels", base + ".txt") voc_to_yolo(xml_path, txt_path) print("转换完成,输出目录:", YOLO_ROOT)这个转换脚本有四个关键设计。第一,CLASS_MAPPING由手工定义,不依赖数据集的任何配置文件,避免类别编号错位。第二,归一化时把坐标结果夹紧到[0,1],VOC标注偶尔会出现坐标比图片尺寸大一点点的边界框,如果不过滤,训练时YOLO算损失会出现NaN。第三,未知类别直接跳过并打印,不会让整个转换崩掉。第四,输出的txt中坐标保留6位小数,精度足够且文件体积小。你需要注意,如果转换后某个图片对应的txt是空文件,说明这张图没有有效标注,训练时要在数据加载阶段过滤掉。
3.4 重新划分train/val:固定随机种子保证可复现
数据集自带的划分不一定适合你,特别是当你只想要“drowning”样本比较多的一组做验证时。重新划分的规则很简单:按图片名随机打乱,保证同一张图不会同时出现在训练集和验证集。下面这段脚本可以同时生成VOC训练所需的train.txt/val.txt和YOLO训练所需的images/train软链或文件列表:
import os import random IMAGES_DIR = "/path/to/dataset/JPEGImages" OUTPUT_DIR = "/path/to/dataset/split" TRAIN_RATIO = 0.8 # 80%训练、20%验证 random.seed(42) # 固定随机种子,多次运行结果一致 all_images = [f for f in os.listdir(IMAGES_DIR) if f.endswith(".jpg")] random.shuffle(all_images) split_idx = int(len(all_images) * TRAIN_RATIO) train_images = all_images[:split_idx] val_images = all_images[split_idx:] os.makedirs(OUTPUT_DIR, exist_ok=True) with open(os.path.join(OUTPUT_DIR, "train.txt"), "w") as f: f.write("\n".join(os.path.splitext(img)[0] for img in train_images)) with open(os.path.join(OUTPUT_DIR, "val.txt"), "w") as f: f.write("\n".join(os.path.splitext(img)[0] for img in val_images)) print(f"训练集: {len(train_images)} 张, 验证集: {len(val_images)} 张")这里的random.seed(42)是关键参数。换一个seed,划分结果就变了,训练结果不具备可比性。另外TRAIN_RATIO取0.8,对4599张图来说训练集约3680张、验证集约920张,验证集规模充足。如果你的目标是做溺水检测的专项测试,可以把所有含drowning的目标框单独抽出来做一次分层统计,确保验证集里两个类别的比例跟训练集接近,避免出现验证集里没有溺水样本的尴尬。
4. 用YOLOv8训练这份数据:data.yaml、超参和迁移学习的具体配置
4.1 data.yaml的正确写法:路径、类别数和类别名
YOLOv8是目前训练自定义数据集最顺手的框架,但它对data.yaml的要求有一些细节。基于这份数据集的目录结构,配置文件这样写:
# dataset.yaml path: /path/to/dataset # 数据集根目录 train: images/train # 训练图片相对路径 val: images/val # 验证图片相对路径 nc: 2 # 类别数量 names: ['swimmer', 'drowning'] # 类别名称,顺序必须和标签txt里的编号一致注意三个容易踩坑的点。第一,path建议写绝对路径,相对路径在调试时容易出幺蛾子。第二,train和val指向的是图片目录,YOLOv8会自行去同级labels目录找对应的txt文件,不要用逗号分隔多个目录,除非你要做多数据集合并。第三,names里的顺序要和前文CLASS_MAPPING保持完全一致——如果标签txt里class_id=0表示drowning而你这里names[0]='swimmer',训练不会报错,但验证时的混淆矩阵和最终检测结果是完全错位的。
4.2 训练命令和关键参数:从预训练权重出发而不是从零开始
训练命令建议用yolo命令行工具加参数覆盖,而不是直接改cfg文件:
yolo detect train \ data=/path/to/dataset.yaml \ model=yolov8n.pt \ epochs=80 \ batch=16 \ imgsz=640 \ patience=10 \ lr0=0.001 \ device=0 \ project=./runs \ name=swimmer_det参数说明如下:model=yolov8n.pt表示加载COCO预训练权重继续训练,这是4599张图规模下最好的起点。batch=16是根据显存调整的,如果你的显卡是8GB显存,16可能要降到8;如果是24GB显存,可以试着升到32。imgsz=640是YOLOv8默认输入尺寸,泳池场景目标比较大,不需要用1280。patience=10表示验证集mAP连续10个epoch不提升就提前停止,防止过拟合。lr0=0.001是初始学习率,从预训练权重微调时这个值不宜太大,否则会破坏已学好的特征。
这里有个细节:加载预训练权重时,YOLOv8会自动适配类别数。COCO预训练模型是80类,你这份数据是2类,框架会截断最后一层分类头重新初始化。不需要手动修改权重文件,但要注意如果直接指定model=yolov8n.yaml而不是.pt,就是从零训练,效果会差很多。第一次先用nano规模跑通,确认loss下降趋势正常,再换yolov8s.pt或yolov8m.pt提精度。
4.3 类别不平衡怎么处理:先看统计再决定要不要改loss
如果校验脚本统计出swimmer有3500个框、drowning只有1500个框,这个比例不算太失衡,还不至于崩。但如果出现10:1的悬殊比例,就需要干预。常见做法有几种:一是用class_weights参数给少数类更高的损失权重,YOLOv8里开启方式如下:
yolo detect train \ data=... \ model=yolov8n.pt \ epochs=80 \ batch=16 \ imgsz=640 \ loss_weights=0.8,1.2loss_weights里第一个数对应swimmer的box/class损失权重,第二个数对应drowning。把“溺水者”的权重调高,让模型更重视这个类别。但这个做法要小心过拟合,权重太高会让模型倾向于把所有目标都预测成drowning。
另一个做法是数据增强里加mosaic=0.5、mixup=0.2,增加样本多样性。不过游泳者检测场景里,Mosaic增强会让多个泳池的画面拼在一起,泳池边的颜色纹理差异反而可能误导模型,建议mosaic不要超过0.8。我看到不少人在这个数据集上把mosaic开到1.0,训练集loss虽然降得快,但验证集mAP忽高忽低,就是增强强度过大的典型表现。
5. 泳池场景训练最常见的5个坑:现象、原因和解决办法
5.1 解压后图片和标注文件名对不上:训练时报错Image not found
现象:用YOLOv8训练时日志里出现大量“image not found”警告,训练直接中断。
原因:.7z压缩包内部可能把图片和标注分成了两个子压缩包,解压时只解压了其中一部分;或者文件名包含特殊字符(比如中文命名的人名编号),Linux下编码不同导致匹配失败。
解决:解压后执行一次完整校验,不要把“能打开”当作“能用”。用md5sum对图片和标注文件做一一比对,或者简单点看两边文件数是否一致——图片4599张,XML和txt也该是4599个。
ls /path/to/dataset/JPEGImages | wc -l ls /path/to/dataset/labels | wc -l如果数量不一致,大概率是压缩包里的标注有缺失,或者解压时有文件损坏。这时不要硬训练,先重新解压并检查压缩包完整性。
5.2 类别编号对不上:模型训练正常但检测结果张冠李戴
现象:训练跑完,loss正常下降,但把模型部署到测试视频上时,把正常的游泳者标成drowning。
原因:这是最容易踩的坑。数据集的YOLO格式txt里class_id=0可能是“drowning”,而你data.yaml里names列表顺序写的是['swimmer','drowning'],编号就错位了。这类数据集的命名规范不统一,有的把drowning作为正类设为0,有的作为第二类设为1。
解决:不要在data.yaml里猜,直接统计原始txt里每行的第一个数字,看有几个类别编号,再抽样打开几张图片用肉眼核对实际目标。确认编号后,再写names列表,并固定下来不再改动。这个坑不报错、不崩训练,发现的窗口只在最终效果验证阶段,越早检查越好。
5.3 标签框坐标出现0.0或1.0:loss直接变成NaN
现象:训练到第十几个epoch时,box_loss突然变成nan,然后整体loss全部崩掉。
原因:某些YOLO标签txt里出现0.000000 0.000000 1.000000之类的整行边界值,这通常是VOC转YOLO时坐标计算错误,把整个图片误标成了一个目标框。YOLO训练时算anchor匹配,这种极端框容易让梯度冲过头,直接爆掉。
解决:训练前用前面写的校验脚本检查坐标。如果出现0 <= x_center <= 1范围内的正常框,但宽度恰好等于1.0或高度恰好等于1.0,删除这一行标注,因为这明显是转换时的异常值,不是真实的目标框。训练时加上cache=True参数,让YOLOv8把数据缓存到内存,这样如果哪个样本有问题,报错信息能精确定位到文件名。
5.4 整体mAP漂亮但drowning类别的AP极低:数据标注含大量噪点
现象:训练20个epoch后,验证集整体mAP到了0.75,但看每个类别的AP,swimmer是0.91,drowning只有0.42。
原因:溺水样本本身的标注一致性差——不同标注者对“正在溺水”的判定标准不同,有的把“仰面漂浮”也算作溺水,有的只把“挣扎姿态”算溺水。模型学到了一个折中的特征边界,两头都不讨好。
解决:把训练集里所有drowning类别的图片抽出来做一次人工复检,重点看标注框是不是把目标框全了,以及类别标签是否跟自己的业务定义一致。4599张图里drowning类别的样本很少,一次人工检查一个小时内能过完。这一步比换任何模型结构都管用。检查后按照业务重新标注不一致的样本,再微调训练。做这一步时可以用python脚本把所有drowning样本复制到一个单独文件夹,逐张快速查看。
5.5 预训练权重加载报错:类别数不匹配导致的KeyError
现象:执行训练命令时报错,提示Error in loading state_dict或者size mismatch for model.head.cv2...。
原因:虽然YOLOv8会自动适配类别数,但如果你用了某些修改版的网络结构,或者直接加载了一个在别的数据集上训好的best.pt而非COCO官方权重,最后一层卷积输出的通道数跟当前nc=2对不上。
解决:如果是YOLOv8官方预训练模型,检查下载的.pt文件是否属于同一个大版本,比如不要用YOLOv5的.pt去初始化YOLOv8的模型,虽然它们同出ultralytics,但网络结构定义不一样。如果是自己训过的权重,加载时指定strict=False跳过不匹配层:
# 加载自己的权重时忽略不匹配层 from ultralytics import YOLO model = YOLO("path/to/best.pt") model.load("path/to/previous_weights.pt", strict=False)strict=False的意思是结构不匹配的层(比如分类头)保留当前模型的初始化值,匹配的层(比如骨干网络)加载旧权重。这在做数据集增量更新时是常用技巧。
6. 生产环境验证:用批量推理、混淆矩阵和分类别AP判断模型是否真的能用
训练完不等于能用,尤其在溺水检测这种场景下,模型在验证集上的mAP高不代表在真实泳池视频里不误报。我的习惯是训练结束后做一轮“生产环境模拟验证”:取一段泳池监控视频(不是训练集和验证集里出现过的画面),用训练好的权重做批量推理,保存每一帧的检测框和置信度,再统计两个类别的误报分布。下面这段脚本可以把YOLOv8的输出整理成结构化数据:
from ultralytics import YOLO import cv2 import csv model = YOLO("runs/swimmer_det/weights/best.pt") video_path = "test_pool.mp4" cap = cv2.VideoCapture(video_path) results = [] frame_id = 0 while cap.isOpened(): ret, frame = cap.read() if not ret: break # conf=0.4是泳池场景下的平衡点,生产环境建议0.35-0.5之间 det = model.predict(frame, conf=0.4, imgsz=640, verbose=False) for box in det[0].boxes: x1, y1, x2, y2 = box.xyxy[0].tolist() cls_id = int(box.cls[0].item()) conf = float(box.conf[0].item()) results.append([frame_id, cls_id, conf, x1, y1, x2, y2]) frame_id += 1 cap.release() with open("detection_results.csv", "w", newline="") as f: writer = csv.writer(f) writer.writerow(["frame_id", "class_id", "confidence", "x1", "y1", "x2", "y2"]) writer.writerows(results) print(f"推理完成,共{frame_id}帧,输出{len(results)}个检测框")这段脚本的核心是conf=0.4这个参数。对溺水检测来说,漏报比误报严重得多——漏报一个正在溺水的人可能出人命,所以置信度阈值应该往低调。我看到不少团队在部署时为了展示效果把阈值调高到0.7,结果溺水时目标姿态模糊、置信度上不来,直接漏检。调低到0.35-0.4,配合帧间跟踪或人工二次确认,才是可靠的工作模式。
跑完批量推理后,把检测结果里的drowning框对应的帧抽出来做成一组缩略图,快速浏览一遍,重点看两个问题:一是误报集中在泳池边的人、穿红衣服的人还是水花飞溅的瞬间;二是漏报的帧里溺水者的姿态跟训练集里的差异在哪里。这一步完成后,你会得到一个明确的结论:当前模型是直接能用、需要补数据还是需要调阈值。我的个人教训是,第一次在这个数据集上训练时只看了整体mAP就上线测试,结果对着一池子游泳教学班的视频连续误报,把教练的正常教学动作识别成了溺水。后来把验证重心从“总量mAP”挪到“分类别AP+人工抽帧”之后,才真正把模型调到能在真实场景里干活的程度。这个顺序希望帮到你,节省几天调参的弯路。
本文还有配套的精品资源,点击获取