You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python自动脚本中Define bbox窗口无限循环问题求助

问题分析与修复:自动挂机脚本的bbox定义窗口无限循环异常

问题根源

  1. 窗口销毁与循环冲突:鼠标点击回调中收集到2个点时直接调用cv2.destroyAllWindows(),但外层while循环仍在执行cv2.imshow("Define bbox", screen),这会重新创建窗口,导致循环无法终止。
  2. 回调退出无效:回调函数内的return仅退出回调本身,无法终止外层的while循环。
  3. 键盘监听器未启动:keyboard.Listener仅被定义但未调用start(),且原回调函数的参数判断逻辑错误(pynput的on_press回调接收的是Key对象,不是字符串)。

修复后的完整代码

import random
import time
import cv2
import numpy as np
import pyautogui
from pynput import mouse, keyboard
from pynput.keyboard import Key

class Rod:
    def __init__(self):
        print('Define bbox')
        self.mouse = mouse.Controller()

    def catch(self, *args):
        time.sleep(0.29)
        self.mouse.press(mouse.Button.left)
        time.sleep(0.1)
        self.mouse.release(mouse.Button.left)
        time.sleep(1)

def stop(key):
    # 修正键盘监听的判断逻辑,支持普通按键和特殊键
    if hasattr(key, 'char') and key.char == 'q' or key == Key.esc:
        cv2.destroyAllWindows()
        exit()

# 启动键盘监听器
listener = keyboard.Listener(on_press=stop)
listener.start()

rod = Rod()

cv2.namedWindow("Define bbox", cv2.WINDOW_NORMAL)
cv2.resizeWindow("Define bbox", 800, 600)
bbox = []

def on_mouse_click(event, x, y, flags, param):
    global bbox
    if event == cv2.EVENT_LBUTTONDOWN:
        bbox.append((x, y))
        # 移除回调内的窗口销毁操作,交给外层循环处理
        if len(bbox) == 2:
            print("Bbox points collected, exiting definition mode")

cv2.setMouseCallback("Define bbox", on_mouse_click)

while True:
    screen = np.array(pyautogui.screenshot())
    screen = cv2.cvtColor(screen, cv2.COLOR_RGB2BGR)
    cv2.imshow("Define bbox", screen)
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break
    elif len(bbox) == 2:
        break

# 循环退出后统一销毁定义窗口
cv2.destroyWindow("Define bbox")

if len(bbox) == 2:
    x1, y1 = bbox[0]
    x2, y2 = bbox[1]
    bbox = {"top": min(y1, y2), "left": min(x1, x2), "width": abs(x2 - x1), "height": abs(y2 - y1)}
    print(f"Bbox defined as: {bbox}")
else:
    print("Error: Bbox not defined")
    exit()

cv2.imshow('programs vision', np.zeros([480, 640, 1]))
cv2.setWindowProperty('programs vision', cv2.WND_PROP_TOPMOST, 1)
cv2.imshow('binary', np.zeros([480, 640, 1]))
cv2.setWindowProperty('binary', cv2.WND_PROP_TOPMOST, 1)

kernel_size = (3, 3)
kernel_el = cv2.getStructuringElement(cv2.MORPH_RECT, kernel_size)

while True:
    screen = np.array(pyautogui.screenshot(region=(bbox["left"], bbox["top"], bbox["width"], bbox["height"])))
    screen = cv2.cvtColor(screen, cv2.COLOR_RGB2BGR)
    cv2.imshow('programs vision', screen)

    binary = np.zeros((screen.shape[:-1]))
    a = screen[:, :, 0] == screen[:, :, 1]
    b = screen[:, :, 1] == screen[:, :, 2]
    mask = np.logical_and(a, b)
    binary[mask] = 1
    binary = cv2.erode(binary, kernel_el, (-1, -1))
    cv2.imshow('binary', binary)

    average = np.average(binary)
    if average == 0:
        rod.catch()

    if cv2.waitKey(25) & 0xFF == ord('q'):
        cv2.destroyAllWindows()
        break

关键修改说明

  1. 调整窗口生命周期:移除回调内的cv2.destroyAllWindows(),改为在while循环正常退出后调用cv2.destroyWindow("Define bbox"),避免窗口被重复创建。
  2. 修复键盘监听器:启动监听器并修正按键判断逻辑,支持普通字母键和特殊按键(如ESC)的退出操作。
  3. 简化回调逻辑:回调仅负责收集坐标点,循环终止逻辑交给外层while循环处理,确保流程清晰可控。

内容的提问来源于stack exchange,提问作者Christian Meyers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:33:24