PyWin32 无法捕获某些窗口,导致黑屏(Python、Windows)

问题描述 投票:0回答:3

〜相同的问题这里,但遗憾的是没有有用的答案。

我使用 PlayStation Remote Play 将实时视频从 PS5 传输到我的电脑。该流正在我的计算机上名为“PS Remote Play”的窗口中显示。我想从此窗口读取帧以在

opencv
中进行最终处理。

使用库

mss
pygetwindow
,我能够正确捕获此窗口:

import cv2
import mss
import pygetwindow as gw
import numpy as np


def fetch_window_image(window_name):
    #
    window = gw.getWindowsWithTitle(window_name)[0]
    window_rect = {'left': window.left + 10, 'top': window.top + 45,
                   'width': window.width - 20, 'height': window.height - 60}
    with mss.mss() as sct:
        screenshot = sct.grab(window_rect)
        img = np.array(screenshot)
    img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
    return img


def main():
    WINDOW_NAME = 'PS Remote Play'
    cv2.namedWindow('Computer Vision', cv2.WINDOW_NORMAL)
    while cv2.waitKey(1) != ord('q'):
        img = fetch_window_image(WINDOW_NAME)
        cv2.imshow('Computer Vision', img)


if __name__ == '__main__':
    main()

问题在于,当窗口被其他窗口遮挡(同时保持活动状态)时,此方法无法捕获它。能够捕获隐藏的窗口对于我的用例来说至关重要。

我遇到了以下代码,它能够捕获隐藏的窗口():

import win32gui
import win32ui
import win32con

w = 1920
h = 1080

hwnd = win32gui.FindWindow(None, 'PS Remote Play')
wDC = win32gui.GetWindowDC(hwnd)
dcObj = win32ui.CreateDCFromHandle(wDC)
cDC = dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (w, h), dcObj, (0, 0), win32con.SRCCOPY)
dataBitMap.SaveBitmapFile(cDC, 'saved.bmp')

# Free Resources
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())

不幸的是,在 PS Remote Play 窗口上使用时,它显示黑屏。我在其他一些窗口上尝试过,结果好坏参半。它能够捕获 Spotify、Paint 和 VSCode 编辑器。它返回 PS Remote Play、Microsoft To Do、Whiteboard 和 Calendar 的空白屏幕。无论可见与否,这些行为都保持不变。

为什么会发生这种情况?我们如何才能持续捕获隐藏的窗口?

python windows window screen-capture
3个回答
1
投票

很多游戏都有多种窗口模式,其中一些在未聚焦时会黑屏以节省图形。我不确定 PS Remote Play 中是否存在此设置,但请尝试查看游戏设置并找到一个显示“窗口模式”或“显示模式”的选项,如果看到它,请选择“窗口全屏”或“无边框”。

我不久前遇到了类似的问题,OBS 没有正确广播特定的失焦窗口,这就是我解决它的方法。由于您的代码适用于其他隐藏窗口,这可能也是您的问题。


1
投票

感谢 Github 上的 @wchill 找到此解决方案(link)!适用于 Windows,适用于硬件加速且被其他窗口遮挡的窗口。

import cv2
import numpy as np
from ctypes import windll
import win32gui
import win32ui


def capture_win_alt(window_name: str):
    # Adapted from https://stackoverflow.com/questions/19695214/screenshot-of-inactive-window-printwindow-win32gui

    windll.user32.SetProcessDPIAware()
    hwnd = win32gui.FindWindow(None, window_name)

    left, top, right, bottom = win32gui.GetClientRect(hwnd)
    w = right - left
    h = bottom - top

    hwnd_dc = win32gui.GetWindowDC(hwnd)
    mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
    save_dc = mfc_dc.CreateCompatibleDC()
    bitmap = win32ui.CreateBitmap()
    bitmap.CreateCompatibleBitmap(mfc_dc, w, h)
    save_dc.SelectObject(bitmap)

    # If Special K is running, this number is 3. If not, 1
    result = windll.user32.PrintWindow(hwnd, save_dc.GetSafeHdc(), 3)

    bmpinfo = bitmap.GetInfo()
    bmpstr = bitmap.GetBitmapBits(True)

    img = np.frombuffer(bmpstr, dtype=np.uint8).reshape((bmpinfo["bmHeight"], bmpinfo["bmWidth"], 4))
    img = np.ascontiguousarray(img)[..., :-1]  # make image C_CONTIGUOUS and drop alpha channel

    if not result:  # result should be 1
        win32gui.DeleteObject(bitmap.GetHandle())
        save_dc.DeleteDC()
        mfc_dc.DeleteDC()
        win32gui.ReleaseDC(hwnd, hwnd_dc)
        raise RuntimeError(f"Unable to acquire screenshot! Result: {result}")

    return img


def main():

    WINDOW_NAME = "PS Remote Play"
    while cv2.waitKey(1) != ord('q'):
        screenshot = capture_win_alt(WINDOW_NAME)
        cv2.imshow('Computer Vision', screenshot)


if __name__ == '__main__':
    main()

0
投票

我有一个错误:

File "c:\Users\karolkens\automategame\tets.py", line 31, in capture_win_alt      
img = np.frombuffer(bmpstr, dtype=np.uint8).reshape((bmpinfo["bmHeight"], bmpinfo["bmWidth"], 4))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: cannot reshape array of size 2 into shape (1,1,4)

知道如何解决吗?

© www.soinside.com 2019 - 2024. All rights reserved.