Python高级图像识别(AIR)机器人3D场景瞄准失效问题修复
问题描述
- 基于Python开发的颜色识别自动瞄准机器人,最初为aimbooster.com等2D网页场景设计,核心逻辑为识别屏幕上指定的目标颜色后,自动移动鼠标到对应位置点击射击。
- 迁移到3D打靶射击场景后出现故障:机器人可正常检测到屏幕上的目标颜色、触发射击逻辑,但不会移动鼠标到识别到的目标坐标,仅会向当前视角朝向的位置射击。
- 原实现代码如下:
import pyautogui import time import keyboard import random import win32api, win32con time.sleep(2) def click(x,y): win32api.SetCursorPos((x,y)) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0) #Color Of Center: (247, 10, 0) while keyboard.is_pressed("q") == False: pic = pyautogui.screenshot(region=(660,350,600,400)) width, height = pic.size for x in range(0,width,5): for y in range(0,height,5): r,g,b= pic.getpixel((x,y)) if b == 195: click(x+247,y+10) time.sleep(0.10) break
故障根因
- 坐标偏移计算错误:
pyautogui.screenshot的region参数格式为(截图区域左上角x坐标, 截图区域左上角y坐标, 区域宽度, 区域高度),截图返回的像素x、y是相对于截图区域左上角的相对坐标,转屏幕绝对坐标时需要加上截图区域的左上角x、y值。原代码错误使用247、10作为偏移量,计算出的目标坐标和实际位置完全不匹配。 - 输入逻辑不兼容3D场景:2D网页游戏读取系统鼠标的绝对光标位置,原代码用
win32api.SetCursorPos设置绝对坐标可正常触发移动,但绝大多数3D射击游戏会锁定鼠标在屏幕中心,仅读取鼠标的相对移动增量,直接设置绝对光标位置会被游戏输入层拦截,表现为鼠标不移动、仅朝当前准星方向射击。 - 颜色判断逻辑错误:代码注释标注目标颜色为
(247, 10, 0)(对应R=247、G=10、B=0),但实际判断逻辑仅检测蓝色通道值等于195,和目标色完全不匹配,极易出现误触发。 - 循环逻辑存在漏洞:找到目标触发点击后,
break仅能跳出内层y轴遍历循环,外层x轴循环会继续遍历剩余像素,拖慢检测帧率,还可能导致重复触发点击。
修复方案
- 修正坐标转换逻辑:严格按照截图区域的起始坐标计算目标点的屏幕绝对位置,替换错误的偏移值。
- 替换鼠标输入方式:放弃绝对光标位置设置,改为计算目标点和屏幕中心(3D游戏准星常驻位置)的坐标差,用相对移动的方式控制鼠标,适配3D游戏的输入规则。
- 修正颜色判断逻辑:同时校验R、G、B三个通道的值,加入适当容差适配画面抗锯齿带来的颜色偏差,降低误识别率。
- 修复循环跳出逻辑:找到目标完成射击后,直接跳出两层像素遍历循环,进入下一轮截图检测,提升运行帧率。
修复后参考代码
import pyautogui import time import keyboard import random import win32api, win32con time.sleep(2) # 配置参数 SCREENSHOT_REGION = (660, 350, 600, 400) REGION_OFFSET_X, REGION_OFFSET_Y, REGION_W, REGION_H = SCREENSHOT_REGION CENTER_X = REGION_OFFSET_X + REGION_W // 2 CENTER_Y = REGION_OFFSET_Y + REGION_H // 2 TARGET_R, TARGET_G, TARGET_B = (247, 10, 0) COLOR_TOLERANCE = 15 # 颜色识别容差,可根据实际画面调整 CLICK_COOLDOWN = 0.1 def mouse_rel_move(dx, dy): # 发送鼠标相对移动信号,适配3D游戏输入 win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, dx, dy, 0, 0) def mouse_click(): win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0) time.sleep(random.uniform(0.01, 0.04)) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0) while not keyboard.is_pressed("q"): pic = pyautogui.screenshot(region=SCREENSHOT_REGION) width, height = pic.size target_found = False for x in range(0, width, 5): if target_found: break for y in range(0, height, 5): r, g, b = pic.getpixel((x, y)) # 三通道联合判断,带容差 if (abs(r - TARGET_R) <= COLOR_TOLERANCE and abs(g - TARGET_G) <= COLOR_TOLERANCE and abs(b - TARGET_B) <= COLOR_TOLERANCE): # 转换为屏幕绝对坐标 target_screen_x = REGION_OFFSET_X + x target_screen_y = REGION_OFFSET_Y + y # 计算准星需要移动的相对偏移 delta_x = target_screen_x - CENTER_X delta_y = target_screen_y - CENTER_Y # 移动准星到目标位置 mouse_rel_move(delta_x, delta_y) time.sleep(0.01) mouse_click() time.sleep(CLICK_COOLDOWN) target_found = True break
注意:如果游戏开启全屏独占模式,pyautogui无法正常捕获游戏画面,需要将游戏调整为无边框窗口或普通窗口模式运行。带内核级反作弊的游戏会拦截这类用户态模拟输入操作,使用前请确认对应游戏的规则,避免账号受到处罚。
内容的提问来源于stack exchange,提问作者Synth
相关产品推荐
相关产品推荐

