Проблемы при создании скриншотов окна и его отображении в OpenCV - PullRequest
1 голос
/ 05 февраля 2020

Когда я запускаю этот код на моем рабочем столе p c, он работает нормально. но когда я запускаю его на своем ноутбуке, что-то идет не так, когда я устанавливаю ограничивающий прямоугольник для захвата изображения на ограничивающий прямоугольник калькулятора 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

1 Ответ

0 голосов
/ 05 февраля 2020

Вот проблемы, с которыми я столкнулся при тестировании вашего кода:

  • Отображение окна калькулятора не работает правильно.
  • win32gui.FindWindow() не удалось найти правильное окно так что я в итоге заменил его. По некоторым причинам в Windows 10, win32gui.EnumWindows() перечислены 2 windows для одного приложения калькулятора: одно из них имеет отрицательные значения ширины / высоты.
  • win32gui.GetWindowRect() возвращает неправильную позицию и размеры окна , Кажется, что мое разрешение 1280x720. Вероятно, это происходит потому, что используется масштабирование DPI .
  • ImageGrab.grab() не удается сделать снимок экрана приложения с использованием координат и размеров из реального пространства разрешения монитора (1920x1080).

enter image description here

Obs: это приложение не будет работать, если целевое окно свернуто .

Исходный код :

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