YOLOv8 CS自走AI Bot准星偏移求助:检测敌人后持续向下瞄准
问题排查与解决建议
核心问题定位
你遇到的持续向下瞄准问题,本质是坐标映射错误或窗口/画面与系统坐标不匹配导致的,以下是具体排查和修复方向:
1. 窗口尺寸与系统屏幕尺寸混淆
你当前用系统全屏尺寸计算目标坐标,但如果游戏窗口不是全屏,WindowCapture获取的画面仅为游戏窗口内区域,直接用系统宽高会导致Y轴坐标被错误放大,鼠标自然会向下偏移。
- 修复:改用游戏窗口的实际尺寸计算坐标:
之后将目标坐标计算改为:hwnd = win32gui.FindWindow(None, 'Counter-Strike: Global Offensive - Direct3D 9') rect = win32gui.GetWindowRect(hwnd) window_width = rect[2] - rect[0] window_height = rect[3] - rect[1] window_x, window_y = rect[0], rect[1] # 窗口左上角的屏幕坐标target_x = int(window_x + window_width * box_center_x / W) target_y = int(window_y + window_height * box_center_y / H)
2. pydirectinput的坐标适配问题
pydirectinput.moveTo()默认使用绝对坐标,但Windows的显示缩放(比如125%/150%)会导致坐标映射偏差,直接调用会让鼠标定位错误。
- 修复:
- 先关闭系统显示缩放:右键桌面→显示设置→缩放与布局→设为100%。
- 或改用相对移动模式,计算鼠标偏移量而非直接定位:
current_x, current_y = win32api.GetCursorPos() delta_x = target_x - current_x delta_y = target_y - current_y # 限制单次移动幅度,避免跳帧 delta_x = max(-50, min(50, delta_x)) delta_y = max(-50, min(50, delta_y)) pydirectinput.move(delta_x, delta_y, relative=True)
3. 目标中心点选择错误
你当前取检测框的垂直中心,但CS中需要瞄准敌人头部,而非身体中心,这会导致默认瞄准胸口下方,看起来像是持续向下飘。
- 修复:将目标Y坐标改为检测框的上半区域,模拟头部位置:
# 取检测框上1/2或1/3处作为瞄准点 box_center_y = y1 + (y2 - y1) * 0.2
4. 窗口捕获画面的翻转/拉伸问题
如果wincap.get_screenshot()返回的画面存在垂直翻转,计算出的Y坐标会完全反向,导致鼠标持续向下移动。
- 修复:在获取帧后验证画面方向,必要时翻转修正:
若翻转后检测框位置正确,就需要在计算坐标前固定翻转画面,或者反向计算Y坐标。frame = cv2.flip(frame, 0) # 尝试垂直翻转,观察检测框是否与游戏画面匹配
5. 高帧率下的鼠标重复定位
循环中每次检测到目标就调用moveTo,帧率过高时鼠标会被频繁重置,当目标轻微移动时,视觉上呈现持续向下飘的效果。
- 修复:添加位置变化阈值,仅当目标偏移超过一定范围时才移动鼠标:
last_target = None # 循环内... if score > threshold: # 计算target_x, target_y后... if last_target is None or abs(target_x - last_target[0]) > 3 or abs(target_y - last_target[1]) > 3: pydirectinput.moveTo(target_x, target_y) last_target = (target_x, target_y)
整合修复后的代码示例
import os import time from ultralytics import YOLO import cv2 import numpy as np from windowcap import WindowCapture import win32gui, win32ui, win32con, win32api import pydirectinput wincap = WindowCapture('Counter-Strike: Global Offensive - Direct3D 9') model_path = os.path.join('.','runs','detect','train10','weights','last.pt') model = YOLO(model_path) hwnd = win32gui.FindWindow(None, 'Counter-Strike: Global Offensive - Direct3D 9') last_target = None while True: frame = wincap.get_screenshot() if frame is None: continue H, W, _ = frame.shape threshold = 0.5 # 获取游戏窗口实际尺寸与位置 rect = win32gui.GetWindowRect(hwnd) window_width = rect[2] - rect[0] window_height = rect[3] - rect[1] window_x, window_y = rect[0], rect[1] results = model(frame)[0] for result in results.boxes.data.tolist(): x1, y1, x2, y2, score, class_id = result if score > threshold: cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 4) cv2.putText(frame, results.names[int(class_id)].upper(), (int(x1), int(y1 - 10)), cv2.FONT_HERSHEY_SIMPLEX, 1.3, (0, 255, 0), 3, cv2.LINE_AA) # 瞄准敌人头部区域(检测框上1/5位置) box_center_x = (x1 + x2) / 2 box_center_y = y1 + (y2 - y1) * 0.2 # 转换为屏幕绝对坐标 target_x = int(window_x + window_width * box_center_x / W) target_y = int(window_y + window_height * box_center_y / H) # 仅当位置变化超过阈值时移动鼠标 if last_target is None or abs(target_x - last_target[0]) > 3 or abs(target_y - last_target[1]) > 3: pydirectinput.moveTo(target_x, target_y) last_target = (target_x, target_y) cv2.imshow("COMPUTER VISION",frame) if cv2.waitKey(1) == ord('q'): cv2.destroyAllWindows() break
内容的提问来源于stack exchange,提问作者BigHeroSus
相关产品推荐
相关产品推荐

