개발/PYTHON

파이썬 화면캡쳐, 이미지 저장 기능

Aireee 2021. 5. 12. 02:19
300x250
반응형

  윈도우에서 파이썬의 pyautogui 를 사용하여 마우스를 제어하여 반복적인 단순 노동을 자동화하기 위한 매크로 프로그램을 만들기 시작했다. 사실 초반에는 애를 좀 먹었다. 아무리 해도 프로그램이 클릭이 되지 않았기 때문인데, 허무하게도 관리자모드로 실행하니 작동하기 시작했다. 정말 허망했다. 안되던게 모두 되기 시작한다. 관리자 모드의 힘은 어디까지인것인지!! 

  그래서 잘 만들고 있는데, 몇가지 문제들이 발생하기 시작했다. 일단 한가지는 예외처리를 해야 하는 상황이다. 나는 A 라는 상황을 진행해야 하는데, 버튼이 비활성된다든지, 버튼의 위치가 바뀐다든지 그러한 이유로 프로그램이 오작동하기 시작한 것이다. 또 다른 문제는, 마우스는 언제나 지정한 곳을 지정한 시간에 클릭한다는 것이다. 그 시간에 내가 원하는 부분이 정확한 위치에 있지 않을 경우 이후는 무조건 오작동의 길로 접어드는 것이다. 그래서 생각해 보았다. 어떻게 하면, 이 오작동을 막을 수 있을까? 

  내가 내린 결론은 이미지를 이용하는 것이었다. 화면을 캡쳐한 후, 특정화면이 나와야 하는데 내가 원하는 화면이 아닐 경우 프로그램을 중단시켜 버리거나, 그 부분은 뛰어 넘고 다른 부분으로 이동하게 하는 것이다. 방식은 간단했다. 

1. 화면을 캡쳐한다. 
2. 캡쳐한 파일에서 비교할 부분을 잘라낸다
3. 기존에 저장한 비교부분 이미지와 동일한지를 체크한다
4. 동일할 때, 동일하지 않을 때 처리를 다르게 한다. 

4번의 경우는 그냥 if ... else 문을 사용하면 되기 때문에 딱히 생각을 오래할 필요는 없었다. 하지만 캡쳐한 이미지를 잘라낼 때 내 속을 좀 썩였다. 이 부분은 소스를 보면서 설명해 드리고자 한다. 

우선 이미지 캡쳐와 저장에 필요한 모듈을 설치해야 한다

pip install pillow

바로 pillow 가 오늘 필요한 모듈이다. 다른 역할은 사실 잘 모른다. 현재로서는 딱히 관심이 없다보니, 일단 무언가를 하면서 익히는 스타일의 나로서는 이 이상의 기능은 당장에 필요가 없기 때문이기도 하다. 

자, 그럼 소스를 작성해보도록 하자

from PIL import ImageGrab, Image

img = ImageGrab.grab()
imgCrop = img.crop((100,100,200,200))
saveas="{}{}".format('imagename','.png')
imgCrop.save(saveas)

img1 = Image.open(saveas)
img2 = Image.open('check.png')

if img1 == img2 :
	print("같다")
else :
	print("다르다")

사실 조금 더 간단하게 만들 수도 있을 것 같지만, 일단은 이렇게 해둔 상태다. 테스트를 해보기 전이기 때문이다. 

  소스를 하나하나 설명하자면.. 첫번째 줄의 "from PIL import ImageGrab, Image" 는 PIL 이라는 모듈("pip install  pillow" 라는 이름으로 설치한 모듈)안에 있는 ImageGrab 이라는 함수와 Image 라는 함수를 가져와서 사용할 것이라는 명령어다.  3번째 줄에 있는 ImageGrab.grab() 이라는 명령어는 "화면전체를 캡쳐하라"는 명령이다. 화면 전체를 캡쳐해서 img 라는 변수에 저장을 하고 4번째 줄에서는 img 라는 변수에 crop을 실행하는데 100, 100, 200, 200 이라는 좌표값을 기준으로 하는 사각형으로 자르라는 말이다. 순서는 x1, y1, x2, y2 이다. 난 처음에 이걸 모르고 처음 x1, y1 을 제대로 작성 한 후 x2, y2 는 이미지의 사이즈를 집어넣어 계속 오류를 발생시켰다. 아마도 ImageGrab.grab() 부분의 괄호() 안에 (100, 100, 200, 200) 을 바로 작성하는 것도 가능할 듯 보인다. 그렇다면 소스 코드가 1줄 줄어드는 것이라 행복한데, 아직 테스트를 안해봤다. 그냥 하면 되지만 게으른 내 성격상 안할지도 모르겠다. 5번째 줄은 파일명을 지정하는 방식인데 {}{} 는 저 안에 두개의 값이 각각 들어갈 수 있다는 것을 말하고, format('a','b') 와 같은 형식으로 집어 넣은 것인데, a 와 b 를 넣으면 출력은 그냥 ab 로 출력된다고 보면 된다. 사실 saveas = 'imagename.png' 라고 작성해도 되고, 바로 아래줄인 6번째 줄에 saveas 대신 'imagename.png' 를 넣어줘도 상관은 없을 듯 싶다. 그리고 6번째 줄에서 나는 캡쳐해서 잘라낸 이미지를 저장을 시켰다. (꼭 저장을 해야만 가능한지 여부는 아직 테스트해보진 않았다)  8번째 줄은 방금 잘라서 저장한 이미지 파일을 불러오는 명령어다. Image.open() 이라는 명령어로 괄호 안에 있는 파일을 열어서 img1 이라는 변수에 대응시켰고, 9번째 줄은 check.png 라는 파일을 불러와서 img2 에 넣은 것이다.  10번째 줄에서는 img1 과 img2 가 '같다' 인지 비교를 해 보았고, 11번째 줄은 같을 때, 12번째 줄 else 는 "그렇지 않다면" 을 의미한다고 보면 된다. 그래서 13번째 줄은 다를 때 print 즉 () 안의 내용을 출력하라는 명령이다. 

  이와 같은 방식의 소스를 사용한다면, 단순 예외처리 뿐만 아니라, 마우스의 위치가 틀어졌을 때에도 대처가 가능할 것으로 본다. 사용한 이미지 파일은 모두 삭제하도록 처리한다면 나중에 더는 사용하지 않는 이미지가 넘쳐나지 않는데 도움이 될 것이라고 본다. 이미지 삭제는 사실상 파일 삭제이므로 파일 삭제기능을 넣어야 하는데.. 기억나지 않으므로 당장은 패스하도록 한다.

다음 번에 이 모듈을 사용한다면, 이번 보다 더 빠르게 사용이 가능하지 않을까 싶다. 
또한 화면캡쳐와 비교를 이용한다면, 오토마우스도 보다 더 정확도를 높일 수 있으리라 생각된다. 많은 업무의 자동화가 가능할 것으로 보인다. 검색하다보니, 이미지에서 글씨를 추출하는 모듈도 있는 것 같던데... 그런 것 까지 사용한다면 점점 더 많은 일을 오토마우스가 할 수 있을 것으로 보인다. 

궁금해진다. 어느 곳의 반복작업을 자동화하면 좋을지 말이다. 

반응형