-
Notifications
You must be signed in to change notification settings - Fork 0
/
screen_capture.py
129 lines (89 loc) · 4.12 KB
/
screen_capture.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import cv2
import numpy
import win32api, win32ui, win32gui, win32con
class ScreenCapture():
def __init__(self, name="Window", top=0, left=0, width=640, height=480, window=None, monitor=None, border=True, d3d=None):
self.hwnd = None
self.name, self.top, self.left, self.width, self.height, self.window, self.monitor, self.border, self.d3d = name, top, left, width, height, window, monitor, border, d3d
if window is not None:
self.hwnd = win32gui.FindWindow(None, window)
if not self.hwnd:
raise Exception(f"Window: {window} not found.")
window_rect = win32gui.GetWindowRect(self.hwnd)
client_rect = win32gui.GetClientRect(self.hwnd)
self.border_width = (window_rect[2] - window_rect[0]) - client_rect[2]
self.border_height = (window_rect[3] - window_rect[1]) - client_rect[3]
self.width = window_rect[2] - window_rect[0]
self.height = window_rect[3] - window_rect[1]
if border:
if self.d3d:
self.left = window_rect[0]
self.top = window_rect[1]
else:
self.left = -(self.border_width // 2)
self.top = -(self.border_height - self.border_width // 2)
else:
if self.d3d:
self.left = window_rect[0] + (self.border_width // 2)
self.top = window_rect[1] + (self.border_height - self.border_width // 2)
self.width -= self.border_width
self.height -= self.border_height
if monitor is not None:
try:
get_monitors = win32api.EnumDisplayMonitors(None, None)
monitor_left, monitor_top, monitor_right, monitor_bottom = get_monitors[monitor][2]
self.top = monitor_top
self.left = monitor_left
self.width = (monitor_right - monitor_left)
self.height = (monitor_bottom - monitor_top)
except:
raise Exception(f"Display {monitor} not found.")
if self.d3d:
self.hwnd = None
self.hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(self.hwnd))
self.cdc = self.hdc.CreateCompatibleDC()
self.hbit = win32ui.CreateBitmap()
self.hbit.CreateCompatibleBitmap(self.hdc, self.width, self.height)
def __del__(self):
cv2.destroyAllWindows()
if hasattr(self, "hdc"):
self.hdc.DeleteDC()
if hasattr(self, "cdc"):
self.cdc.DeleteDC()
if hasattr(self, "hbit"):
win32gui.DeleteObject(self.hbit.GetHandle())
def read(self, color=True):
if self.d3d:
hwnd = win32gui.FindWindow(None, self.window)
window_rect = win32gui.GetWindowRect(hwnd)
if self.border:
self.left = window_rect[0]
self.top = window_rect[1]
else:
self.left = window_rect[0] + (self.border_width // 2)
self.top = window_rect[1] + (self.border_height - self.border_width // 2)
self.cdc.SelectObject(self.hbit)
self.cdc.BitBlt((0, 0), (self.width, self.height), self.hdc, (self.left, self.top), win32con.SRCCOPY)
signedIntsArray = self.hbit.GetBitmapBits(True)
image = numpy.frombuffer(signedIntsArray, dtype="uint8")
image.shape = (self.height, self.width, 4)
if not color:
image = cv2.cvtColor(image, cv2.COLOR_RGBA2GRAY)
else:
image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
return image
def list_monitors():
for k, v in enumerate(win32api.EnumDisplayMonitors(None, None)):
print( f"{k}: " + str(win32api.GetMonitorInfo(v[0])) )
def main():
cap = ScreenCapture()
while True:
frame = cap.read()
cv2.imshow(cap.name, frame)
key = cv2.pollKey()
if key == ord("q"):
break
if not cv2.getWindowProperty(cap.name, cv2.WND_PROP_VISIBLE):
break
if __name__ == "__main__":
main()