简介:本资源为LOL英雄联盟角色检测数据集,面向目标检测初学者、算法工程师及游戏AI研究者,可用于训练与验证队友、己方小兵、敌方小兵、防御塔及英雄角色(LUX、VAYNE)的识别模型。压缩包共2000个文件,以1999个Pascal VOC格式xml标注文件和1个说明txt为主,整体约135.85MB,图片与标注一一对应,可直接用于YOLO或VOC格式训练流程。数据集包含3000张jpg图片,标注类别6类,总框数达24665个,其中敌方小兵10973框、己方小兵7339框、VAYNE 3669框、LUX 1531框、防御塔合计1153框,类别分布清晰,便于分析样本均衡性。目前已有464人学习下载,适合作为课程设计、毕业项目或检测算法对比实验的数据基础,帮助读者快速搭建训练管线并验证模型在游戏场景下的检测效果。
1. 从一张截图说起:为什么3000张6类的角色检测数据集值得你花时间
做游戏视觉方向的人,大概都遇到过这种场景:想给某款MOBA游戏做一个自动剪辑、自动战报或者辅助分析的小工具,第一步就卡在数据上。网上开源的目标检测数据集大多是COCO、VOC那套通用类别,猫狗行人车辆,跟游戏画面里的队友、小兵、防御塔完全不搭边。你拿YOLO预训练权重直接推理游戏截图,模型会把防御塔认成路灯,把敌方小兵认成背景噪点。这时候一个标注好的、类别对齐游戏语义的数据集,价值就出来了。
这篇要聊的就是一个3000张、6类的角色检测数据集,类别覆盖队友、己方小兵、敌方小兵、防御塔、韦恩。它解决的核心问题是:让你跳过最耗时的标注环节,直接进入模型训练和调参阶段。适合谁?做游戏AI分析的学生、想快速验证检测方案的个人开发者、以及需要一个小规模干净数据集做算法对比的工程师。3000张不算大,但6个类别的语义边界清晰,足够跑通一条完整的训练链路。
2. 六类目标的标注逻辑:为什么这样分类比你想的更讲究
拿到一个数据集,先别急着喂给模型。你得先理解标注者的分类意图,否则训练出来的模型会出现类别混淆,而你连问题出在哪都找不到。这个数据集的6个类别不是随便切的,每一类背后都有明确的视觉特征和检测难点。
2.1 队友与敌方小兵:颜色通道是第一判别依据
队友和敌方小兵在形态上高度相似,都是小型单位,体型接近,移动轨迹也类似。区分它们的主要线索是颜色:队友通常带蓝色系血条或轮廓光效,敌方带红色系。这意味着模型在浅层特征上就必须对颜色敏感,而不是等到深层语义。
如果你用YOLO系列训练,数据增强里的HSV抖动要谨慎。色相偏移过大会把蓝色队友染成红色,模型直接学废。我一般会把hsv_h控制在0.015以内,hsv_s和hsv_v可以正常给到0.7和0.4。这一点在后面避坑章节还会展开。
2.2 防御塔:静态大目标带来的正负样本失衡
防御塔是场景里的静态建筑,尺寸大、位置固定、出现频率高。问题在于,一局游戏截图里防御塔可能只出现1到2个,但背景里类似塔状结构的干扰物不少。更麻烦的是,防御塔的标注框往往很大,和队友、小兵这些小目标混在一起训练时,anchor的匹配策略会打架。
常见做法是检查数据集的标注框尺寸分布。如果防御塔的框面积是中位数小兵框的20倍以上,你就需要考虑用多尺度训练,或者在anchor设置上做分组。YOLOv8默认的anchor-free机制对这种尺度差异容忍度比v5好一些,但输入分辨率不能太低,640起步,最好到960。
2.3 韦恩:单英雄类别的样本量与泛化边界
韦恩作为一个具体英雄出现在类别里,说明这个数据集可能面向特定分析任务,比如针对该英雄的行为统计。单英雄类别的风险是样本多样性不足:如果3000张里韦恩只占几百张,且集中在少数几个皮肤或动作上,模型对韦恩的召回率会虚高,换一个皮肤就崩。
你需要先统计每个类别的实例数,而不是只看图片数。一张图里可能有3个队友、6个小兵、2个防御塔,类别实例分布和图片分布是两回事。用后面的统计脚本跑一遍,心里有数再决定要不要做重采样。
2.4 标注格式与坐标体系:拿到数据先做一次格式体检
数据集常见的标注格式有VOC XML、COCO JSON、YOLO TXT三种。这个数据集从标题看是zip包,大概率是YOLO格式的txt标注,每行class_id x_center y_center width height,坐标归一化到0到1。但你不能假设,必须自己验证。
体检要查三件事:坐标是否越界(小于0或大于1)、宽高是否为零或负数、class_id是否超出0到5的范围。这三类错误在手工标注或转换脚本有bug时非常常见,不查就训练,损失曲线会莫名其妙震荡。
import os import glob # 遍历标注文件,检查YOLO格式的合法性 label_dir = "labels/train" issues = [] for txt_path in glob.glob(os.path.join(label_dir, "*.txt")): with open(txt_path, "r") as f: for line_num, line in enumerate(f, 1): parts = line.strip().split() if len(parts) != 5: issues.append(f"{txt_path}:{line_num} 字段数={len(parts)}") continue cls_id = int(parts[0]) x, y, w, h = map(float, parts[1:]) # 类别范围检查 if cls_id < 0 or cls_id > 5: issues.append(f"{txt_path}:{line_num} 类别越界 {cls_id}") # 坐标范围检查 if not (0 <= x <= 1 and 0 <= y <= 1): issues.append(f"{txt_path}:{line_num} 中心坐标越界") if w <= 0 or h <= 0 or w > 1 or h > 1: issues.append(f"{txt_path}:{line_num} 宽高异常 w={w} h={h}") print(f"共发现 {len(issues)} 个问题") for item in issues[:20]: print(item)这段脚本做的是逐行解析,字段数不对直接记录,类别ID超出0到5的记录,中心坐标不在0到1区间的记录,宽高非正或超过1的记录。跑完如果问题数在几十个以内,可以写个清洗脚本自动修;如果上百,说明标注质量堪忧,得考虑要不要换数据源。参数上,label_dir指向你的标注目录,类别上限5对应6类(0到5)。
3. 用YOLOv8跑通第一条训练曲线:从数据组织到超参设置
数据体检通过之后,下一步是把它组织成YOLO能直接吃的目录结构,然后启动训练。这一章给出一条能复现的最小路径,包括目录结构、data.yaml配置、训练命令和关键参数解释。
3.1 目录结构与data.yaml:三个路径写错一个就白跑
YOLO系列要求的数据集结构是固定的:images和labels分开,各自下面再分train、val、test。很多人第一次跑失败就是因为把图片和标注混在一个文件夹,或者路径写成了绝对路径导致换机器就崩。
dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/data.yaml里要写清楚训练集和验证集的路径、类别数、类别名。注意path字段是根目录,train和val是相对路径。类别名的顺序必须和标注里的class_id严格对应,否则模型学出来的类别全是错位的。
# data.yaml path: ./dataset train: images/train val: images/val test: images/test nc: 6 names: 0: teammate 1: ally_minion 2: enemy_minion 3: tower 4: vayne 5: unknown这里我把第6类写成unknown,是因为标题里只列了5个具体类别名但说是6类,实际使用时你需要根据数据集里的真实类别名替换。nc: 6是类别数,names列表长度必须等于nc,顺序不能乱。如果你的数据集类别名和这里不一致,以数据集自带的说明为准,不要照抄。
3.2 训练命令与关键超参:batch和imgsz怎么定
YOLOv8的训练入口是yolo detect train,核心参数有data、model、epochs、imgsz、batch、device。下面这条命令是我在单卡24G显存上跑这个数据集的常用配置。
yolo detect train \ data=./data.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=960 \ batch=8 \ device=0 \ workers=4 \ patience=20 \ project=runs/lol_detect \ name=exp01 \ hsv_h=0.015 \ hsv_s=0.7 \ hsv_v=0.4 \ mosaic=1.0 \ mixup=0.1 \ degrees=0.0 \ translate=0.1 \ scale=0.5逐项说明:model=yolov8s.pt选s而不是n,是因为6类目标里有大小尺度混合,s的特征提取能力比n稳。imgsz=960是为了让防御塔和小兵在同一张图里都有足够像素,640会让小兵变成十几个像素的斑点。batch=8是24G显存下960分辨率的保守值,显存不够就降到4,别硬撑,OOM中断比慢更浪费时间。patience=20表示20轮验证指标不升就早停,3000张数据100轮通常够收敛,早停能省时间。
数据增强里hsv_h=0.015是重点,前面说过队友和敌方小兵靠颜色区分,色相抖动必须压小。mosaic=1.0保留,它能提升小目标的召回。mixup=0.1给一点点,太多会让小兵和防御塔的边界变模糊。degrees=0.0不旋转,因为游戏视角基本固定,旋转会引入不存在的姿态。
3.3 训练过程看什么:loss曲线和mAP的读法
训练启动后,终端会打印每轮的box_loss、cls_loss、dfl_loss和mAP50、mAP50-95。box_loss管定位,cls_loss管分类,dfl_loss是分布焦点损失,YOLOv8特有。三个loss都应该是下降趋势,如果cls_loss震荡不降,大概率是类别标注有冲突,比如同一类目标在不同图里标法不一致。
mAP50到0.7以上算这个数据集上不错的水平,mAP50-95到0.5左右说明框的精度也还行。如果mAP50高但mAP50-95很低,说明模型能找对位置但框不够紧,可以检查标注框是否偏大。验证集loss开始上升而训练loss还在降,就是过拟合信号,早停或者加数据增强。
4. 避坑与排查:六类游戏目标检测里最容易翻车的五个地方
这一章是我自己在类似数据集上踩过的坑,按现象、原因、解决三段式写。你训练时如果遇到对应现象,直接对照排查。
4.1 队友和敌方小兵互相误检:颜色增强开太大
现象:验证集上队友和敌方小兵的混淆矩阵里,两者互相误判的比例超过20%,mAP卡在0.5上不去。
原因:HSV色相抖动过大,把蓝色系队友的像素染成了红色系,模型学到的颜色特征被破坏。或者数据集本身标注时就有少量队友标成敌方的情况。
解决:先把hsv_h降到0.01甚至0,重跑一轮看混淆矩阵是否改善。如果改善明显,说明就是增强问题。如果没改善,用脚本抽查标注,把队友和敌方小兵的样本各抽50张可视化,人眼过一遍。标注错误超过5%就得考虑清洗或重标。
4.2 防御塔漏检严重:小目标anchor被大目标挤占
现象:防御塔的召回率只有0.4左右,但精度很高,检出来的都对,就是漏得多。
原因:防御塔框大,小兵框小,训练时正样本分配偏向小目标,大目标的梯度被稀释。或者输入分辨率太低,防御塔边缘特征丢失。
解决:把imgsz从640提到960或1280,重跑。如果显存不够,用梯度累积模拟大batch。另外检查YOLOv8的anchor-free机制下,大目标的dfl_loss是否异常高,如果是,可以适当调大box损失权重,但YOLOv8不直接暴露这个参数,更实际的做法是增加防御塔的样本权重,通过复制含防御塔的图片实现。
4.3 韦恩类别过拟合:样本太少导致换皮肤就崩
现象:训练集上韦恩的mAP到0.9,验证集只有0.5,换一个没见过的皮肤截图,直接检不到。
原因:韦恩的样本集中在少数皮肤或动作,模型记住了特定纹理而不是英雄的通用特征。
解决:统计韦恩类别的实例数,如果少于300,考虑从其他来源补充,或者对韦恩样本做更强的数据增强,比如随机裁剪、颜色抖动、遮挡。但颜色抖动要控制,别把韦恩的标志性特征也抖没了。另一个思路是把韦恩和其他英雄合并成一个大类,但这样会损失细粒度,看你的任务需求。
4.4 训练到一半loss变nan:标注里有零宽高框
现象:前几十轮正常,突然某一轮loss变成nan,训练中断。
原因:标注文件里有宽或高为0的框,计算损失时出现除零或log(0)。
解决:用第2章的体检脚本跑一遍,把所有w<=0或h<=0的行删掉或修正。如果体检时没发现,可能是数据增强过程中产生的,检查mosaic和mixup的实现是否有边界情况。YOLOv8官方实现一般不会,但如果你自己改了增强逻辑,就要查。
4.5 验证集mAP虚高:train和val有重复图片
现象:验证集mAP高得离谱,0.95以上,但实际推理新截图效果很差。
原因:train和val划分时没有去重,同一张图或高度相似的连续帧同时出现在两个集合里。
解决:用图片哈希或感知哈希做去重,确保train和val没有重叠。游戏截图如果是连续帧,相邻帧差异极小,必须按时间间隔划分,不能随机分。我一般会按视频片段划分,前80%片段做train,后20%做val,这样验证集才是真正的未见数据。
5. 从能跑到好用:类别重映射与推理后处理的两个进阶技巧
训练跑通只是第一步,真正要用起来,还得处理类别体系和你实际任务的对齐问题,以及推理时的后处理调优。这一章给两个具体技巧,都是我在实际部署时反复用到的。
5.1 类别重映射:把6类合并成3类提升鲁棒性
如果你的任务不关心队友和敌方小兵的具体区分,只关心“单位”和“建筑”,那可以把6类合并成3类:友方单位(队友+己方小兵)、敌方单位(敌方小兵+韦恩如果算敌方)、建筑(防御塔)。合并后类别数减少,类间混淆降低,mAP通常能涨3到5个点。
做法是在data.yaml里改names,同时用脚本把标注文件里的class_id做映射。映射关系写成一个字典,遍历所有txt文件替换第一列。
import os import glob # 类别重映射:6类合并为3类 # 0 teammate + 1 ally_minion -> 0 friendly # 2 enemy_minion + 4 vayne -> 1 hostile # 3 tower -> 2 building # 5 unknown -> 保留或删除,这里映射到2 id_map = {0: 0, 1: 0, 2: 1, 4: 1, 3: 2, 5: 2} label_dir = "labels/train" out_dir = "labels/train_remap" os.makedirs(out_dir, exist_ok=True) for txt_path in glob.glob(os.path.join(label_dir, "*.txt")): out_lines = [] with open(txt_path, "r") as f: for line in f: parts = line.strip().split() if len(parts) != 5: continue old_id = int(parts[0]) if old_id not in id_map: continue new_id = id_map[old_id] out_lines.append(f"{new_id} {' '.join(parts[1:])}") # 写入新目录,保持文件名一致 out_path = os.path.join(out_dir, os.path.basename(txt_path)) with open(out_path, "w") as f: f.write("\n".join(out_lines))这段脚本遍历标注文件,按id_map替换类别ID,写入新目录。id_map的键是原类别ID,值是目标类别ID。注意如果某个类别你不想保留,就不放进字典,对应的标注行会被跳过。跑完后记得同步更新data.yaml的nc和names,nc改成3,names改成friendly、hostile、building。
5.2 推理后处理:置信度阈值和NMS的联动调法
推理时有两个参数直接影响结果:conf置信度阈值和iou NMS的IoU阈值。默认conf=0.25、iou=0.7,但在游戏画面上,小兵密集时NMS会误删相邻的小兵框,防御塔则因为框大不容易被抑制。
我的调法是分类别设阈值。YOLOv8的推理接口支持agnostic_nms和按类别的conf,但更灵活的做法是推理后拿原始输出自己过滤。先用低conf(比如0.1)跑出所有候选框,然后对每个类别单独设conf阈值:小兵类给0.3,防御塔给0.5,韦恩给0.4。NMS的iou对小兵类降到0.5,避免密集场景误删,对防御塔保持0.7。
from ultralytics import YOLO import numpy as np model = YOLO("runs/lol_detect/exp01/weights/best.pt") results = model.predict("test_screenshot.jpg", conf=0.1, iou=0.7, verbose=False) # 按类别后处理 class_conf = {0: 0.3, 1: 0.3, 2: 0.3, 3: 0.5, 4: 0.4, 5: 0.5} class_iou = {0: 0.5, 1: 0.5, 2: 0.5, 3: 0.7, 4: 0.6, 5: 0.7} for r in results: boxes = r.boxes if boxes is None: continue cls_ids = boxes.cls.cpu().numpy().astype(int) confs = boxes.conf.cpu().numpy() # 按类别过滤 keep = np.array([confs[i] >= class_conf.get(cls_ids[i], 0.25) for i in range(len(cls_ids))]) filtered_boxes = boxes[keep] # 后续可对filtered_boxes按类别分别做NMS,这里省略具体实现 print(f"过滤后剩余 {len(filtered_boxes)} 个框")这段代码先以低conf推理拿到候选,再按类别阈值过滤。class_conf字典里每个类别的阈值根据实际验证集调,小兵类低一些保证召回,防御塔高一些保证精度。class_iou是预留的按类别NMS参数,实际实现需要调用torchvision的nms或自己写循环。参数不是固定的,你在自己的验证集上画PR曲线,找每个类别的F1最大点对应的conf,比拍脑袋设值靠谱。
5.3 一个验证技巧:用混淆矩阵反推标注质量
训练完看混淆矩阵,不只是看模型好坏,还能反推标注质量。如果某个类别的对角线数值明显低于同行其他格,说明这个类别的样本被大量标成了别的类。比如敌方小兵经常被预测成队友,除了模型问题,也可能是标注时颜色判断失误。把混淆矩阵和标注抽查结合,能定位到具体是哪些图片出了问题。
我一般会导出验证集的预测结果,和标注做逐图对比,把差异最大的前20张图挑出来人眼看。这个习惯帮我发现过好几次标注错误,比盲目调参有效得多。希望帮到你。
本文还有配套的精品资源,点击获取