☰
王者荣耀目标检测数据实战:YOLOv8训练到ONNX部署
2026/10/19 9:15:30 网站建设 项目流程

简介:王者荣耀目标检测数据集是一份面向计算机视觉学习者与研究者的游戏场景数据资源,聚焦英雄、怪物、防御塔、野怪等目标的位置与类别识别,可用于目标检测模型训练、算法效果对比及游戏人工智能相关课题研究。压缩包共810个文件,大小约230KB,其中806个TXT标注文件保存各场景的检测框坐标与类别标签,另附说明文档和辅助脚本,便于数据整理、标签转换与快速预览。当前已有122人浏览学习,适合希望以游戏画面为切入点开展目标检测实战的初学者,也适合进阶者扩展训练集与验证新模型。借助这些标注数据,可配合YOLO、Faster R-CNN、SSD等常见检测框架进行训练,直观理解标注格式、训练流程和调参思路;配套脚本能简化数据预处理环节。数据文件命名带有时间戳,便于按游戏时刻组织样本,整体是一个轻量但完整的目标检测实验素材,可支撑小规模实验、课程设计或算法复现。 做目标检测训练这几年,我收藏夹里躺得最多的不是论文链接,而是各种从社区和群文件里捡回来的数据压缩包。这次的“王者荣耀目标检测数据集_HonorOfKingsObjectDetection.zip”就是其中之一。光看文件名,它标榜的是王者荣耀游戏界面的目标检测数据集,用途很直白:从游戏画面中识别英雄、小兵、防御塔、水晶、野怪这类单位,输出带类别标签的检测框。

说实话,这种游戏数据集比普通的车辆、行人检测更有意思。游戏画面里的目标形态非常多变:英雄有不同皮肤、技能释放瞬间有各种特效、小兵成群结队密集排列、防御塔和野怪的光效还会随时间切换。拿它来练手目标检测,几乎能把会踩的坑都踩一遍。

这篇文章记录我拿到这个zip之后,从解压、格式识别、标注清理、训练调参到最终部署到ONNX的完整流程。如果你也在社区下载过类似的识别数据集,或者打算训练一个游戏画面目标检测模型,跟着走一遍能省下不少时间。

1. 解压前的信息侦察:从zip结构入手

1.1 先看压缩包,再谈训练

很多人拿到zip就双击解压,结果解到一半报错,或者解出来一堆乱码文件才后悔。我现在的习惯是先用命令把包里的目录结构过一遍,不用真的等解压完成:

unzip -l HonorOfKingsObjectDetection.zip | head -50

unzip -l列出的是压缩包内的文件清单,能看到有多少张图片、多少个标注文件,以及目录层级大概长什么样。如果这个包体积很大,用zipinfo也能达到类似效果。Windows用户直接用7-Zip打开压缩包也能预览内部结构。

这里有一个值得注意的点:游戏UI截图数据集经常包含大量中文文件名,zip包内部的文件名编码在Windows和Linux上处理方式不一样。Windows下解压正常,到了Linux解出来全是乱码,这是因为zip头里的文件名编码存在GBK和UTF-8两种历史遗留。遇到这种情况不要慌,用unzip -O gbk指定编码,或者在Python里自己控制解压过程:

import zipfile with zipfile.ZipFile("HonorOfKingsObjectDetection.zip") as zf: for name in zf.namelist(): print(name)

如果发现namelist()里是乱码,需要在解压时对文件名做编码修复。这个数据集的整体结构不算复杂,解压后大致是:

HonorOfKingsObjectDetection/ images/ img_0001.jpg ... labels/ img_0001.txt ...

1.2 目录结构与标注体系初判

解压完先别急着训练,先翻标注文件。目标检测数据集最常见的是两个“派系”:VOC的xml标注和YOLO的txt标注。VOC风格长这样:

<annotation> <folder>JPEGImages</folder> <filename>img_0001.jpg</filename> <size> <width>960</width> <height>540</height> <depth>3</depth> </size> <object> <name>hero</name> <bndbox> <xmin>123</xmin> <ymin>234</ymin> <xmax>310</xmax> <ymax>461</ymax> </bndbox> </object> </annotation>

YOLO风格则是纯文本,每行一个目标:

0 0.231 0.348 0.195 0.422

每行格式为类别id 中心点x 中心点y 宽度 高度,坐标全部归一化到0-1之间。这个包基本以YOLO txt为主,说明数据集已经被处理过一次,省去了最原始的xml转换工作。但别高兴太早,格式对不等于内容干净,标注质量还是要自己核查。

2. 标注质量核查:统计、过滤与坐标可视化

2.1 类别分布统计与异常过滤

无论标注是xml还是txt,第一件事是统计类别数量和样本分布。如果数据集没有提供classes.txt,就自己遍历所有标注文件:

import os from collections import Counter label_dir = "HonorOfKingsObjectDetection/labels" counter = Counter() for fname in os.listdir(label_dir): if not fname.endswith(".txt"): continue with open(os.path.join(label_dir, fname), "r", encoding="utf-8") as f: for line in f: parts = line.split() if len(parts) >= 5: counter[int(parts[0])] += 1 print(counter.most_common())

这里要留意两个问题。一是类别id可能不从0开始,或者中间断档。比如id=0到6都有值,但缺少某个id,或者标注文件里混入了异常行。二是类别不均衡,小兵、野怪的数量通常远多于水晶,这是游戏机制的天然结果,不算数据缺陷,但训练时如果不做任何平衡处理,模型会倾向于忽略稀有类别。

我统计下来的分布大致是:英雄、小兵、防御塔、水晶、野怪、红蓝buff等若干类别。数量上小兵和野怪明显占大头,水晶和基地样本很少。对于稀有一类,后续要么单独补数据,要么在loss里适当提高权重。

2.2 坐标合法性检查

这一步很多人会跳过,但恰恰是决定模型能不能训练好的地方。需要检查的点包括:

  • 坐标是否越界:YOLO归一化坐标必须在[0,1]区间
  • 宽高是否为0或负数:标注工具导出异常时经常出现
  • 空label文件:有些图片没有任何目标,可以忽略或删除

写一个小脚本过滤非法行:

def is_valid_line(line): parts = line.split() if len(parts) != 5: return False try: cid, cx, cy, w, h = map(float, parts) except ValueError: return False if cid < 0 or w <= 0 or h <= 0: return False if not (0 <= cx <= 1 and 0 <= cy <= 1): return False return True

我在这个数据集里确实扫出了几行宽高为0的脏数据,如果直接丢给训练框架,轻则梯度异常,重则训练中断。所以这一步千万别省。

2.3 可视化抽检标注框

坐标合法性通过之后,还要看标注框是否贴合目标。批量画几张预览图是最直观的方式:

import cv2 class_names = ["hero", "minion", "tower", "crystal", "monster"] def draw_yolo_box(img_path, label_path, class_names): img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path, "r") as f: for line in f: parts = line.split() if len(parts) != 5: continue cid, cx, cy, bw, bh = map(float, parts) x1 = int((cx - bw / 2) * w) y1 = int((cy - bh / 2) * h) x2 = int((cx + bw / 2) * w) y2 = int((cy + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, class_names[int(cid)], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1) cv2.imshow("preview", img) cv2.waitKey(0)

如果某个类别的框全都偏大或者偏小,说明是标注风格问题,训练出来的模型定位精度会受影响。这种问题在后期很难通过调参挽回,只能在训练前处理掉。

3. 整理为YOLO格式并用YOLOv8跑通首轮训练

3.1 数据目录划分与配置文件写法

数据集本身已经是YOLO txt格式,目录结构还要整理成YOLO训练框架期望的样子:

dataset/ images/ train/ val/ labels/ train/ val/

划分比例一般按9:1或8:2。划分时注意一个细节:如果图片文件名带帧号,尽量按连续帧分组,不要让同一局游戏的相邻帧被拆到train和val两边,否则验证指标会高估模型效果。我是先按文件名前缀分桶,再随机分配,保证同一场对局不会横跨两个集合。

然后创建配置文件,YOLOv8用yaml描述数据路径和类别名:

path: /path/to/dataset train: images/train val: images/val names: 0: hero 1: minion 2: tower 3: crystal 4: monster 5: buff 6: base

这里有个容易踩的坑:path如果写绝对路径,换机器后忘了改就报错。我后来统一用相对路径,把yaml放在dataset根目录下,train和val只写相对于yaml的路径。

3.2 训练命令与参数选择

安装ultralytics:

pip install ultralytics

然后启动训练:

yolo detect train data=honor_of_kings.yaml model=yolov8s.pt epochs=100 imgsz=640 batch=16 device=0

第一次跑通先用yolov8s,如果显存足够且类别数较多,换成yolov8m。针对这个数据集的画面比例,imgsz保持640基本没问题,游戏画面长宽比通常是16:9,letterbox处理会加黑边。

为什么选择YOLOv8而不是其他框架?它有健全的生态,内置mosaic、mixup等增强策略,标签分配用了解耦头与动态匹配,对中小目标相对友好。如果之后想对比其他网络,用mmdetection的RTMDet也是好选择,但首次跑通建议先用YOLO,简单省事。项目里的batch、epoch、imgsz三个参数是核心,epoch至少100起,游戏目标不算特别难,100轮足够看出趋势。

3.3 训练日志怎么看

训练时要看两类东西:loss曲线和验证集指标。如果loss在头部十几轮下降明显,后面缓慢收敛,这是正常状态。如果loss震荡剧烈,优先检查batch size和learning rate。YOLOv8默认学习率适合大多数情况,但如果batch很小,比如4或8,可以把学习率调低一点,否则梯度更新步长过大,loss会一直在高处抖动。

验证集mAP50如果能在50轮左右过0.6,说明数据集标注质量过关,接下来就可以继续优化了。如果mAP都快90轮还在0.3以下,大概率是数据问题,不是模型问题,回头检查类别映射和标注坐标。

4. 密集小目标漏检的优化实践

4.1 首次评估暴露出的问题

第一次训练完,我在验证集上试了几段录屏,发现英雄、防御塔、水晶这类大目标识别很稳,但小兵和技能特效的漏检率很高。分析下来原因很典型:小兵在画面里占的像素非常少,尤其远视角下往往只有15x15像素左右,加上多个小兵挤在一起互相遮挡,属于典型的“小目标+密集目标”组合问题。

如果是在实时视频流里做检测,漏检小兵会导致连续几帧目标数忽多忽少,后续任务根本没法用。

4.2 增强与分辨率调整

针对这个问题,我试了组合方案:

  • 提高输入分辨率。imgsz从640调整到960,甚至1280。代价是显存占用上升和推理速度下降。这个数据集里的游戏截屏原始分辨率如果是1920x1080,直接用1280训练比较合理,小目标会保留更多像素。
  • 调节mosaic增强。YOLOv8默认mosaic概率较高,对通用场景有帮助,但小目标较多时,mosaic拼图会裁掉不少小目标。把mosaic概率降低到0.5左右,小目标保存率会提高。
  • 做简单复制粘贴增强。对于水晶、基地这类稀有目标,可以把目标实例复制到画面中其他合理位置,人为增加样本量。
  • 调大最大检测框数量。游戏团战一帧可能同时出现30多个目标,虽然默认的max_det=300够用,但面对大规模团战,建议把max_det调到1000,避免后处理阶段丢检测框。

4.3 推理阈值与NMS调优

小目标检测的置信度天然偏低。默认conf阈值0.25会过滤掉很多真目标,我在推理阶段会降到0.15甚至0.1,然后靠NMS过滤重叠框。最终配置大致是conf=0.12,iou=0.50。如果误检很多,再把conf慢慢拉回去。

阈值这一步没有标准答案,核心逻辑是先让召回率上来,再用NMS和后续业务逻辑压制误检。对游戏画面,宁可多框几个候选,也不要漏掉关键目标。

5. 模型导出ONNX并在Python/C++环境部署

5.1 ONNX导出细节

训练完拿到best.pt,如果想脱离PyTorch环境运行,需要先导出ONNX:

yolo export model=best.pt format=onnx dynamic=True opset=12

dynamic=True让输入尺寸尽量可变。opset选择12是兼容性较好的版本,更高的opset在部分推理引擎上反而会出现算子支持问题。

导出成功后,强烈建议先打印输入输出tensor的形状。YOLOv8的不同版本导出的输出格式有差异,有些带NMS预处理,有些是原始预测结果,后处理逻辑完全不同。不确认这一点,后面代码会写得非常痛苦。

5.2 Python端onnxruntime推理

安装依赖:

pip install onnxruntime opencv-python

推理流程包含读取图片、letterbox缩放、归一化、模型推理、后处理几个环节。关键代码骨架如下:

import cv2 import numpy as np import onnxruntime as ort session = ort.InferenceSession( "best.onnx", providers=["CUDAExecutionProvider", "CPUExecutionProvider"] ) def letterbox(img, size=640): h, w = img.shape[:2] scale = min(size / w, size / h) nw, nh = int(w * scale), int(h * scale) img = cv2.resize(img, (nw, nh)) canvas = np.full((size, size, 3), 114, dtype=np.uint8) x, y = (size - nw) // 2, (size - nh) // 2 canvas[y:y + nh, x:x + nw] = img return canvas, scale, x, y image = cv2.imread("demo.jpg") input_img, scale, padx, pady = letterbox(image, 640) input_tensor = input_img[:, :, ::-1].astype(np.float32) / 255.0 input_tensor = np.transpose(input_tensor, (2, 0, 1))[np.newaxis] outputs = session.run( None, {session.get_inputs()[0].name: input_tensor} )[0]

后处理阶段,先看输出shape,再决定是直接解析还是先做解码。坐标还原到原图时,记得按letterbox的scale和pad偏移做逆变换。我一开始漏了这一步,所有检测框都偏到左上角,排查了好一会儿才发现是坐标映射问题。

5.3 C++部署的几个关键点

C++端部署我建议用onnxruntime C++库,它和Python端共享同一个模型文件。最核心的步骤是构造Ort::Session并填充输入输出张量:

#include <onnxruntime_cxx_api.h> #include <opencv2/opencv.hpp> Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "hok_detector"); Ort::SessionOptions options; options.SetIntraOpNumThreads(4); Ort::Session session(env, "best.onnx", options);

C++实现时最容易踩的坑是RGB/BGR通道顺序。OpenCV默认读图是BGR,如果模型训练时用了RGB,推理时需要cv::cvtColor(image, rgb_image, cv::COLOR_BGR2RGB)。这个错位不会直接报错,但检测精度会下降得很诡异,而且很难排查。

另外一个坑是输入张量的内存布局。onnxruntime要求数据连续,如果从cv::Mat直接塞进去,要确保按HWC转CHW并正确设置维度。先用Python端跑通一条完整链路,再对照C++输出,能省很多调试时间。

6. 这轮实践沉淀下来的几点经验

6.1 别只信mAP,多看一眼真实画面

YOLOv8训练结束会给出mAP50和mAP50-95,看到0.8的mAP很容易让人放心。但在游戏场景,mAP高不等于体验好。有些漏检在指标上看不出来,尤其小目标,比如一帧画面出现15个小兵,模型只框出10个,mAP下降不明显,但实际效果就是不可用。我习惯训练完会抽几段录屏跑可视化,亲眼看一下实时检测结果,比反复盯指标有用得多。

6.2 路径规范与数据一致性

解压、移动目录时,保持图片和标签的相对路径一致。如果图片和标签被拆到两个不同根目录,训练过程中会遇到大量“图片存在但标签不存在”的问题。我的经验是固定一个根目录,yaml里用相对路径引用,不要写死绝对路径。否则换一台机器,就得把所有路径都改一遍,很容易漏改。

6.3 先小步跑通,再全量训练

整个训练部署链路,无论是格式转换、训练还是导出,先用40-50张图把流程走通,再上全量数据。这个习惯帮我避免了好多次“训练了5小时后才发现数据路径写错”的尴尬。尤其是从社区下载的数据集,标注格式千奇百怪,先小批量跑通相当于给后面的全量训练买了一份保险。

这个数据集整体质量还算不错,整理之后可以支撑一个完整的游戏画面目标检测模型训练。如果你手上也有类似的社区数据集,按照这条链路走一遍,遇到的坑大概率就集中在格式、小目标、部署这三个环节,提前有个心理准备会从容很多。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询