简介:一套基于YOLOv8框架的游戏自动化测试与质量评估系统,面向游戏测试工程师、计算机视觉开发者和自动化测试脚本编写人员。系统覆盖游戏画面识别、实时目标检测、异常行为监控、游戏元素定位、动态场景处理及多分辨率适配等能力,配合自动化测试脚本可自动执行负载、压力等测试,并输出性能分析报告。压缩包共753个文件,约101.37MB,包含Python源码(162个py)、Markdown文档(300个md)、YOLO配置(60个yaml)、预训练模型和onnx导出模型,以及dll、json、txt等辅助资源;同时提供Dockerfile与shell脚本,便于快速部署环境。目前已有83人学习使用。借助附带的说明文件、开发文档和主工程源码,读者可复现YOLOv8游戏检测流程,掌握自动化测试脚本编写与性能报告生成逻辑,并参考多分辨率适配策略将系统扩展到更多游戏场景。
1. 游戏测试还在人工盯屏?YOLOv8把“看见画面”变成了可断言的结构化数据
做游戏自动化测试,踩得最多的坑不是脚本不稳定,而是脚本“看不见”。按钮弹没弹、加载图标转没转、结算面板出没出,全靠坐标硬等,版本一更新换了 UI 就全线翻车。基于 YOLOv8 计算机视觉框架做游戏画面识别,等于给测试脚本装了一双眼睛:实时目标检测输出元素坐标与类别,自动化测试脚本根据结果执行点击和断言,性能分析报告和异常行为监控也都有了数据来源。这套方案适合游戏 QA、自动化测试开发、客户端质量平台的工程师,目标很直接:把肉眼回归变成可重复、可量化的机器检查。
游戏测试最贵的成本是“人眼盯屏”,而 YOLOv8 把这块成本换成了一次模型训练和持续的录像回归。后面我按实际落地的顺序展开:为什么选 YOLOv8、数据怎么准备、坐标怎么变成操作、报告怎么看、坑在哪,最后给一个我常用的验证套路。
2. 游戏画面识别为什么选 YOLOv8:模板匹配的边界与检测系统骨架
2.1 游戏元素定位的选型逻辑:模板匹配、传统CV与YOLOv8的取舍
做游戏画面识别,第一反应往往是模板匹配:截一张按钮小图,滑窗去原图里找相似度。这个思路在“图标完全不变、没有缩放、没有压暗”的前提下能跑,但真实游戏 UI 根本不是这样。按钮有圆角渐变、hover 变色、New 角标、键盘焦点高亮,技能图标还带粒子特效,模板匹配的相似度会直接跌破阈值。更麻烦的是多分辨率,同一个“开始游戏”按钮在 720p 和 2K 下大小差两倍,模板得准备好几套。
传统 CV 也有边界。颜色阈值和轮廓查找适合血条、能量条这类颜色稳定的元素,但碰上“关闭按钮”这种带半透明遮罩、边缘不清晰的控件,阈值怎么调都是玄学。游戏画面又是场景、角色、特效混在一起的,背景干扰远大于工业质检里的传送带。
YOLOv8 走的是另一条路:不预设元素长什么样,而是让模型自己从标注数据里学特征。从网络结构图能看到,YOLOv8 的 backbone 用 C2f 模块提特征,head 是 anchor-free 的解耦结构,分类和回归分开输出。这对游戏 UI 这种“小目标密集、背景复杂”的场景很合适:模型同时输出类别、置信度和边界框,一个前向推理就能拿到整个画面的结构化信息。生态也友好,ultralytics 包开箱即用,CLI 和 Python API 都有,新手也能快速跑通。
| 维度 | 模板匹配 | 传统CV | YOLOv8目标检测 |
|---|---|---|---|
| 缩放鲁棒性 | 差 | 一般 | 好 |
| 变色/半透明 | 差 | 一般 | 好 |
| 动态特效遮挡 | 差 | 差 | 较好 |
| 多类别同时输出 | 不支持 | 需分别处理 | 支持 |
| 多分辨率适配 | 需多套模板 | 需重算几何 | letterbox+多尺度 |
| 开发成本 | 低 | 中 | 中高,需准备数据 |
2.2 系统骨架:图像采集、检测服务、测试脚本与评估端如何分工
这套系统不是“一个模型跑起来”就完事,我一般拆成四个独立模块,方便后续各自升级。
| 模块 | 职责 | 输出 |
|---|---|---|
| 图像采集 | 截屏、录屏、多窗口捕获,统一帧格式 | 原始画面帧 |
| 检测服务 | YOLOv8 模型推理,解析 boxes/cls/conf | 结构化检测结果 |
| 测试脚本 | 消费检测结果,执行点击、拖拽、等待 | 游戏操作与用例日志 |
| 评估与监控 | 汇总延迟、FPS、误检漏检,识别卡死/黑屏 | 性能分析报告、异常告警 |
分工的原因很实际:模型更新时测试脚本不用动,测试脚本重写时检测服务不用动。游戏测试场景和工业质检还有一个区别,画面是合成的,UI 元素相对规则,但弹窗盖弹窗、镜头抖动、技能特效会把画面搅得很乱,所以检测服务要独立成一个“视觉黑匣子”,对外只暴露坐标和置信度。
2.3 用最小命令把 YOLOv8 跑起来:从环境搭建到单张截图推理
先在 Ubuntu 20.04 上搭一个能跑的环境。CPU 版本也能推理,但游戏画面识别对延迟敏感,建议推理侧用 GPU。环境搭建命令如下:
# 创建 Python 3.9 虚拟环境 conda create -n game-det python=3.9 -y conda activate game-det # 安装 ultralytics,会自动拉取 torch 等依赖 pip install ultralytics # 验证 CLI 是否可用 yolo help依赖装好后,下载官方预训练权重并跑一张游戏截图。这里先用 yolov8n.pt,模型最小,验证链路最合适:
from ultralytics import YOLO # 预训练权重会自动下载,首次运行稍慢 model = YOLO("yolov8n.pt") # 对本地截图做推理 results = model.predict( source="shop_ui.png", # 游戏商店界面截图 conf=0.25, # 置信度阈值 imgsz=640, # 推理分辨率 save=True ) # 打印第一个目标的类别、置信度、坐标 for box in results[0].boxes: print(box.cls, box.conf, box.xyxy)逻辑说明:官方预训练权重是 COCO 80 类,第一次跑拿不到游戏 UI 元素,这一步只验证“环境通、推理链路通”。参数上,conf=0.25是起步值,游戏元素误检率高时我会提到 0.3 甚至 0.4;imgsz=640是推理时的 letterbox 尺寸,不是截图原始分辨率。如果截图是 2K,UI 元素普遍较小,建议换 yolov8s 或 yolov8m,并把imgsz调到 960,代价是单帧延迟从 20ms 涨到 60ms 左右。
这一步跑通后,整个系统的“眼睛”就有了,接下来要解决的是让这双眼睛认识游戏里的具体元素。
3. 游戏元素定位与多分辨率适配:从 labelme 标注到训练推理
3.1 标哪些元素、怎么用 labelme 转成 YOLO 训练格式
训练自己的数据集,第一版别贪多。我踩过的坑是上来就标了 18 个类别,结果样本不均衡,训练两三百轮 mAP 才 0.3。第一次建议只标 5 到 6 个高频元素:
| 类别 | 示例 | 为什么值得标 |
|---|---|---|
| start_btn | 开始游戏按钮 | 冒烟测试主入口 |
| close_btn | 弹窗关闭按钮 | 最常用、常被误点 |
| ok_btn | 确认按钮 | 各种弹窗的公共按钮 |
| loading_icon | 转圈加载图标 | 加载状态判断 |
| battle_btn | 战斗入口 | 核心玩法入口 |
| red_dot | 红点提示 | 活动/邮件提醒,易漏检 |
标注工具用 labelme,画矩形框即可。标注完成后,labelme 存的是 JSON 多边形或多点坐标,YOLO 训练要的是class x_center y_center w h这种归一化格式,需要转换。转换脚本我这样写:
import json import os def labelme_to_yolo(json_path, class_dict, output_dir): """ 把 labelme 的 JSON 标注转成 YOLO 格式的 txt class_dict: {"start_btn": 0, "close_btn": 1, ...} """ with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) img_w, img_h = data["imageWidth"], data["imageHeight"] lines = [] for shape in data["shapes"]: label = shape["label"] if label not in class_dict: continue # labelme 的 points 是 [[x1, y1], [x2, y2]] pts = shape["points"] xs = [p[0] for p in pts] ys = [p[1] for p in pts] x_min, x_max = min(xs), max(xs) y_min, y_max = min(ys), max(ys) # 全部归一化到 [0, 1] cx = (x_min + x_max) / 2 / img_w cy = (y_min + y_max) / 2 / img_h bw = (x_max - x_min) / img_w bh = (y_max - y_min) / img_h lines.append(f"{class_dict[label]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}") txt_path = os.path.join(output_dir, os.path.basename(json_path).replace(".json", ".txt")) with open(txt_path, "w", encoding="utf-8") as f: f.write("\n".join(lines))逻辑说明:labelme 的框可能是倾斜多边形,我这里取外接矩形的左上和右下点。坐标归一化这一步不能省,YOLO 训练要求所有坐标除以图片宽高。注意类别 ID 必须从 0 开始连续编号,不连续会训练报错。另外我遇到过一个问题:图片太大、目标太小时,直接丢进 YOLO 学不好。比如 2K 截图里一个 30 像素的红点,建议先把原图切片成 640 或 960 的 patch 再标注,或者用“先粗检再放大”的二级结构,这个后面细说。
3.2 多分辨率适配不是 resize:letterbox、推理尺寸与坐标映射
多分辨率适配是游戏测试的硬需求。同一个游戏在 PC 上有 1080p、2K,模拟器上有各种手机分辨率,测试机还会窗口化。最容易翻车的做法是自己把原图直接cv2.resize成 640x640,UI 元素被压扁,坐标还得手动换算回去。
YOLOv8 内部默认做 letterbox:等比缩放后把剩余区域填充灰边,保证画面不畸变。推理时imgsz控制的是 letterbox 后的尺寸,选多少要看元素大小而不是只看分辨率。我一般这样动态选:
import cv2 from ultralytics import YOLO model = YOLO("best.pt") # 任意分辨率的截图 frame = cv2.imread("phone_1080p.png") h, w = frame.shape[:2] # 根据分辨率切推理尺寸:目标越小、分辨率越高,imgsz 越大 if w >= 2560: imgsz = 1280 elif w >= 1920: imgsz = 960 elif w >= 1280: imgsz = 960 else: imgsz = 640 results = model.predict(frame, imgsz=imgsz, conf=0.3) for box in results[0].boxes: # xyxy 已经是逆映射回原图的坐标,直接用 print(box.xyxy.cpu().numpy(), box.cls.cpu().numpy(), box.conf.cpu().numpy())逻辑说明:box.xyxy是经过 letterbox 逆映射后的原图坐标,不需要自己算比例。这里有一个很隐蔽的坑:如果你自己先 resize 再传进去,模型输出坐标基于的是你 resize 后的图,坐标就得按缩放比映射回去,一旦宽高比不一致就错位。所以我都是把原始帧直接传给predict,让 ultralytics 内部处理 letterbox。
训练侧也要配合多分辨率。ultralytics 默认开启多尺度训练,每轮迭代会随机把输入缩放 50% 到 150%,所以训练时不用额外写增强。但要注意imgsz不要设太低,我训练游戏 UI 类小目标一般从 640 起,元素特别小的加到 960,代价是训练显存占用增大。
3.3 训练自己的检测模型:参数含义、早停与损失曲线怎么看
数据准备好后,先建一个data.yaml,指向训练集和验证集:
path: datasets/game_ui train: images/train val: images/val names: 0: start_btn 1: close_btn 2: ok_btn 3: loading_icon 4: battle_btn 5: red_dot然后开始训练。我拿 yolov8s.pt 做预训练权重,因为游戏 UI 和 COCO 场景差得远,从头训会慢很多,基于 COCO 权重微调是最稳的做法:
yolo detect train \ data=datasets/game_ui/data.yaml \ model=yolov8s.pt \ epochs=200 \ imgsz=640 \ batch=16 \ patience=30 \ lr0=0.01 \ project=runs/train \ name=game_ui_v1参数含义:epochs=200是上限,实际跑不到那么多,patience=30表示验证集指标连续 30 轮不提升就早停,省时间也防过拟合;batch=16要根据显存调,显存不够就 8;lr0=0.01是起步学习率,微调场景我一般不改。训练结束后,在runs/train/game_ui_v1/下会生成results.png,里面是 box_loss、cls_loss、dfl_loss 的曲线图。自定义数据集上如果 box_loss 下降很慢,先去看标注框是不是有大量漏标或错标,而不是急着调学习率。
评估环节我这样跑:
from ultralytics import YOLO model = YOLO("runs/train/game_ui_v1/weights/best.pt") metrics = model.val(data="datasets/game_ui/data.yaml") print(metrics.box.map) # mAP50-95 print(metrics.box.map50) # mAP50游戏测试场景我更看重 mAP50。UI 元素的边界框不需要像素级精确,任务是“找到它、点它”,mAP50 上去比 mAP50-95 更有意义。如果 mAP50 在 0.9 以上,但实际运行还是漏检,多半不是模型问题,而是测试场景里有训练集没见过的特效帧或新 UI 状态,这个放到第 5 章说。
4. 实时目标检测与自动化测试脚本对接:把检测坐标变成游戏操作和断言
4.1 检测结果到屏幕操作:窗口偏移、点击与异步队列
模型输出的是截图坐标系里的框,自动化脚本要用它做两件事:把坐标映射成屏幕坐标,然后执行点击。全屏截图时,截图坐标系等于屏幕坐标系;窗口化游戏时,需要加上窗口在桌面上的偏移量,否则会点到旁边的浏览器。
import pyautogui import time def click_by_detection(result, target_cls, class_names, window_offset=(0, 0)): """ result: YOLOv8 单帧预测结果 target_cls: 要点击的类别名,比如 "start_btn" window_offset: 游戏窗口在桌面上的偏移 (offset_x, offset_y) """ for box in result.boxes: cls_id = int(box.cls.item()) conf = float(box.conf.item()) if class_names[cls_id] != target_cls: continue # 取框中心点,加窗口偏移 x1, y1, x2, y2 = [int(v) for v in box.xyxy[0].tolist()] cx = int((x1 + x2) / 2) + window_offset[0] cy = int((y1 + y2) / 2) + window_offset[1] # 先移动再点击,停顿 50ms 更接近人工操作 pyautogui.moveTo(cx, cy, duration=0.1) time.sleep(0.05) pyautogui.click() return True return False逻辑说明:duration=0.1让鼠标有移动轨迹,有些游戏对瞬时跳变的点击有防作弊判定,直接闪现点击会无效。另外 pyautogui 在某些独显渲染的游戏窗口里会失效,常见原因是权限,脚本要以管理员权限跑;如果还不行,改用 Windows 下的 win32 SendMessage 后台发送鼠标消息。这里我建议把点击动作放到独立线程,不要在检测线程里直接 click,检测一旦延迟,鼠标就会抽搐。
4.2 实时检测流水线:生产者消费者模型与帧率控制
游戏自动化脚本最常见的翻车是“检测和操作互相卡”。截图线程、检测线程、操作线程如果捏在一起,某一帧检测慢了,整个用例就跟着抖。我一般用生产者消费者模型:截图线程生产帧,检测线程消费,检测结果放进队列,操作脚本从队列取“最新结果”。
import threading import queue from ultralytics import YOLO class DetectorLoop: def __init__(self, screen_getter): self.model = YOLO("best.pt") self.screen_getter = screen_getter # 截图回调,每次返回一帧 self.result_q = queue.Queue(maxsize=2) self.stop = False self.thread = threading.Thread(target=self._run, daemon=True) self.thread.start() def _run(self): while not self.stop: frame = self.screen_getter() if frame is None: continue result = self.model.predict(frame, imgsz=960, conf=0.3, verbose=False)[0] # 队列满了就丢最旧的一帧,保证消费端拿到的是最新结果 if self.result_q.full(): try: self.result_q.get_nowait() except queue.Empty: pass self.result_q.put(result) def latest(self): """取最新一帧检测结果,没有则返回 None""" try: return self.result_q.get_nowait() except queue.Empty: return None逻辑说明:队列容量设为 2,满了丢旧帧,这是故意的。游戏测试注重的不是“每一帧都检测”,而是“操作时拿到的画面状态足够新鲜”。如果队列无限堆积,操作脚本会处理一堆早已过期的帧,延迟越来越大。检测线程的帧率不用跑满,我一般控制在 15 到 20 FPS,给 CPU 和显卡留余量。测试环境的机器通常不只是跑游戏,还要跑录制和日志,资源预留很重要。
4.3 异常行为监控:卡死、黑屏与加载超时的状态机识别
性能分析报告里最值钱的部分不是快慢,而是“异常有没有被抓到”。用检测结果做异常监控,核心不是单帧判断,而是状态持续时长。比如黑屏:连续 2 秒检测不到任何预期元素;卡死:画面静止且帧率骤降;加载超时:loading_icon 持续出现超过 10 秒。
# 简化的异常状态机 MISS_LIMIT = 120 # 连续 120 帧看不到预期元素,判定异常 LOADING_LIMIT = 600 # loading 图标持续 600 帧,判定加载超时 state = "UNKNOWN" miss_count = 0 loading_count = 0 for result in frame_stream: classes = {int(c) for c in result.boxes.cls.tolist()} # 加载状态跟踪 if "loading_icon" in classes: loading_count += 1 if loading_count > LOADING_LIMIT: report("加载超时") loading_count = 0 else: loading_count = max(0, loading_count - 2) # 缓慢衰减,避免抖动误判 # 画面丢失跟踪 if classes: miss_count = 0 else: miss_count += 1 if miss_count > MISS_LIMIT: report("画面无元素,疑似黑屏或卡死") miss_count = 0逻辑说明:loading_count的衰减逻辑是关键,如果直接清零,loading 图标闪烁两次就会漏判。这里用“每次未出现减 2”的慢衰减,对偶发漏检有容忍度。阈值MISS_LIMIT和LOADING_LIMIT不要拍脑袋定,拿一段录屏跑一遍,看正常画面下误报多少帧,再留 1.5 倍余量。异常行为监控的输出会写进性能分析报告,作为质量评估的一部分。
5. 游戏自动化测试的避坑清单:误检、多分辨率与性能分析报告的排查记录
5.1 性能分析报告:延迟、FPS 与置信度分布的统计口径
性能分析报告不是“模型跑得挺快”这种主观感受,我一般按四个指标出数:推理延迟 p50/p95、检测 FPS、置信度分布、误检/漏检率。注意延迟统计一定要在测试机真实负载下测,单独跑模型和边运行游戏边检测是两回事。
import time import statistics latencies = [] for frame in eval_frames: t0 = time.perf_counter() model.predict(frame, imgsz=960, conf=0.3, verbose=False) latencies.append((time.perf_counter() - t0) * 1000) # ms latencies.sort() p50 = statistics.median(latencies) p95 = latencies[int(len(latencies) * 0.95)] mean_fps = 1000 / statistics.mean(latencies) print(f"p50: {p50:.1f} ms, p95: {p95:.1f} ms, mean FPS: {mean_fps:.1f}")逻辑说明:p50 决定整体手感,p95 决定是否会出现间歇性卡顿。游戏测试里 p95 比平均值重要,因为一次 300ms 的检测峰值就会导致点击落到错误位置。置信度分布也要看:如果大量检测框置信度集中在 0.35 到 0.5,说明模型其实在“犹豫”,此时不要盲目调高阈值,而应该回去补训练数据。
| 指标 | 参考区间 | 说明 |
|---|---|---|
| 推理延迟 p50 | < 60ms | 1080p 下 yolov8s 的常见水平 |
| 推理延迟 p95 | < 120ms | 超过则会出现可见操作迟滞 |
| 检测 FPS | 15-20 足够 | 不需要跑满显卡 |
| 置信度分布 | 目标类 > 0.6 | 大量 0.3-0.5 说明特征没学够 |
5.2 动态场景处理:特效帧、镜头抖动与滑窗确认
游戏画面识别和工业视觉最大的区别是画面会“动”。技能爆发瞬间满屏粒子,镜头旋转时 UI 相对静止但背景全变,剧情对话里弹出新窗口,这些动态场景会让单帧检测频繁抖动:上一帧框出来了,下一帧又消失。直接按单帧结果做断言,测试用例会随机失败,最气人的是本地复现不了。
我现在的做法是滑窗确认:不拿单帧下结论,而是看连续 3 到 5 帧里目标出现次数是否过半。比如点“开始游戏”,要求最近 5 帧里至少 3 帧检测到 start_btn,才执行点击。这比单纯调高置信度阈值有效,因为它容忍偶发漏检,又压制了噪声误检。
# 滑窗确认:最近 5 帧里目标出现 >= 3 次才认定稳定 window = [] for result in frame_stream: has_start = any(int(b.cls) == START_BTN_ID for b in result.boxes) window.append(has_start) window = window[-5:] if sum(window) >= 3: trigger_click("start_btn") window.clear()训练侧也能缓解动态场景翻车。给训练图加运动模糊、随机遮挡、轻微色彩偏移,模拟技能特效和镜头抖动。数据增强放在 ultralytics 的augment=True默认参数上即可,但遮挡增强需要单独配,具体加多少要看验证集效果,不要一上来就加很重的增强,容易把模型训“近视”。
5.3 五个真实踩坑:现象、原因与解决方式
第一条,截图黑屏。现象:游戏跑得正常,但自动化脚本截出来的图全黑。原因:普通 GDI 截屏拿不到独显渲染的画面,尤其 DX12、Vulkan 全屏模式下。解决:让游戏跑在无边框窗口模式,截屏改用 Windows 的 Desktop Duplication API;mss 库在多数场景下比 GDI 稳,先试这个。
第二条,剧情对话里误检率飙升。现象:NPC 立绘的背景被频繁识别成按钮。原因:训练数据里“按钮的相似物”不够,模型没见过带人物立绘的画面。解决:把真实游玩录屏里误检的帧单独抽出来当负样本,加入训练集重新微调;同时把置信度阈值从 0.25 提到 0.35。
第三条,多分辨率下点击位置偏移。现象:1080p 下点击正确,2K 下整体偏左上或右下。原因:没有用 YOLO 输出的原图坐标,而是自己按比例缩放,或者把窗口偏移算错了。解决:统一走 letterbox 逆映射机制,窗口偏移用窗口客户区左上角坐标,不要用边框坐标。
第四条,低端测试机延迟爆炸。现象:集显机器上单帧推理超过 200ms,p95 高得没法用。原因:imgsz 开太高或模型太大。解决:模型从 yolov8m 降到 yolov8s,imgsz 从 1280 降到 640,先测 p95 再逐步放宽。游戏测试不是自动驾驶,不需要每帧都“完美”,10 FPS 也能完成大部分 UI 回归。
第五条,第一版类别贪多导致模型学不动。现象:标了十几个类别,mAP50 卡在 0.4。原因:红点、角标这类小目标样本量不够,类别间特征重叠。解决:砍到 5 个高频类别跑通第一个版本,后续按“先验证、再扩类”的节奏加。这条是血泪经验,游戏 UI 元素动辄几十个,一口气全标进去基本都会翻车。
6. 进阶:用录像回放验证检测稳定性,把 YOLOv8 做成可回归的测试基座
模型更新最怕“这个版本没问题,上个版本也没问题,但说不清哪里变了”。我现在所有项目都维护一段真实游玩录屏作为回归集,固定抽帧、固定标注,每次模型更新都在同一段录像上重放,对比漏检率和误检率变化。这个习惯帮我挡住了很多“我改了增强参数结果模型反而变笨”的后悔药场景。
回放验证的做法是:录一段 15 分钟的真实游玩视频,覆盖登录、战斗、结算、设置四个场景,按帧抽出来,用当前模型预标注,再人工修正成 JSONL ground truth。重放脚本逐帧对比:
import cv2 import json from ultralytics import YOLO model = YOLO("best.pt") cap = cv2.VideoCapture("regression_round1.mp4") frame_idx = 0 while cap.isOpened(): ret, frame = cap.read() if not ret: break # 每 10 帧检测一次,模拟测试脚本采样频率 if frame_idx % 10 == 0: result = model.predict(frame, imgsz=960, conf=0.3, verbose=False)[0] preds = [int(b.cls) for b in result.boxes] # 与 GT 对比,统计漏检/误检 frame_idx += 1导出推理模型这一步,我建议训练完成后直接转 ONNX,不仅推理更快,也让检测服务不依赖训练框架:
yolo export model=runs/train/game_ui_v1/weights/best.pt format=onnx imgsz=960 half=True导出后可以用 onnxruntime 加载,CPU 上跑比原生 PyTorch 明显快,测试机没有 NVIDIA 显卡时也不用干瞪眼。如果后续要在 RK3588 这类边缘设备上部署,再走量化流程,常规 PC 测试环境用 ONNX 就够。
我现在拿到新项目的第一件事,不是急着标数据,而是先录 15 分钟真实游玩视频,用当前模型跑一遍,把漏检和误检的帧截出来排优先级,再定第一版类别清单。这个习惯帮我少走了很多弯路。游戏测试里没有银弹,YOLOv8 解决的是“看见”的问题,剩下的“怎么判断、怎么响应”还得靠测试设计本身。希望帮到你。
本文还有配套的精品资源,点击获取