摘要

在前几篇文章中,项目已经完成了 TFT 阵容顾问的资源构建、英雄识别、装备识别和截图路由层。旧方案主要依赖 tft_screen_capture.py,通过 OpenCV 完成六边形边框检测、HSV 直方图粗筛、灰度 NCC 模板匹配等流程。

这套方案的优点是实现清晰、依赖轻、CPU 即可运行,但随着识别场景变复杂,它的上限也逐渐暴露出来:截图来源不统一、边框颜色变化、英雄头像缩放、UI 遮挡、无框截图等情况都会影响识别稳定性。

因此,本阶段项目开始引入新的识别引擎:tft_yolo_clip.py。它采用 YOLO + CLIP 的双阶段思路,将原来“靠规则找位置、靠模板猜身份”的流程,升级为“YOLO 负责定位,CLIP 负责识别”。


一、旧方案已经解决了什么

旧版本截图识别链路主要集中在 tft_screen_capture.py 中。

整体流程可以概括为:

截图
  ↓
判断截图类型
  ↓
检测英雄候选框
  ↓
裁剪英雄头像区域
  ↓
HSV 直方图粗筛
  ↓
灰度 NCC 精匹配
  ↓
输出英雄、星级、装备、站位

这个方案不是简单的模板匹配,而是经过多轮工程优化的结果。

例如:

  1. 模板图片不是手动维护,而是由 tft_fetch_assets.py 从赛季数据库中构建。
  2. 英雄 PNG 的透明区域会合成到中性灰背景,避免透明像素变成黑色影响匹配。
  3. 英雄识别不是全库暴力匹配,而是先用 HSV 直方图筛出候选,再用零均值 NCC 精筛。
  4. 棋盘图、横排结算图、全局阵容表、战绩回顾图会先通过 detect_screenshot_mode() 分流。

所以旧方案的价值在于:它把截图识别从“能跑”推进到了“有工程结构”。


二、为什么仍然需要切换到 YOLO

OpenCV 方案的核心假设是:截图中存在可解释的视觉规律。

例如棋盘模式里,英雄通常位于带颜色边框的六边形格子中,所以可以通过 HSV 范围检测青色、紫色、金色、蓝色边框。

但真实截图并不总是这么理想。

当截图来自不同分辨率、不同客户端、不同页面,甚至头像区域没有明显边框时,旧方案就会遇到几个问题:

问题 OpenCV 方案的表现
边框颜色变化 HSV 阈值需要重新调
头像缩放不同 模板匹配分数下降
UI 图标干扰 需要继续补过滤规则
无明显六边形边框 候选框可能检测不到
新赛季英雄变化 模板库和阈值都要维护

也就是说,旧方案的问题不是某一行代码写得不好,而是方法本身依赖太多人工规则。

当规则越来越多时,系统会从“可解释”慢慢变成“难维护”。

这就是引入 YOLO 的原因。


三、迁移的核心思路:先拆开“定位”和“识别”

旧方案中,“找到英雄在哪里”和“判断英雄是谁”是强绑定的。

例如:

检测六边形边框 → 裁剪头像 → 模板匹配

如果第一步边框检测失败,后面的英雄识别也就没有机会执行。

新方案把问题拆成两个阶段:

截图
  ↓
YOLO 检测英雄位置
  ↓
裁剪英雄区域
  ↓
CLIP 判断英雄身份
  ↓
输出结构化结果

这里最重要的变化是:

YOLO 不需要知道边框是什么颜色,它只需要学习“英雄头像区域长什么样”。

而 CLIP 不依赖本地模板图片逐像素相似,它通过图像和文本之间的语义相似度来判断候选英雄。

这让整个识别链路从“像素规则”开始转向“目标检测 + 语义识别”。


四、当前新增的 YOLO+CLIP 模块

本阶段新增的核心文件是:tft_yolo_clip.py

它的定位是一个新的截图识别引擎,而不是直接删除旧的 OpenCV 方案。

原因很实际:旧方案已经支持装备识别、截图路由、Web 上传入口等功能,直接替换风险较高。因此当前更合理的做法是并行引入新引擎,先验证 YOLO 的检测能力,再逐步接入主流程。

当前模块中的关键配置包括:

YOLO_MODEL_PATH = Path("./tft_yolo_models/tft_champion_det.pt")
CLIP_MODEL_NAME = "ViT-B/32"

DETECT_CONF = 0.25
IOU_THRESHOLD = 0.45
CLIP_THRESHOLD = 0.50

其中:

  • DETECT_CONF 控制 YOLO 检测框的置信度;
  • IOU_THRESHOLD 用于去除重复框;
  • CLIP_THRESHOLD 控制英雄语义识别的最低相似度;
  • tft_yolo_models/ 用来存放后续训练得到的检测模型。

五、YOLO 在这里主要解决“英雄在哪里”

新模块中的 detect_heroes_yolo() 负责检测英雄候选框。

它不再扫描 HSV 边框,也不再依赖六边形轮廓,而是让 YOLO 直接输出 bounding box。

这一步的意义很大:

旧方案识别的是“边框”,再推断里面有英雄;新方案识别的是“英雄区域”本身。

这会让识别更适合处理以下场景:

  1. 无边框或弱边框截图;
  2. 英雄头像尺寸变化;
  3. 棋盘、结算、回顾等不同截图版式;
  4. UI 颜色变化;
  5. 后续接入真实游戏截图。

当然,当前如果只使用预训练 yolov8n.pt,检测效果不会理想,因为通用 YOLO 没有专门学过 TFT 英雄头像。因此后续仍需要准备截图数据并训练专用模型。


六、CLIP 在这里主要解决“这个英雄是谁”

YOLO 检测到框以后,系统会裁剪每个英雄区域,然后交给 CLIP 做分类。

项目中不是只给 CLIP 一个英雄名字,而是为每个英雄构造多种文本提示:

a photo of Draven champion from Teamfight Tactics
the League of Legends character Draven
Draven from TFT game
hero portrait of Draven

这种设计比单纯写一个 "Draven" 更稳,因为 CLIP 比较的是图像和文本描述之间的语义相似度,多提示模板可以提高匹配鲁棒性。

同时,英雄列表会优先从 tft_champion_db.json 中读取,而不是完全写死。这一点延续了前面项目的数据驱动思路:赛季数据更新以后,识别候选集合也可以跟着更新。


七、这次迁移不是推翻旧方案,而是重新划分职责

我觉得这次升级最关键的技术理解不是“YOLO 比 OpenCV 高级”,而是识别系统的职责重新划分了。

旧方案更像是:OpenCV 同时负责定位、过滤、识别、部分后处理

新方案开始变成:

YOLO:负责目标定位
CLIP:负责身份识别
OpenCV:继续负责星级、装备等局部规则
Converter:负责羁绊与阵容摘要
RAG Agent:负责策略分析

这样做的好处是,每个模块的边界更清楚。

例如星级检测依然适合用 OpenCV,因为星星颜色和位置比较固定;装备识别后续可以继续模板匹配,也可以训练单独的装备检测模型;英雄位置检测则更适合交给 YOLO。

这不是把传统视觉方法全部丢掉,而是把它们放到更合适的位置上。


八、当前阶段的技术进度

目前项目已经完成了 YOLO+CLIP 引擎的基础骨架:

  1. 新增 tft_yolo_clip.py;
  2. 支持 YOLO 检测英雄框;
  3. 支持 CLIP 对裁剪头像做零样本识别;
  4. 支持 yolo_clip、yolo_only、clip_only 三种模式;
  5. 保留星级检测逻辑;
  6. 预留装备识别扩展入口;
  7. 提供训练配置生成与命令行入口。

运行方式示例:

python tft_yolo_clip.py screenshot.png --mode yolo_clip --debug

如果只想看 YOLO 框检测结果,可以使用:

python tft_yolo_clip.py screenshot.png --detect-only

九、总结

从 OpenCV 模板匹配迁移到 YOLO,并不是简单换一个库,也不是把代码改成深度学习版本。

这次变化的核心是:项目对截图识别问题的理解变了。

旧方案证明了整条链路可以跑通:资源构建、模板加载、英雄识别、装备识别、截图分流、阵容分析都已经形成闭环。

新方案则开始解决旧方案的上限问题:减少手工视觉规则,提高对复杂截图的适应能力,并为后续真实游戏截图识别打基础。

当前项目正处在一个比较关键的阶段:OpenCV 方案仍然是稳定 fallback,YOLO+CLIP 则是下一代识别引擎的雏形。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐