Broccoli's House

#5-(1) 파이썬을 이용한 게임 이미지 추출 본문

공부/캡스톤 디자인

#5-(1) 파이썬을 이용한 게임 이미지 추출

김콜리 2018. 3. 8. 15:09

5회차 - (1) 파이썬을 이용한 시뮬레이터(BeamNG Drive) 영상 이미지 추출



  • 직접적 방법
 - 앞서 설치 및 환경을 구성한 Microsoft AirSim이나 TORCS에서는 프로그램 소스 코드를 이용하여 게임 이미지를 직접적으로 받아올 수 있다. AirSim의 경우 C언어 기반으로 작성된 시뮬레이터이지만, 서버-클라이언트 방식으로 파이썬에서 시뮬레이터의 이미지를 추출하는 API를 자체적으로 제공한다.   따라서 별 다른 어려움 없이, 예제 코드를 따라하면 그대로 영상을 추출할 수 있다. (https://github.com/Microsoft/AirSim/blob/master/docs/image_apis.md)를 참고하면 된다.


 - AirSim과는 다르게, TORCS에서 파이썬으로 이미지를 추출하는 것은 쉽지 않다. TORCS 또한 AirSim과 마찬가지로 C++ 기반으로 작성되었지만, SCR-패치를 통한 서버-클라이언트 통신 방식에서 이미지를 추출하는 자체 API는 제공하지 않는다. 따라서 파이썬으로 이미지를 받기란 쉽지 않다. 그러나 TORCS는 OpenGL 기반으로 그래픽을 렌더링하여, C++로 작성된 TORCS의 메인 소스 코드에서 OpenGL API를 사용하면 이미지를 추출할 수 있다. 즉, 서버-클라이언트 방식이 아닌 메인 소스 코드를 변경 및 추가하는 방식으로 시뮬레이터 영상을 추출할 수 있는 것이다. 관련된 내용은 위의 PDF 문서에서 확인할 수 있다. 그러나 우리는 파이썬으로 이미지를 추출 및 가공하고자 하므로 다른 방법을 이용한다.




  • 간접적 방법

 - 소스 코드나 통신을 통해 시뮬레이터에서 영상 이미지를 받아오는 직접적 방식과는 다르게, 파이썬의 라이브러리를 사용하여 컴퓨터 스크린의 화면 자체를 캡처함으로써 간접적으로 시뮬레이터의 이미지를 받아온다. 


 - 스크린 캡처 방식에는 여러 장점이 있는데 첫째, 간편하다는 것이다. 위의 직접적 방식은 간접적 방식에 비해 꽤나 복잡하다. 간접적 방법을 사용해 이미지를 받아오는데는 코드 두 줄이면 충분할만큼 간단하다. 두 번째는 이미지를 받아오는 것이 빠르다는 점이다. AirSim에서 서버-클라이언트 통신을 통해 시뮬레이터의 이미지를 받는 데에는 대략 60ms 정도가 소요된다(컴퓨터마다 다를 수 있음). 그러나 파이썬의 스크린 캡처 라이브러리 중 가장 빠른 것은 30ms 정도밖에 소요되지 않는다. 마지막으로, 사용할 수 있는 시뮬레이터의 범위가 넓어진다는 점이다. 이미지를 받아오기 위해서 오픈 소스로 된 시뮬레이터(AirSim, TORCS)를 이용하였지만, 스크린 캡처는 굳이 소스가 오픈되어 있지 않아도 이미지를 받아올 수 있으므로 어떤 시뮬레이터나 게임이건 관계없이 사용할 수 있다.


 - 스크린을 캡처할 수 있는 파이썬 라이브러리는 많이 있지만, 파이썬 3을 기준으로 PIL의 ImageGrab.grab(), PyAutoGUI의 screenshot(), MSS의 sct.shot() 이 세 가지를 비교해보고자 한다. 


 라이브러리

PIL (ImageGrab.grab())

 PyAutoGUI (screenshot())

 MSS (sct.shot())

촬영 시간(저장 X)

30ms

300ms

40ms

 촬영 시간(저장 O)

90ms

500ms

100ms


 - 세 라이브러리의 이미지 캡처 함수를 사용하여 캡처를 해본 결과, PIL의 ImageGrab.grab() 함수가 저장을 하지 않았을 때나 저장을 하였을 때 가장 빠른 캡처 성능을 보였다. 이미지의 실시간 처리를 위해서는 이미지를 받아오는 시간이 무조건 짧아야 하는데, 저장을 하지 않았을 때 30ms 정도의 시간이 걸리므로 대략 30fps 정도의 초당 프레임 수가 나온다. 따라서 이미지를 캡처할 때 ImageGrab.grab() 함수를 사용하도록 한다.




  • 이미지 추출

 - PIL의 ImageGrab.grab() 함수를 사용하여 이미지를 추출해본다. 시뮬레이터로는 차량 손상 시뮬레이터인 BeamNG Drive를 사용하였다.


import numpy as np # 배열 라이브러리
from PIL import ImageGrab # 스크린 캡처 라이브러리
import cv2 # OpenCV, 이미지 처리 라이브러리

while (True): # 무한 반복
screen = ImageGrab.grab() # 스크린을 캡쳐하여 변수에 저장
screen = np.array(screen) # 이미지를 배열로 변환
cv2.imshow('window', cv2.cvtColor(screen, cv2.COLOR_BGR2RGB))
# window라는 이름의 창을 생성하고, 그 곳에 이미지를 출력함 



 - 위의 동영상에서 우측이 실제 게임 영상이고, 좌측은 영상 이미지를 받아와 반복해서 출력해주는 창이다. 약간의 딜레이를 제외하고는 이미지를 잘 추출하는 것을 볼 수 있다.


Comments