파이썬 화면 인식 - paisseon hwamyeon insig

안녕하세요? 만들오 입니다.

오늘은 윈도우의 특정 영역을 선택하여 opencv로 모니터링 하는 프로그램 기록을 남깁니다.

from PIL import ImageGrab
import cv2
import keyboard
import mouse
import numpy as np


def set_roi():
    global ROI_SET, x1, y1, x2, y2
    ROI_SET = False
    print("Select your ROI using mouse drag.")
    while(mouse.is_pressed() == False):
        x1, y1 = mouse.get_position()
        while(mouse.is_pressed() == True):
            x2, y2 = mouse.get_position()
            while(mouse.is_pressed() == False):
                print("Your ROI : {0}, {1}, {2}, {3}".format(x1, y1, x2, y2))
                ROI_SET = True
                return

keyboard.add_hotkey("ctrl+1", lambda: set_roi())

ROI_SET = False
x1, y1, x2, y2 = 0, 0, 0, 0
while True:
    if ROI_SET == True:
        image = cv2.cvtColor(np.array(ImageGrab.grab(bbox=(x1, y1, x2, y2))), cv2.COLOR_BGR2RGB)
        cv2.imshow("image", image)
        key = cv2.waitKey(100)
        if key == ord("q"):
            print("Quit")
            break

cv2.destroyAllWindows()

코드의 흐름은 다음과 같습니다.

1. 키보드의 ctrl + 1 버튼을 누르면 set_roi 함수를 호출합니다.

2. 마우스 down상태에서 x1, y1의 값을 기록하고, 마우스 up 상태에서 x2, y2의 값을 기록합니다. 메인루프에서 사용될 ROI_SET 변수를 True로 변환합니다.

3. 메인루프(while)단에서 지정된 영역(x1, y1, x2, y2)을 캡쳐하고 이를 opencv 윈도우를 통해 보여줍니다.

4. 종료를 위해서는 opencv 윈도우 활성화 상태에서 q 버튼을 누릅니다.

* 주의점 : 영역을 지정할 때 좌측상단에서 우측하단으로 드래그 해야합니다. 순서가 바뀌면 에러가 나게 됩니다.

예전에 Autohotkey를 이용해 X니지M 게임 자동귀환 프로그램을 만들었었는데 아직까지도 요청하시는 분들이 많아서 이번에는 python을 이용해 제작해 보려고 시작하게 되었습니다. 당시에는 단순히 화면의 컬러값을 읽어서 처리했었는데, python을 적용하는 만큼 tensorflow를 이용한 머신러닝도 가능할 것으로 생각됩니다.

감사합니다.

* 이 글은 티스토리 카카오계정 연동정책으로 인해 이전 블로그(오코취) 글을 옮겨왔습니다.

[].

안녕하세요, 왕초보 코린이를 위한 코딩유치원에 오신 것을 환영합니다.

파이썬 화면 인식 - paisseon hwamyeon insig

오늘은 엑셀이나 웹브라우저처럼 파이썬 전용 패키지가 없어서 조작을 할 수 없는 경우에 아주 유용한 PyAutoGUI라는 패키지에 대해서 배워보겠습니다.

저는 회사에서 SAP사의 ERP(Enterprise Resource Planning)를 사용하는데, 이걸 자동화 시키려고 하니깐 무료로 제공하는 API가 없어서 고민하던 중 해당 패키지를 사용하면 좋겠다는 생각이 들어서 공부해보게 되었답니다.

<PyAutoGUI 관련 글>

2021.06.14 - [파이썬 패키지/사무자동화] - [Python / PyAutoGUI] 파이썬 마우스/키보드 조작 패키지_1편.마우스 조작하기

2021.06.15 - [파이썬 패키지/사무자동화] - [Python / PyAutoGUI] 파이썬 마우스/키보드 조작 패키지_2편.키보드 조작하기(ft.한글 입력 방법)


이번 시간에는 직접 좌표를 지정해서 마우스를 움직이는 방법이 아니라,

화면에서 찾고자 하는 이미지를 캡처&저장해놓고 그 이미지의 좌표를 찾아가는 방법에 대해서 배워보겠습니다.

1. 화면 원하는 부분 캡처하기

이를 위해서 먼저 화면을 캡처하는 방법을 간단히 알아보겠습니다.

1) Windows OS

    - 캡처 도구 (모드는 사각형 캡처를 추천)

    - 캡처 후 저장하면 자동으로 png 파일로 저장됨 (파일명은 영어로 할 것)

파이썬 화면 인식 - paisseon hwamyeon insig

- Shift + 윈도우키 + S 

2) mac OS

   - Shift + Command + 4 (부분 캡처)

   - Shift + Command + 3 (전체 캡처)

   - 마찬가지로 저장 시 자동으로 png 파일로 저장됨 ((파일명은 영어로 할 것)

2. 캡처한 이미지로 좌표 정보 얻기

캡처한 이미지의 좌표를 얻으려면 locateOnScreen( ) 함수를 사용하시면 됩니다. 이때 괄호 안의 이미지는 같은 디렉토리에 위치해야 작동합니다. 굳이 이미지 파일을 다른 폴더에 위치시키고 싶다면 해당 경로를 입력해주어야합니다.

저의 경우는 화면 우측상단의 Run 버튼을 캡처해서 찾아보는 코드를 작성해보았습니다. img_capture 변수에 들어가 있는 값을 확인해보면 Box(left=x 좌표, top=y 좌표, width = 이미지 너비, height=이미지 높이)가 출력되는 것을 확인하실 수 있습니다.

img_capture = pyautogui.locateOnScreen("Run_icon.png")

print(img_capture)

pyautogui.click(img_capture)
파이썬 화면 인식 - paisseon hwamyeon insig

이미지의 경로가 제대로 설정되지 않은 경우에는 에러가 출력되며, 경로는 정확하지만 화면상에서 해당 이미지를 못 찾았을 때는 None(값이 없음을 의미)을 돌려줍니다.

3. 캡처한 이미지가 화면에 여러개 일 때

예를 들어서 아래와 같은 체크박스를 중복 선택해야한다면 어떻게 해야할까요?

파이썬 화면 인식 - paisseon hwamyeon insig

그럴 때는 아래와 같이 locateAllOnScreen( ) 함수와 for 문으로 해결 가능합니다. 위에서 배운 locateOnScreen( ) 함수와 무엇이 다른지 보이시죠? 해당 함수를 사용하면 원하는 이미지의 위치들을 리스트에 저장해놓고 for문으로 하나씩 꺼내어 쓰는 개념입니다.

for i in pyautogui.locateAllOnScreen("checkbox.png"):
    
    pyautogui.click(i, duration=0.25)

4. 범위 안에서만 캡처한 이미지를 찾고 싶을 때

다른 영역에 있는 중복되는 이미지를 무시하고 싶거나, 이미지 검색 범위를 좁혀 속도를 개선하고 싶을 때 사용하면 좋을 것 같아요.

import pyautogui

img_capture = pyautogui.locateOnScreen("Run_icon.png", region=(1800, 0, 1920, 100))

pyautogui.moveTo(img_capture)

Tip. 코드 실행 속도 측정법

import pyautogui
import time

start = time.time()  # 시작 시간 저장

img_capture = pyautogui.locateOnScreen("Run_icon.png")

pyautogui.moveTo(img_capture)

# 현재시각 - 시작시각 = 실행 시간
print("코드 실행 시간 :", time.time() - start)  

5. 이미지 인식이 됐다안됐다 할 때

가끔 찾고자 하는 이미지와 화면의 이미지가 어떤 이유로 100% 일치하지 않아서 잘 되던 코드가 실행이 되지 않을 경우도 있습니다. 저는 아직 겪어보지  않았지만 혹시 이런 현상이 발생한다면 지금 알려드리는 옵션을 사용해보세요!

이런 경우에는 예를 들어 일치도를 70% 이상이면 같은 이미지로 인식하라고 설정할 수가 있습니다.

이 기능을 사용하려면 아래의 패키지를 설치해주셔야 합니다.

# 이미지 처리 패키지인 opencv-python 설치
pip install opencv-python

사용법은 간단합니다. 지금껏 배워왔던 locateOnScreen 함수안에 confidence 옵션을 설정해주시면 됩니다.

img_capture = pyautogui.locateOnScreen("Run_icon.png", confidence=0.7) # 70%

pyautogui.moveTo(img_capture)

오늘 준비한 내용은 여기까지 입니다.


<참고 자료>

나도코딩_업무자동화 유튜브 강의:

https://www.youtube.com/watch?v=exgO1LFl9x8&t=3083s