학교 과제로 지질도의 3차원 분석을 작성하며 matplotlib의 3D projection을 사용하였다. 삼차원으로 그린 지형의 모습을 360도 돌리며 보여주는 자료를 보고서에 추가해야 해서, matplotlib에 내장된 animation 모듈을 사용하였다.
아래에서 언급하는 fig
, ax
는 아래 코드에서 왔다.
|
|
animation 모듈 사용법
animation을 사용하기 위해서는 애니메이션 모듈을 임포트한다.
|
|
animation.FuncAnimation
함수를 보자.
(간략한 설명만 한다. 자세한 내용은 링크를 참고하자)
|
|
- 이 함수를 호출할 때는 반환값을 변수로 받아주어야 한다. (예시의
anim =
) 그렇지 않으면 애니메이션이 GC에 의해 소멸된다. fig
는 플롯 변수animate
는 매 프레임마다 실행되는 함수다.animate(frame)
꼴로 실행되고, fig의 콜렉션을 반환하여야 한다. (exreturn fig,
)init_func
은animate
함수를 처음 실행하기 전 실행되는 함수다. (필수는 아니다) 호출 인자는 없다.animate
와 똑같이 fig의 콜렉션을 반환하여야 한다.frames
는animate
함수의 인자로 넘겨지기 위한 프레임들이다. 정수(range(0,정수)
를 넘기는 것과 동일) 또는 iterable 자료형을 넘길 수 있다. 예시에서는range()
를 넘겼다.interval
은 프레임 사이의 시간 차이다. 단위는 ms. 그런데 여기서 interval 지정해도, 이따 gif 저장할 때 fps 설정하면 의미 없는 값이다.blit
가True
면, 매번 그려지는 물체들은 각각의zorder
에 따라 그려지지만,False
면zorder
에 상관없이 이전에 그려진 그림 위에 새로 그려진다.
draw
함수는 대략 아래와 같이 구성할 수 있다.
|
|
animate
함수는 아래처럼 구현할 수 있다. 각 프레임마다 시야의 고도를 변화시키는 코드다.
|
|
이제 애니메이션을 만들었으니, gif를 저장해야 한다. 저장을 위해서는 ffmpeg
가 필요하다.
|
|
- 첫번째 인자는 파일이 저장될 경로를 지정한다.
fps
는 frame per second로, gif의 속도를 조절할 수 있다.- 저장은 그리 오래 걸리지 않는다.
만약 실제 작동하는 예시를 확인하고 싶다면, 보고서에서 사용된 코드를 참고해보자. (결과 gif. 용량 매우 큼)
multiprocessing
으로 애니메이션 병렬 처리
FuncAnimation
함수는 차례차례 한 프레임 한 프레임 animate
함수를 호출한다.
하지만 위의 코드처럼 시야 고도를 바꾸는 것만으로도 꽤 시간이 걸리고,
animate
함수에 복잡한 과정이 포함되었다면(만약 처음부터 다시 그린다거나…) 필자의 경우에는 8시간 이상 실행해도 360 프레임 중 200 프레임도 채 진행이 안 된 경우도 있었다.
오래 켜놓는 것도 능사가 아닌게, 180 프레임쯤에서 멈추면(경-험-담) 다시 시작하는 것 밖에 답이 없다!
그러므로 렌더링 시간 단축을 위해서 multiprocessing
을 사용해보자.
필자의 계획은 총 360 프레임을 90개씩 4세트로 나눈 다음, 이 4세트를 각각 5개의 프로세스로 나눠 실행하는 것이다. 그러니까, 한 프로세스당 90/5=18 프레임을 처리한다. 예를 들어, 0-89 1세트를 5개 프로세스로 병렬 처리 한 다음, 모든 프로세스가 끝나면 그 다음 2세트인 90-179를 또다시 5개 프로세스로 병렬 처리한다. 360개의 프레임을 곧바로 n개의 프로세스로 나누면 n이 작으면 각 프로세스마다 수행 시간이 너무 길고, 그렇다고 n을 키우면(프로세스의 수를 늘리면) 노트북의 발열이 심했다.
프로세스가 실행할 FuncAnimation
과 save
를 동시에 수행하는 함수를 만든다.
|
|
이제 multiprocessing
의 Process
모듈을 임포트한다.
|
|
프로세스 코드를 작성한다. 프로세스를 실행하는 코드는 if __name__ == "__main__":
구문으로 감싸야 한다.
그렇지 않으면 Frozen
에러가 발생한다.
|
|
(왜 종료할 때까지 대기하는 함수의 이름이 join일까? 이에 대한 해답)
anim_and_save
에서 지정한 이미지 저장 경로에 output_0.gif
, output_18.gif
, …, output_342.gif
로 총 20개(=5x4)의 gif 파일이 생성되었다. 이제 하나의 gif 파일로 합쳐주자.
imageio
모듈을 이용한다. pip로 먼저 설치해주자.
이하는 하나로 병합하는 코드다.
|
|