当我在台式电脑上运行此代码时,它运行良好。但是当我在我的笔记本电脑上运行它时,当我将图像抓取的边界框设置为 Windows 计算器的边界框和窗口的屏幕录制并将其自身稍微向上和向左放置时,出现了问题。
import cv2
import numpy as np
from PIL import ImageGrab
import win32gui
def windowGrab(window_title=None):
if window_title:
global hwnd
hwnd = win32gui.FindWindow(None, window_title)
if hwnd:
win32gui.SetForegroundWindow(hwnd)
else:
print("window not found")
windowGrab("Calculator")
while True:
left_x, top_y, right_x, bottom_y = win32gui.GetWindowRect(hwnd)
screen = np.array(ImageGrab.grab( bbox = (left_x, top_y, right_x, bottom_y ) ) )
cv2.imshow('window', screen)
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
最佳答案
以下是我在测试您的代码时遇到的问题:
- 无法正常显示计算器窗口。
win32gui.FindWindow()
没有找到正确的窗口,所以我最终更换了它。由于某种原因,在 Windows 10 上,win32gui.EnumWindows()
为一个计算器应用列出了 2 个窗口:其中一个具有负宽度/高度值。win32gui.GetWindowRect()
返回窗口的不正确位置和尺寸。看来我的分辨率是1280x720。发生这种情况可能是因为 DPI scaling is being used .ImageGrab.grab()
无法使用真实显示器分辨率空间 (1920x1080) 中的坐标和尺寸来截取应用的屏幕截图。
观察:如果目标窗口最小化,此应用程序将无法运行。
源代码:
import cv2
import numpy as np
import sys
import ctypes
import ctypes.wintypes
from ctypes.wintypes import HWND, RECT, DWORD
from ctypes import *
import win32gui
import win32con
from PIL import ImageGrab
# global variables
dwmapi = ctypes.WinDLL("dwmapi")
APP_NAME = ''
win_hwnd = -1
def callback(hwnd, extra):
wnd_name = win32gui.GetWindowText(hwnd)
if (wnd_name == APP_NAME):
rect = win32gui.GetWindowRect(hwnd)
x = rect[0]
y = rect[1]
w = rect[2] - x
h = rect[3] - y
#print("Name: %s" % wnd_name)
#print("\tLocation: (%d, %d)" % (x, y))
#print("\t Size: (%d, %d)" % (w, h))
if (x >= 0 and y >= 0):
global win_hwnd
win_hwnd = hwnd
def windowGrab(window_title=None):
global APP_NAME, win_hwnd
APP_NAME = window_title
if (window_title is None) or (len(window_title) == 0):
print('!!! window_title == None')
sys.exit(-1)
# try to find a window with matching title and valid coordinates
win32gui.EnumWindows(callback, None)
# check if it has focus
if (win_hwnd != win32gui.GetForegroundWindow()):
print('not focused')
win32gui.SetActiveWindow(win_hwnd)
win32gui.SetForegroundWindow(win_hwnd)
# main()
windowGrab("Calculator")
# workaround to allow ImageGrab to capture the whole screen
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
# get monitor resolution
screen_w = ctypes.windll.user32.GetSystemMetrics(0)
screen_h = ctypes.windll.user32.GetSystemMetrics(1)
print('screen_w=', screen_w, 'screen_h=', screen_h)
# loop
while True:
# retrieve size and position of the window
rect = RECT()
DWMWA_EXTENDED_FRAME_BOUNDS = 9
dwmapi.DwmGetWindowAttribute(HWND(win_hwnd), DWORD(DWMWA_EXTENDED_FRAME_BOUNDS), ctypes.byref(rect), ctypes.sizeof(rect))
x = rect.left
y = rect.top
w = rect.right- x
h = rect.bottom - y
print('x=', x, 'y=', y, 'w=', w, 'h=', h)
if (w == 0 or h == 0):
continue
# take a full screenshot of the desktop
full_screen = np.array(ImageGrab.grab( bbox= (0, 0, screen_w, screen_h) ))
if (full_screen is None):
continue
# crop window area from the screenshot
cropped_rgb = full_screen[y : y+h, x : x+w]
# convert from RGB to BGR order so that colors are displayed correctly
cropped_bgr = cv2.cvtColor(cropped_rgb, cv2.COLOR_RGB2BGR)
cv2.imshow('window', cropped_bgr)
key = cv2.waitKey(25)
if (key & 0xFF) == ord('q'):
break
cv2.destroyAllWindows()
关于python - 截取窗口屏幕截图并使用 OpenCV 显示它时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60067002/