从YOLOv3到YOLOv5s6:我的《明日之后》自动采集脚本升级实录
三年前用YOLOv3写的《明日之后》自动采集脚本,最近打开GitHub发现居然还有人在提issue。看了眼游戏官网——好家伙,这游戏居然还活着!趁着周末把代码翻出来重跑了一遍,结果在RTX 3060上帧率还不到20fps。这性能放在2023年实在说不过去,于是决定用YOLOv5s6彻底重构这个项目。
1. 为什么要从YOLOv3升级到YOLOv5s6
去年帮朋友部署一个工业质检系统时第一次接触YOLOv5,当时就被它的易用性震惊了。相比YOLOv3需要手动编译Darknet的折腾,YOLOv5开箱即用的体验简直像从DOS时代跳到了macOS。
性能对比实测数据:
| 指标 | YOLOv3-608 | YOLOv5s6-1280 | 提升幅度 |
|---|---|---|---|
| mAP@0.5 | 52.3% | 63.7% | +21.8% |
| 推理延迟(ms) | 48.2 | 23.5 | -51.2% |
| 内存占用(MB) | 1872 | 896 | -52.1% |
更惊喜的是模型兼容性。原本担心要重新标注数据集,结果发现YOLOv5完全兼容v3的标注格式(中心点+宽高归一化坐标),我的旧数据集直接就能用。PyTorch生态也比Darknet友好太多,想加个TensorBoard监控训练进度?pip install tensorboard就搞定了。
实际测试发现YOLOv5s6在1280x720分辨率下的检测精度,比YOLOv3在608x608下还高出11.4个百分点
2. 训练环境搭建与数据准备
我的开发环境配置:
- GPU: RTX 3060 12GB
- CUDA: 11.7
- PyTorch: 1.13.1
# 创建conda环境 conda create -n yolo5 python=3.8 conda activate yolo5 # 安装依赖 pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 --extra-index-url https://download.pytorch.org/whl/cu117 pip install opencv-python matplotlib pandas seaborn tqdm pyyaml数据集结构保持与v3时代一致:
datasets/ └──明日之后/ ├── images/ # 存放所有游戏截图 │ ├── scene1.png │ └── scene2.png └── labels/ # 对应标注文件 ├── scene1.txt └── scene2.txt标注文件示例(class_id center_x center_y width height):
0 0.512 0.723 0.124 0.156 3 0.112 0.456 0.078 0.3423. 模型训练实战记录
3.1 配置文件详解
创建data/game.yaml配置文件:
# 数据集路径配置 path: ../datasets/明日之后 train: images # 训练集路径(相对path) val: images # 验证集路径 test: # 测试集路径(可选) # 类别定义 nc: 11 # 类别数量 names: ['树', '石头', '草药', '狼', '僵尸', '鹿', '熊', '直升机', '浆果', '蘑菇', '煤']3.2 启动训练的关键参数
python train.py --img 1280 \ --batch 16 \ --epochs 100 \ --data data/game.yaml \ --weights yolov5s6.pt \ --device 0 \ --optimizer AdamW \ --cache ram遇到的坑与解决方案:
- CUDA内存不足:将batch size从32降到16,启用
--cache ram将数据集预加载到内存 - 过拟合问题:添加
--rect参数启用矩形训练,减少图像填充带来的噪声 - 类别不平衡:使用
--cls 0.5增加分类损失权重
3.3 训练过程监控
YOLOv5内置的TensorBoard日志太香了,实时查看各项指标:
tensorboard --logdir runs/train重点关注三个指标曲线:
- metrics/mAP_0.5- 置信度阈值0.5时的平均精度
- metrics/precision- 识别结果的精确率
- val/obj_loss- 验证集的目标检测损失
4. 部署优化与性能调优
4.1 模型导出为ONNX格式
import torch model = torch.hub.load('ultralytics/yolov5', 'custom', 'best.pt') model.eval() torch.onnx.export(model, torch.randn(1, 3, 1280, 1280), "game_model.onnx")4.2 OpenCV加速推理方案
import cv2 net = cv2.dnn.readNetFromONNX("game_model.onnx") blob = cv2.dnn.blobFromImage(img, 1/255.0, (1280,1280), swapRB=True) net.setInput(blob) outs = net.forward()性能对比:
| 推理方式 | 帧率(fps) | GPU占用 |
|---|---|---|
| PyTorch原生 | 42 | 78% |
| ONNX+OpenCV | 53 | 65% |
| TensorRT加速 | 68 | 52% |
4.3 游戏窗口实时捕获方案
import mss import win32gui def capture_game_window(): hwnd = win32gui.FindWindow(None, "明日之后") left, top, right, bottom = win32gui.GetWindowRect(hwnd) with mss.mss() as sct: monitor = {"left": left, "top": top, "width": right-left, "height": bottom-top} img = np.array(sct.grab(monitor)) return img[:,:,:3] # 去除alpha通道5. 完整代码实现
核心检测类封装:
class GameDetector: def __init__(self, model_path): self.model = torch.hub.load('ultralytics/yolov5', 'custom', path=model_path) self.model.conf = 0.6 # 置信度阈值 self.model.iou = 0.45 # NMS阈值 def detect(self, img): results = self.model(img, size=1280) return results.pandas().xyxy[0] # 返回DataFrame格式结果 def filter_targets(self, results, target_types): targets = [] for _, row in results.iterrows(): if row['name'] in target_types and row['confidence'] > self.model.conf: targets.append({ 'type': row['name'], 'x1': int(row['xmin']), 'y1': int(row['ymin']), 'x2': int(row['xmax']), 'y2': int(row['ymax']) }) return targets主循环控制逻辑:
def main(): detector = GameDetector("best.pt") while True: start_time = time.time() # 捕获游戏画面 img = capture_game_window() # 执行目标检测 results = detector.detect(img) trees = detector.filter_targets(results, ['树', '石头']) # 显示检测结果 show_detection(img, trees) # 计算帧率 fps = 1 / (time.time() - start_time) print(f"当前帧率: {fps:.2f}")6. 效果对比与优化建议
升级前后的关键指标对比:
采集效率测试(10分钟):
| 版本 | 采集次数 | 误采率 | 平均帧率 |
|---|---|---|---|
| YOLOv3 | 87 | 12.6% | 18.2fps |
| YOLOv5s6 | 142 | 5.3% | 47.5fps |
几个实用优化技巧:
- 启用
--half参数使用FP16精度,推理速度提升20%+ - 对于固定场景,使用
--rect矩形推理减少图像变形 - 调整
--conf-thres和--iou-thres平衡精度与速度
在Mumu模拟器上最终实现了稳定50fps的检测速度,比旧版本快近3倍。最让我意外的是YOLOv5s6的功耗控制——GPU温度始终保持在65℃以下,风扇噪音比v3时代小多了。