截取窗口屏幕截图并使用 OpenCV 显示时出现的问题 [英] Problems while taking screenshots of a window and displaying it with OpenCV

查看:323
本文介绍了截取窗口屏幕截图并使用 OpenCV 显示时出现的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在台式电脑上运行此代码时,它运行良好.但是当我在我的笔记本电脑上运行它时,当我将图像抓取的边界框设置为 Windows 计算器的边界框和窗口的屏幕录制并将其自身稍微向上和向左放置时,出现了问题.

导入 cv2将 numpy 导入为 np从 PIL 导入 ImageGrab导入 win32guidef windowGrab(window_title=None):如果 window_title:全球硬件hwnd = win32gui.FindWindow(None, window_title)如果 hwnd:win32gui.SetForegroundWindow(hwnd)别的:打印(找不到窗口")windowGrab("计算器")为真: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('窗口', 屏幕)如果 cv2.waitKey(25) &0xFF == ord('q'):cv2.destroyAllWindows()休息

解决方案

以下是我在测试您的代码时遇到的问题:

  • 无法正常显示计算器窗口.
  • win32gui.FindWindow() 没有找到正确的窗口,所以我最终更换了它.出于某种原因,在 Windows 10 上,win32gui.EnumWindows() 为一个计算器应用列出了 2 个窗口:其中一个具有负的宽度/高度值.
  • win32gui.GetWindowRect() 返回错误的窗口位置和尺寸.它似乎认为我的分辨率是 1280x720.这可能是因为

    Obs:如果目标窗口最小化,此应用程序将无法运行.

    源代码:

    导入 cv2将 numpy 导入为 np导入系统导入 ctypes导入 ctypes.wintypes从 ctypes.wintypes 导入 HWND、RECT、DWORD从 ctypes 导入 *导入 win32gui导入 win32con从 PIL 导入 ImageGrab# 全局变量dwmapi = ctypes.WinDLL("dwmapi")APP_NAME = ''win_hwnd = -1定义回调(hwnd,额外):wnd_name = win32gui.GetWindowText(hwnd)如果(wnd_name == APP_NAME):rect = win32gui.GetWindowRect(hwnd)x = 矩形 [0]y = 矩形 [1]w = rect[2] - xh = rect[3] - y#print("姓名:%s" % wnd_name)#print("\tLocation: (%d, %d)" % (x, y))#print("\t 大小:(%d, %d)" % (w, h))如果 (x >= 0 并且 y >= 0):全局 win_hwndwin_hwnd = hwnddef windowGrab(window_title=None):全局 APP_NAME,win_hwndAPP_NAME = window_title如果 (window_title 为 None) 或 (len(window_title) == 0):print('!!! window_title == None')sys.exit(-1)# 尝试找到具有匹配标题和有效坐标的窗口win32gui.EnumWindows(回调,无)# 检查是否有焦点如果 (win_hwnd != win32gui.GetForegroundWindow()):打印('未聚焦')win32gui.SetActiveWindow(win_hwnd)win32gui.SetForegroundWindow(win_hwnd)# 主要的()windowGrab("计算器")# 允许 ImageGrab 捕获整个屏幕的解决方法user32 = ctypes.windll.user32user32.SetProcessDPIAware()# 获取显示器分辨率screen_w = ctypes.windll.user32.GetSystemMetrics(0)screen_h = ctypes.windll.user32.GetSystemMetrics(1)打印('screen_w=',screen_w,'screen_h=',screen_h)# 环形为真:# 获取窗口的大小和位置矩形 = 矩形()DWMWA_EXTENDED_FRAME_BOUNDS = 9dwmapi.DwmGetWindowAttribute(HWND(win_hwnd), DWORD(DWMWA_EXTENDED_FRAME_BOUNDS), ctypes.byref(rect), ctypes.sizeof(rect))x = rect.lefty = rect.topw = rect.right- xh = rect.bottom - y打印('x=', x, 'y=', y, 'w=', w, 'h=', h)如果(w == 0 或 h == 0):继续# 截取桌面的完整截图full_screen = np.array(ImageGrab.grab( bbox= (0, 0, screen_w, screen_h) ))如果(全屏为无):继续# 从屏幕截图中裁剪窗口区域cropped_rgb = full_screen[y : y+h, x : x+w]# 将 RGB 转换为 BGR 顺序,以便正确显示颜色cropped_bgr = cv2.cvtColor(cropped_rgb,cv2.COLOR_RGB2BGR)cv2.imshow('window',cropped_bgr)键 = cv2.waitKey(25)if (key & 0xFF) == ord('q'):休息cv2.destroyAllWindows()

    When i run this code on my desktop pc it runs fine. but when i run it op my laptop something goes wrong when i set the bounding box for the image grab to the bounding box of the windows calculator and the screen recording of the window and places it self a little up and to the left.

    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
    

    解决方案

    Here are the problems that I faced while testing your code:

    • Displaying the calculator window wasn't working correctly.
    • win32gui.FindWindow()wasn't finding the correct window so I ended up replacing it. For some reason on Windows 10, win32gui.EnumWindows() lists 2 windows for one Calculator app: one of them has negative width/height values.
    • win32gui.GetWindowRect() returns the incorrect position and dimensions of the window. It seems to think my resolution is 1280x720. This probably happens because DPI scaling is being used.
    • ImageGrab.grab() has trouble taking a screenshot of the app using coordinates and dimensions from the real monitor resolution space (1920x1080).

    Obs: this application won't work if the target window is minimized.

    Source code:

    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()
    

    这篇关于截取窗口屏幕截图并使用 OpenCV 显示时出现的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆