Dear, List Members using the FindWindow function from win32gui to find the window handle of a certain window through window name to enable video capture of certain window results in a black screen. Although trying the same code without a window handle to default it to capturing the whole screen results in a successful video capture, the same code however results in a black or white screen when trying to capture a specific window with window handle. How can I solve this? Code: This is the main file, main.py import cv2 as cv import numpy as np import os from time import time from windowcapture import WindowCapture # Change the working directory to the folder this script is in. # Doing this because I'll be putting the files from each video in their own folder on GitHub os.chdir(os.path.dirname(os.path.abspath(__file__))) # initialize the WindowCapture class wincap = WindowCapture('Albion Online Client') loop_time = time() while(True): # get an updated image of the game screenshot = wincap.get_screenshot() cv.imshow('Computer Vision', screenshot) # debug the loop rate print('FPS {}'.format(1 / (time() - loop_time))) loop_time = time() # press 'q' with the output window focused to exit. # waits 1 ms every loop to process key presses if cv.waitKey(1) == ord('q'): cv.destroyAllWindows() break print('Done.') This is the class file which gets imported into main.py, windowcapture.py import numpy as np import win32gui, win32ui, win32con class WindowCapture: # properties w = 0 h = 0 hwnd = None cropped_x = 0 cropped_y = 0 offset_x = 0 offset_y = 0 # constructor def __init__(self, window_name): # find the handle for the window we want to capture self.hwnd = win32gui.FindWindow('UnityWndClass', window_name) if not self.hwnd: raise Exception('Window not found: {}'.format(window_name)) # get the window size window_rect = win32gui.GetWindowRect(self.hwnd) self.w = window_rect[2] - window_rect[0] self.h = window_rect[3] - window_rect[1] # account for the window border and titlebar and cut them off border_pixels = 8 titlebar_pixels = 30 self.w = self.w - (border_pixels * 2) self.h = self.h - titlebar_pixels - border_pixels self.cropped_x = border_pixels self.cropped_y = titlebar_pixels # set the cropped coordinates offset so we can translate screenshot # images into actual screen positions self.offset_x = window_rect[0] + self.cropped_x self.offset_y = window_rect[1] + self.cropped_y def get_screenshot(self): # get the window image data wDC = win32gui.GetWindowDC(self.hwnd) dcObj = win32ui.CreateDCFromHandle(wDC) cDC = dcObj.CreateCompatibleDC() dataBitMap = win32ui.CreateBitmap() dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h) cDC.SelectObject(dataBitMap) cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY) # convert the raw data into a format opencv can read #dataBitMap.SaveBitmapFile(cDC, 'debug.bmp') signedIntsArray = dataBitMap.GetBitmapBits(True) img = np.fromstring(signedIntsArray, dtype='uint8') img.shape = (self.h, self.w, 4) # free resources dcObj.DeleteDC() cDC.DeleteDC() win32gui.ReleaseDC(self.hwnd, wDC) win32gui.DeleteObject(dataBitMap.GetHandle()) # drop the alpha channel, or cv.matchTemplate() will throw an error like: # error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type() # && _img.dims() <= 2 in function 'cv::matchTemplate' img = img[...,:3] # make image C_CONTIGUOUS to avoid errors that look like: # File ... in draw_rectangles # TypeError: an integer is required (got type tuple) # see the discussion here: # https://github.com/opencv/opencv/issues/14866#issuecomment-580207109 img = np.ascontiguousarray(img) return img # find the name of the window you're interested in. # once you have it, update window_capture() # https://stackoverflow.com/questions/55547940/how-to-get-a-list-of-the-name-of-every-open-window def list_window_names(self): def winEnumHandler(hwnd, ctx): if win32gui.IsWindowVisible(hwnd): print(hex(hwnd), win32gui.GetWindowText(hwnd)) win32gui.EnumWindows(winEnumHandler, None) # translate a pixel position on a screenshot image to a pixel position on the screen. # pos = (x, y) # WARNING: if you move the window being captured after execution is started, this will # return incorrect coordinates, because the window position is only calculated in # the __init__ constructor. def get_screen_position(self, pos): return (pos[0] + self.offset_x, pos[1] + self.offset_y) This code was run on a HP Pavilion Gaming Laptop, Model: 15-dk1056wm This laptop was running a 24 bit depth display This code was run in a python virtual environment using virtualenv, this virtual environment was running Python 3.8.0 – 32 bit Code dependencies: appdirs==1.4.4 distlib==0.3.2 filelock==3.0.12 numpy==1.20.3 opencv-python==4.5.2.52 pywin32==301 six==1.16.0 virtualenv==20.4.7 Sent from<https://go.microsoft.com/fwlink/?LinkId=550986> Mail for Windows 10 Sincerely, A Fellow List Member
_______________________________________________ python-win32 mailing list python-win32@python.org https://mail.python.org/mailman/listinfo/python-win32