opencv Python无限窗口循环

vd8tlhqk  于 2023-05-18  发布在  Python
关注(0)|答案(2)|浏览(105)

所以基本上这个脚本是自动农场。但重要的是定义bbox或区域的代码。当你打开脚本时,你可以在一个名为Define bbox的屏幕上点击两个点来定义bbox。之后,脚本的主要功能开始工作。但是当Define bbox窗口打开时,它显示自己正在创建一个无限循环。

脚本

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

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 key == 'q':
        cv2.destroyAllWindows()
        exit()

keyboard.Listener(on_press=stop)

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:
            cv2.destroyAllWindows()
            return
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

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

我把Windows变小了,但这还不够。

rhfm7lfc

rhfm7lfc1#

您将正在运行的屏幕截图显示给自己。当然,它将显示一个独立的图像。这不是不期望的。
如果你想要一张你打开窗口之前的屏幕图片,请在打开窗口之前截图(一次)。

kx7yvsdv

kx7yvsdv2#

一个解决方案是使用win32和Pillow图像抓取库,以便显示您想要的内容的窗口只显示该窗口,尽管您想要显示的窗口不能全屏显示,窗口不应该重叠。因此,代码看起来像这样:

import random
import time
import cv2
import numpy as np
import pyautogui
from pynput import mouse, keyboard
import win32gui
from PIL import ImageGrab

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 key == 'q':
        cv2.destroyAllWindows()
        exit()

keyboard.Listener(on_press=stop)

rod = Rod()

hwnd = win32gui.FindWindow(None, 'Roblox')
win32gui.SetForegroundWindow(hwnd)
dimensions = win32gui.GetWindowRect(hwnd)

cv2.namedWindow("Define bbox", cv2.WINDOW_NORMAL)
cv2.resizeWindow("Define bbox", dimensions[2] - dimensions[0], dimensions[3] - dimensions[1])
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:
            cv2.destroyAllWindows()
            return
cv2.setMouseCallback("Define bbox", on_mouse_click)

while True:
    image = ImageGrab.grab(dimensions)
    screen = np.array(image)
    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

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:
    image = ImageGrab.grab(dimensions)
    screen = np.array(image)
    screen = cv2.cvtColor(screen, cv2.COLOR_RGB2BGR)
    screen = screen[bbox["top"]:bbox["top"]+bbox["height"], bbox["left"]:bbox["left"]+bbox["width"]]
    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

您可以在此论坛中查找代码片段Capturing a window in Python

相关问题