如何在有快速移动投射物的屏幕上识别手游骰子棋盘信息?
手游棋盘骰子识别优化方案
一、解决检测速度慢的问题
pyautogui的模板匹配效率极低,尤其是多模板场景,以下是针对性优化:
- 锁定ROI区域,避免全图搜索:提前计算棋盘上5×3个骰子的精确坐标(比如每个骰子格子是80×80像素),直接裁剪每个格子的ROI,而非在整屏搜索所有模板。
- 替换为OpenCV高效匹配:放弃pyautogui的
locateOnScreen,改用OpenCV的cv2.matchTemplate,提前将所有模板和ROI转为灰度图,选择更快的匹配算法(如cv2.TM_SQDIFF_NORMED)。 - 预处理模板批量缓存:将5种类型×7等级的所有模板,提前resize到与骰子格子一致的尺寸并转灰度,存储为列表,避免每次匹配时重复处理。
- 并行处理多格子:15个骰子格子的匹配是独立任务,用
concurrent.futures.ThreadPoolExecutor并行处理,可将速度提升3-5倍。
示例代码片段:
import cv2 import numpy as np from concurrent.futures import ThreadPoolExecutor # 提前加载并预处理模板(假设模板路径为templates/typeX_levelY.png) templates = {} for dice_type in range(1,6): for level in range(1,8): path = f"templates/type{dice_type}_level{level}.png" template = cv2.imread(path, cv2.IMREAD_GRAYSCALE) templates[(dice_type, level)] = cv2.resize(template, (80,80)) # 假设骰子格子80×80 # 定义单个格子的匹配函数 def match_dice(roi_gray): best_score = float('inf') best_match = None for (dtype, lvl), temp in templates.items(): res = cv2.matchTemplate(roi_gray, temp, cv2.TM_SQDIFF_NORMED) min_val = np.min(res) if min_val < best_score: best_score = min_val best_match = (dtype, lvl) return best_match if best_score < 0.1 else None # 置信度阈值设为0.1 # 裁剪所有ROI并并行匹配 def recognize_board(screen_gray): roi_coords = [(x*80, y*80, 80,80) for y in range(3) for x in range(5)] # 5×3格子 rois = [screen_gray[y:y+h, x:x+w] for x,y,w,h in roi_coords] with ThreadPoolExecutor(max_workers=5) as executor: results = list(executor.map(match_dice, rois)) # 整理为5×3数组 return np.array(results).reshape(3,5).T
二、解决投射物干扰的问题
1. 帧平均法(可行且易实现)
连续捕获20-30帧快速截图(用mss替代pyautogui的screenshot,速度快10倍以上),对所有帧的对应像素取平均值,动态的投射物会因位置变化被模糊消除,留下清晰的静态骰子。
示例代码片段:
import mss import numpy as np import cv2 def get_avg_frame(num_frames=20): with mss.mss() as sct: monitor = sct.monitors[1] # 主显示器 frames = [] for _ in range(num_frames): frame = np.array(sct.grab(monitor)) frames.append(cv2.cvtColor(frame, cv2.COLOR_BGRA2GRAY)) # 取平均并转为uint8格式 avg_frame = np.mean(frames, axis=0).astype(np.uint8) return avg_frame
注意:需确保捕获帧的间隔足够短(mss的截图间隔约1ms),避免骰子本身位置变化。
2. 特征聚焦识别
放弃整骰子模板,聚焦骰子的核心特征:
- 颜色分割:5种类型的骰子主色调不同,用HSV颜色空间分割出每个骰子的区域,过滤掉投射物的异色区域。
- 等级数字单独匹配:只截取骰子上等级数字的小区域(比如骰子顶部10×20的区域),用数字模板匹配或轻量OCR(如Tesseract训练小数字模型)识别等级,避免投射物干扰。
3. 多模板鲁棒匹配
针对每个等级的骰子,收集3-5张带有不同投射物干扰的模板,匹配时取所有模板的最高置信度结果,无需降低置信度即可避免等级混淆。
三、可选技术栈优化
如果Python的性能仍不满足需求:
- 改用C++结合OpenCV,速度比Python快5-10倍。
- 训练轻量CNN模型(如MobileNetV2、TensorFlow Lite模型),将每个骰子ROI输入模型直接输出类型和等级,抗干扰能力强,推理速度可达每秒数百帧。训练数据可自行截图生成,加入投射物干扰的样本并做数据增强(旋转、模糊、亮度调整)。
内容的提问来源于stack exchange,提问作者Loïc Pottier
相关产品推荐
相关产品推荐

