본문 바로가기
소프트웨어/파이썬

[파이썬] 윈도우 화면 캡처 (with mss)

by 만들오 2022. 3. 10.
728x90
윈도우 화면 캡처란?

관심영역(ROI : Region of interesting)의 화면을 캡쳐합니다. 유용하게 사용하고 있는 윈도우 캡처 도구의 창 캡처와 동일한 방식입니다.


파이썬 라이브러리 설치
pip install PySimpleGUI opencv-python mss pywin32

위 명령어로 라이브러리를 설치합니다.


파이썬 코드
import PySimpleGUI as sg
import win32gui
import win32com.client
import cv2
import numpy as np
import mss

# 접을 수 있는 행 추가 함수
def add_row(layout, key):
    return [sg.pin(sg.Column(layout, key=key, visible=False))]

# 윈도우에 실행중인 모든 창의 Text, handle을 list로 반환.
def get_win_list():
    def callback(hwnd, hwnd_list: list):
        title = win32gui.GetWindowText(hwnd)
        if win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd) and title:
            hwnd_list.append((title, hwnd))
        return True
    output = []
    win32gui.EnumWindows(callback, output)
    return output

# window handle로 이미지 위치 및 크기 찾는 함수
def get_win_size(hwnd):
    left, top, right, bottom = win32gui.GetWindowRect(hwnd)
    return left, top, right, bottom


shell = win32com.client.Dispatch("WScript.Shell")
def set_foreground(hwnd):
    shell.SendKeys('%')
    win32gui.SetForegroundWindow(hwnd) # window handle로 창 앞으로 가져오기:

# 이미지 캡쳐하기
def get_win_image(x1, y1, x2, y2):
    # img = cv2.cvtColor(np.array(ImageGrab.grab(bbox=(x1, y1, x2, y2))), cv2.COLOR_RGB2BGR) # PIL VER
    with mss.mss() as sct: # mss로 캡처 수정 - 2022.03.08
        pos = {"left":x1, "top":y1, "width":x2-x1, "height":y2-y1}
        img = np.array(sct.grab(pos))
    return img

win_list = get_win_list()
win_text = [list[0] for list in win_list]
hwnd = None
run = False
s_1 = (10, None)  # 1st column size
s_b = (6, None) # Button size
s_i = (3, None) # Input size

sg.theme("Dark2")

lay_main = [
    [sg.Text("윈도우", size=s_1), sg.Combo(values=win_text, key="WIN", readonly=True, expand_x=True, enable_events=True)],
    [sg.Button("시작", size=s_b, key="START", expand_x=True, metadata=False), sg.Button("정지", size=s_b, key="STOP", expand_x=True)],
    [sg.Image(filename="", key="IMG")],
]

window = sg.Window('리니지W V6-r4, 2022.03.10', lay_main, grab_anywhere=True)

while True:
    evt, val = window.read(timeout=250)

    if evt == sg.WIN_CLOSED:
        break
    elif evt == "WIN":
        selected_text = window["WIN"].get()
        selected_text_idx = win_text.index(selected_text)
        hwnd = win_list[selected_text_idx][1]
        print("윈도우가 선택되었습니다. {}".format(hwnd))
    
    elif evt == "START":
        run = False if hwnd == None else True
        set_foreground(hwnd)

    elif evt == "STOP":
        run = False
    
    if run:
        x1, y1, x2, y2 = get_win_size(hwnd) # 윈도우 핸들로 게임창의 위치를 찾는다.
        fullImage = get_win_image(x1, y1, x2, y2) # 게임창 전체를 캡쳐한다.
        window["IMG"].update(data=cv2.imencode(".png", fullImage)[1].tobytes()) # 이미지 업데이트
            
window.close()

제가 만들어 사용하는 앱의 일부를 떼어와서 불필요한 변수가 몇개 있습니다. 

모바일로 글 편집 시 코드의 줄바꿈이 사라지는 오류로 인해 파일을 첨부했습니다.

capture_window.py
0.00MB


실행 화면

 

기타 궁금하신 부분은 댓글을 남겨주세요.

 

감사합니다.

[끝].

댓글