如何提升OpenCV对Chrome恐龙游戏屏幕多目标检测的性能
优化Chrome恐龙游戏自动化的帧率问题
我正在实现Chrome恐龙游戏的自动化,通过裁剪昼夜两种状态下的障碍物(小仙人掌、大仙人掌、翼龙)图像,用OpenCV的matchTemplate遍历目标字典来定位物体。程序核心逻辑:
- 捕获恐龙前方的屏幕区域
- 遍历待检测目标,使用
cv2.matchTemplate进行检测 - 当检测到的物体X坐标处于距离阈值内时,触发恐龙跳跃
当前帧率仅能达到15 FPS,即使游戏初期速度较慢,恐龙也无法在物体进入阈值时立即跳跃,躲避效果不佳。
主脚本代码
def main_script(): # Local variables loop_time = 0.00001 fps_list = [] action_threshold = 280 dodge_objects = { 'big_cacti_day': GameObject(find_img('big_cacti_day.png')), 'big_cacti_night': GameObject(find_img('big_cacti_night.png')), 'bird_day': GameObject(find_img('bird_day.png')), 'bird_night': GameObject(find_img('bird_night.png')), 'small_cacti_day': GameObject(find_img('small_cacti_day.png')), 'small_cacti_night': GameObject(find_img('small_cacti_night.png')), } # Start the game jump(actions) # Game loop with mss.mss() as sct: monitor = {"top": 600, "left": 250, "width": 550, "height": 150} while 1: # FPS print for testing print_fps(fps_list, loop_time) loop_time = time.time() # Update game screen img = numpy.array(sct.grab(monitor)) game_screen = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) for key in dodge_objects: dodge_object = dodge_objects[key] if dodge_object.match(game_screen): dodge_object_left_x = dodge_object.location[0][0] cv2.rectangle(game_screen, dodge_object.location[0], dodge_object.location[1], (0,0,255), 2) # Action if dodge_object_left_x < action_threshold: print(key, 'x:', dodge_object_left_x, 'y:', dodge_object_left_y) jump(actions) # Show recorded region cv2.imshow('screen', game_screen) if cv2.waitKey(1) == ord('q'): break
GameObject类代码
import cv2 class GameObject: location = None def __init__(self, path): img = cv2.imread(path, 0) self.img = img self.width = img.shape[1] self.height = img.shape[0] def match(self, screen): res = cv2.matchTemplate(screen, self.img, cv2.TM_CCOEFF_NORMED) minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res) startLoc = maxLoc endLoc = (startLoc[0] + self.width, startLoc[1] + self.height) if maxVal > 0.8: self.location = (startLoc, endLoc) return True else: self.location = None return False
已尝试的优化措施
- 测试dxcam、win32api、pyautogui、PIL等屏幕捕获库,mss库性能最优
- 通过mss裁剪恐龙前方550x150的感兴趣区域,性能有所提升但仍不足
- 将待检测物体的图像裁剪至最小尺寸
性能分析显示,Python循环和cv2.matchTemplate是主要瓶颈——注释循环部分后帧率可达约27 FPS,mss._grab_impl和matchTemplate函数占用了大部分运行时间,现寻求更多可实施的代码性能优化技巧。
优化建议
1. 合并昼夜模板,减少检测次数
恐龙游戏的昼夜切换是全局色调反转,无需分开检测昼夜模板:
- 提前将夜间模板做灰度反转,与白天模板共用检测逻辑
- 或通过屏幕平均亮度判断当前昼夜状态,仅检测对应状态的3个模板,直接减少一半
matchTemplate调用次数
2. 优化matchTemplate的计算效率
- 更换更快的匹配算法:
cv2.TM_SQDIFF_NORMED或cv2.TM_CCORR_NORMED的计算速度优于TM_CCOEFF_NORMED,可测试精度是否满足需求 - 对模板和屏幕帧做降采样(比如缩小至原尺寸的50%),匹配后再还原坐标,大幅减少计算量
- 提前预计算模板的归一化参数,避免每次匹配重复计算
3. 降低Python循环开销
- 将
dodge_objects从字典改为列表,遍历列表的速度比字典更快 - 提前缓存所有模板的尺寸等属性,避免在循环中重复读取
- 把匹配逻辑中的固定计算(如
startLoc[0] + self.width)移至__init__方法中完成
4. 优化屏幕捕获与处理
- 让mss直接返回灰度图:使用
format="gray"参数,省去cv2.cvtColor的转换耗时 - 进一步缩小捕获区域:如果恐龙前方的有效预警区域可压缩至更小范围(比如前300px宽度),减少处理的像素量
- 移除调试开销:注释
print_fps、print调试输出,关闭不必要的cv2.imshow预览,IO操作会显著拖慢帧率
5. 批量处理模板
将同状态的模板合并为一个大数组,利用OpenCV的批量匹配能力(部分版本支持),一次调用检测多个模板,减少Python与C层的交互开销
6. 多线程重叠耗时操作
将屏幕捕获与模板检测放在不同线程:mss捕获当前帧的同时,处理上一帧的模板检测,重叠耗时操作,提升整体帧率(注意cv2.imshow需放在主线程避免冲突)
内容的提问来源于stack exchange,提问作者yakubszatkowski
相关产品推荐
相关产品推荐

