简介:本资源是面向计算机视觉初学者与目标检测实践者的LOL英雄联盟角色检测专用数据集,适用于YOLO、Faster R-CNN等主流检测模型的训练与验证,特别适合游戏场景识别、小目标检测及多类别不平衡问题研究。数据集共3000张高质量JPG图像,配套3000份Pascal VOC格式XML标注文件与3000份YOLO格式TXT标注文件,涵盖6类关键游戏实体:己方小兵、己方防御塔、敌方小兵、敌方防御塔、英雄露西(LUX)和韦恩(VAYNE),总标注框数达24665个,标注由labelImg工具完成,矩形框规范清晰。压缩包含2000个文件(1999个XML+1个说明txt),大小135.85MB,结构简洁,开箱即用。目前已有460人学习下载,资源附带说明文档及典型样本XML文件,便于快速校验标注格式、理解类别映射关系与开展数据预处理,是入门游戏AI视觉任务的实用型训练素材。
1. 这不是游戏截图合集,而是一套可直接喂进YOLOv8训练管道的LOL实战级目标检测数据集
你手头那套标注了“小兵”“防御塔”“韦恩”的3000张图,不是拿来凑数的素材包——它是一套结构完整、类别明确、格式双备(VOC+YOLO)、且已通过labelImg人工校验的工业级目标检测数据集。它解决的不是“能不能识别”,而是“在真实LOL对战画面中,模型能否稳定区分己方/敌方单位、建筑与英雄”这一具体问题。6类标签覆盖MOBA场景核心交互对象:AllyMinions(我方小兵)和EnemyMinions(敌方小兵)数量悬殊(7339 vs 10973),反映实际推线压力;LUX与VAYNE作为高辨识度英雄样本,分别提供1531和3669个框,足够支撑单类fine-tune;而AllyTower/EnemyTower虽仅551/602框,但其结构刚性、边缘清晰,是验证模型定位鲁棒性的关键锚点。适合正在用YOLOv8或YOLOv5搭建LOL辅助识别模块的开发者、需要MOBA领域迁移学习基线的算法工程师,以及想绕过数据采集与标注环节、直接验证检测pipeline的同学。它不承诺上线精度,但保证每张jpg都有对应xml和txt,每个框都符合Pascal VOC坐标规范(xmin,ymin,xmax,ymax),且YOLO格式txt中类别索引严格按["AllyMinions","AllyTower","EnemyMinions","EnemyTower","LUX","VAYNE"]顺序映射为0~5。
2. 从VOC到YOLO:双格式数据集的结构解析与路径规范化处理
2.1 数据集目录结构与文件命名逻辑
解压后你会看到三个并列目录:JPEGImages/(存放3000张.jpg)、Annotations/(存放3000个.xml)、labels/(存放3000个.txt)。注意:Annotations/中的XML文件名与JPEGImages/中JPG文件名完全一致(如xyxr_images_2703.jpg↔xyxr_images_2703.xml),这是VOC标准要求;而labels/下的TXT文件名也严格同步(xyxr_images_2703.txt),且内容为YOLO格式:<class_id> <x_center> <y_center> <width> <height>(归一化到0~1)。这种命名一致性是后续自动划分训练/验证集的前提。若发现某JPG缺失对应XML或TXT,说明该样本标注不全,需剔除——本数据集已声明“标注数量=图片数量=3000”,故理论上无缺失,但建议首次加载时用脚本校验:
# bash校验脚本:检查三目录文件名是否完全一致 cd /path/to/dataset find JPEGImages -name "*.jpg" | sed 's/JPEGImages\///; s/\.jpg$//' | sort > jpg_list.txt find Annotations -name "*.xml" | sed 's/Annotations\///; s/\.xml$//' | sort > xml_list.txt find labels -name "*.txt" | sed 's/labels\///; s/\.txt$//' | sort > txt_list.txt diff jpg_list.txt xml_list.txt || echo "JPG与XML文件名不匹配" diff jpg_list.txt txt_list.txt || echo "JPG与TXT文件名不匹配"提示:
sed命令剥离路径和扩展名,sort确保顺序一致,diff输出为空表示完全匹配。此步骤必须执行,避免因文件系统大小写敏感或隐藏字符导致后续训练报错。
2.2 VOC XML解析:提取坐标并验证标注合理性
每个XML文件遵循Pascal VOC标准,关键字段为<object>下的<bndbox>。以xyxr_images_2703.xml为例,其<bndbox>内含<xmin>,<ymin>,<xmax>,<ymax>。需确认两点:一是坐标值是否越界(如xmin < 0或xmax > image_width),二是宽高是否为正(xmax > xmin且ymax > ymin)。以下Python脚本批量校验并统计异常:
# python3 check_voc_bbox.py import os import xml.etree.ElementTree as ET from PIL import Image voc_dir = "Annotations" jpg_dir = "JPEGImages" errors = [] for xml_file in os.listdir(voc_dir): if not xml_file.endswith(".xml"): continue xml_path = os.path.join(voc_dir, xml_file) jpg_path = os.path.join(jpg_dir, xml_file.replace(".xml", ".jpg")) # 获取图像尺寸 try: img = Image.open(jpg_path) w, h = img.size except Exception as e: errors.append(f"Image missing or corrupt: {jpg_path}") continue # 解析XML tree = ET.parse(xml_path) root = tree.getroot() for obj in root.findall("object"): 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) # 检查越界与负值 if xmin < 0 or ymin < 0 or xmax > w or ymax > h or xmax <= xmin or ymax <= ymin: errors.append(f"Invalid bbox in {xml_file}: ({xmin},{ymin},{xmax},{ymax}) on {w}x{h}") print(f"Total errors: {len(errors)}") for e in errors[:5]: # 仅显示前5个错误 print(e)注意:脚本中
w, h = img.size获取原始图像分辨率,所有坐标必须在此范围内。若发现越界框,需用labelImg重新打开对应XML修正——本数据集虽声明“准确标注”,但人工标注难免疏漏,此步不可跳过。
2.3 YOLO TXT生成逻辑与归一化验证
YOLO格式要求将VOC坐标转换为归一化中心点坐标及宽高比例:x_center = (xmin + xmax) / (2 * image_width)y_center = (ymin + ymax) / (2 * image_height)width = (xmax - xmin) / image_widthheight = (ymax - ymin) / image_height
验证方法:随机抽取一个TXT文件(如xyxr_images_2703.txt),读取首行0 0.421 0.635 0.124 0.218,反向计算原始坐标:xmin = (0.421 - 0.124/2) * w ≈ 0.359wxmax = (0.421 + 0.124/2) * w ≈ 0.483w
再比对同名XML中<xmin>和<xmax>值是否匹配。以下代码实现批量反向校验:
# python3 validate_yolo_txt.py import os from PIL import Image def yolo_to_voc(yolo_line, img_w, img_h): parts = list(map(float, yolo_line.strip().split())) cls_id, x_c, y_c, w, h = parts[0], parts[1], parts[2], parts[3], parts[4] xmin = max(0, int((x_c - w/2) * img_w)) ymin = max(0, int((y_c - h/2) * img_h)) xmax = min(img_w, int((x_c + w/2) * img_w)) ymax = min(img_h, int((y_c + h/2) * img_h)) return xmin, ymin, xmax, ymax labels_dir = "labels" jpg_dir = "JPEGImages" mismatches = [] for txt_file in os.listdir(labels_dir): if not txt_file.endswith(".txt"): continue txt_path = os.path.join(labels_dir, txt_file) jpg_path = os.path.join(jpg_dir, txt_file.replace(".txt", ".jpg")) try: img = Image.open(jpg_path) w, h = img.size except: continue with open(txt_path) as f: lines = f.readlines() if not lines: continue # 取第一行(假设单类为主) yolo_line = lines[0] xmin_yolo, ymin_yolo, xmax_yolo, ymax_yolo = yolo_to_voc(yolo_line, w, h) # 读取同名XML的首个bbox(简化验证) xml_path = os.path.join("Annotations", txt_file.replace(".txt", ".xml")) try: import xml.etree.ElementTree as ET tree = ET.parse(xml_path) obj = tree.getroot().find("object") bbox = obj.find("bndbox") xmin_xml = int(bbox.find("xmin").text) ymin_xml = int(bbox.find("ymin").text) xmax_xml = int(bbox.find("xmax").text) ymax_xml = int(bbox.find("ymax").text) if abs(xmin_yolo - xmin_xml) > 2 or abs(ymin_yolo - ymin_xml) > 2: mismatches.append(f"Mismatch in {txt_file}: YOLO({xmin_yolo},{ymin_yolo}) vs XML({xmin_xml},{ymin_xml})") except: pass print(f"YOLO-XML mismatch count: {len(mismatches)}")提示:容差设为2像素是因浮点归一化四舍五入导致的微小偏差。若
mismatches非空,说明YOLO TXT生成有误,需重新用voc2yolo工具转换——本数据集虽提供双格式,但校验是训练前必经步骤。
3. YOLOv8训练全流程:从环境配置到mAP验证的实操细节
3.1 环境准备与数据集目录重构
YOLOv8要求数据集按train/val/test三级目录组织,且images/与labels/需平行放置。本数据集原始结构需重构。首先创建标准目录:
# 创建YOLOv8兼容目录结构 mkdir -p lol_dataset/{train,val,test}/{images,labels} # 假设你已将原始数据集解压至 ./lol_raw/ # 按8:1:1比例划分(2400:300:300) cd lol_raw shuf -n 2400 < <(ls JPEGImages/*.jpg | sed 's/JPEGImages\///; s/\.jpg$//') > train_list.txt shuf -n 300 < <(grep -v -f train_list.txt <(ls JPEGImages/*.jpg | sed 's/JPEGImages\///; s/\.jpg$//')) > val_list.txt shuf -n 300 < <(grep -v -f train_list.txt <(grep -v -f val_list.txt <(ls JPEGImages/*.jpg | sed 's/JPEGImages\///; s/\.jpg$//'))) > test_list.txt # 复制文件(使用循环避免xargs参数过长) while read name; do cp JPEGImages/${name}.jpg ../lol_dataset/train/images/; cp labels/${name}.txt ../lol_dataset/train/labels/; done < train_list.txt while read name; do cp JPEGImages/${name}.jpg ../lol_dataset/val/images/; cp labels/${name}.txt ../lol_dataset/val/labels/; done < val_list.txt while read name; do cp JPEGImages/${name}.jpg ../lol_dataset/test/images/; cp labels/${name}.txt ../lol_dataset/test/labels/; done < test_list.txt注意:
shuf命令随机采样,grep -v -f排除已选文件,确保无重叠。cp操作需确认源路径正确——若原始数据集未解压到lol_raw/,请替换为实际路径。
3.2 配置文件编写与类别映射定义
YOLOv8需data.yaml定义路径与类别。创建lol_dataset/data.yaml:
train: ../lol_dataset/train/images val: ../lol_dataset/val/images test: ../lol_dataset/test/images nc: 6 names: ["AllyMinions", "AllyTower", "EnemyMinions", "EnemyTower", "LUX", "VAYNE"]关键点:nc: 6必须与names列表长度一致;names顺序必须与YOLO TXT中class_id(0~5)严格对应;路径使用相对路径(从训练脚本所在目录起算)。若训练脚本位于yolov8/目录下,则train:应指向../lol_dataset/train/images。
3.3 模型训练命令与关键参数调优
使用官方ultralytics库启动训练。以下命令针对LOL数据集特性优化:
# 安装依赖(若未安装) pip install ultralytics # 启动训练(GPU加速) yolo detect train \ data=lol_dataset/data.yaml \ model=yolov8n.pt \ # 轻量级起点,显存<4GB可用 epochs=100 \ batch=16 \ # 根据GPU显存调整:RTX3090可设32,GTX1660设8 imgsz=640 \ # LOL画面常含密集小兵,640分辨率平衡细节与速度 name=lol_v8n_finetune \ patience=10 \ # 早停:验证mAP10连续10轮不升则终止 lr0=0.01 \ # 初始学习率,较COCO默认0.01略高(因数据量小) lrf=0.1 \ # 最终学习率 = lr0 * lrf = 0.001 hsv_h=0.015 \ hsv_s=0.7 \ hsv_v=0.4 \ # 颜色扰动增强,应对LOL不同皮肤色调 degrees=5 \ translate=0.1 \ scale=0.5 \ shear=0 \ # 几何增强幅度,避免过度扭曲塔/兵模型 mosaic=1.0 \ mixup=0.1 \ # Mosaic提升小目标检测,mixup防过拟合 cache=True # 启用内存缓存,加速IO(需16GB RAM以上)提示:
mosaic=1.0强制启用马赛克增强,对小兵(AllyMinions/EnemyMinions)检测提升显著;hsv_s=0.7大幅调整饱和度,模拟不同英雄皮肤(如VAYNE的暗红vs LUX的亮蓝);patience=10防止在300张验证集上过拟合。
3.4 训练过程监控与mAP指标解读
训练日志会实时输出metrics/mAP50-95(B)(即IoU阈值0.5~0.95的平均精度)。重点关注:
mAP50:IoU=0.5时的精度,反映基础定位能力;mAP75:IoU=0.75时的精度,检验框 tightness;mAP50-95:COCO标准指标,综合评估。
LOL数据集因小兵密集、尺度变化大,mAP50达0.75+即属良好,mAP75超0.55表明模型能准确定位塔/英雄。若mAP50-95低于0.3,需检查:
- 是否
data.yaml中names顺序与TXTclass_id错位; imgsz是否过小导致小兵丢失(尝试imgsz=736);batch是否过大引发梯度爆炸(降低至8)。
验证命令:
yolo detect val \ data=lol_dataset/data.yaml \ model=runs/detect/lol_v8n_finetune/weights/best.pt \ split=val结果生成confusion_matrix.png,可直观查看类别混淆(如AllyMinions误检为EnemyMinions)。
4. 类别不平衡应对与LOL场景特化后处理技巧
4.1 针对小兵类别的损失加权与采样策略
数据集中EnemyMinions框数(10973)是AllyTower(551)的20倍,直接训练会导致模型偏向高频类。YOLOv8原生不支持类别权重,需修改损失函数。在ultralytics/utils/loss.py中定位BCEWithLogitsLoss调用处,注入pos_weight:
# 修改前(约line 120) self.BCEcls = nn.BCEWithLogitsLoss(reduction='none') # 修改后 # 计算各类别正样本权重:总框数/该类框数 cls_weights = torch.tensor([24665/7339, 24665/551, 24665/10973, 24665/602, 24665/1531, 24665/3669]) self.BCEcls = nn.BCEWithLogitsLoss(pos_weight=cls_weights, reduction='none')注意:
cls_weights需按names顺序排列,且必须在model.train()前加载。此修改使AllyTower等稀有类损失放大,迫使模型关注其特征。
4.2 LOL画面特有的NMS阈值调优
默认NMS IoU阈值0.7对LOL不适用:敌我小兵常并排站立,IoU易超0.7导致误删。实测将conf(置信度阈值)设为0.3、iou(NMS阈值)降至0.45,可提升小兵召回:
# 推理时指定参数 results = model.predict( source="test_image.jpg", conf=0.3, # 低置信度阈值,捕获更多小兵 iou=0.45, # 严苛NMS,防止相邻小兵合并 classes=[0,2], # 仅检测小兵类,加速推理 verbose=False )4.3 基于游戏逻辑的后处理规则引擎
单纯依赖模型输出易出错(如将草丛阴影误检为VAYNE)。加入轻量级规则可提升鲁棒性:
- 塔存在性验证:若检测到
AllyTower,其周围50像素内出现AllyMinions,则提高该小兵置信度; - 英雄位置约束:
LUX/VAYNE应远离兵线(距最近小兵>100像素),否则降分; - 阵营一致性:同一帧中
AllyMinions与EnemyMinions数量比应在0.8~1.2之间,偏离则触发人工复核。
以下伪代码实现塔-小兵联动:
def post_process_tower_minion(results, img_shape): boxes = results[0].boxes.xyxy.cpu().numpy() # [x1,y1,x2,y2] classes = results[0].boxes.cls.cpu().numpy() confs = results[0].boxes.conf.cpu().numpy() tower_boxes = boxes[classes == 1] # AllyTower class_id=1 minion_boxes = boxes[classes == 0] # AllyMinions class_id=0 # 对每个塔,查找邻近小兵 for t_box in tower_boxes: t_cx = (t_box[0] + t_box[2]) / 2 t_cy = (t_box[1] + t_box[3]) / 2 for i, m_box in enumerate(minion_boxes): m_cx = (m_box[0] + m_box[2]) / 2 m_cy = (m_box[1] + m_box[3]) / 2 dist = ((t_cx - m_cx)**2 + (t_cy - m_cy)**2)**0.5 if dist < 50: # 像素距离 confs[i] *= 1.3 # 提升置信度 return confs提示:此规则无需额外训练,仅在推理后运行,毫秒级开销。实际部署时,可将
dist < 50改为基于图像分辨率的动态阈值(如dist < 0.03 * img_shape[1])。
4.4 模型轻量化部署到游戏辅助工具的关键参数
若需集成到实时辅助工具(如FPS>30的屏幕捕获程序),需平衡精度与延迟:
- 使用
yolov8n而非s/m,模型大小<3MB; imgsz=320(非640),推理速度提升2.1倍;- 启用TensorRT加速(需NVIDIA GPU):
yolo export model=lol_v8n_finetune.pt format=engine half=True dynamic=True- 输出层截断:仅保留
boxes与cls,丢弃masks(本数据集无分割)。
最终部署时,conf=0.25、iou=0.3、agnostic_nms=True(跨类NMS)可进一步减少冗余框。
本文还有配套的精品资源,点击获取