Python自动脚本中Define bbox窗口无限循环问题求助
问题分析与修复:自动挂机脚本的bbox定义窗口无限循环异常
问题根源
- 窗口销毁与循环冲突:鼠标点击回调中收集到2个点时直接调用
cv2.destroyAllWindows(),但外层while循环仍在执行cv2.imshow("Define bbox", screen),这会重新创建窗口,导致循环无法终止。 - 回调退出无效:回调函数内的
return仅退出回调本身,无法终止外层的while循环。 - 键盘监听器未启动:
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
关键修改说明
- 调整窗口生命周期:移除回调内的
cv2.destroyAllWindows(),改为在while循环正常退出后调用cv2.destroyWindow("Define bbox"),避免窗口被重复创建。 - 修复键盘监听器:启动监听器并修正按键判断逻辑,支持普通字母键和特殊按键(如ESC)的退出操作。
- 简化回调逻辑:回调仅负责收集坐标点,循环终止逻辑交给外层while循环处理,确保流程清晰可控。
内容的提问来源于stack exchange,提问作者Christian Meyers
相关产品推荐
相关产品推荐

