Python3 관련

파이썬에서 Matplotlib를 사용해 gif 파일 만들기!

녕집사 2022. 2. 1. 00:30
반응형

Matplotlib는 매트랩의 결과 그래프 이미지를 python에서 출력할 수 있게 하는 라이브러리 입니다.

 

보통의 경우에는 결과 자료로 이미지를 출력하기 위해 나타내는 용도로 사용합니다.

 

만약에 다음과 같은 코드를 가진 함수를 그래프로 표현한다면 다음과 같습니다.

 

def target(x,y=0):
    return (-20*np.exp(-0.2*np.sqrt(0.5*(x**2 + y**2)))
           - np.exp(0.5*(np.cos(2*np.pi*x) + np.cos(2*np.pi*y)))
           + np.e + 20)

 

matplotlib를 활용해 그래프 생성:

 

x_axis_val_front = -5
x_axis_val_back = 5

x = np.linspace(x_axis_val_front, x_axis_val_back, 5000).reshape(-1, 1)
y = target(x)

gs = gridspec.GridSpec(1, 1)
axis = plt.subplot(gs[0])

axis.plot(x, y, linewidth=3, label='Target')
plt.show()

이 상태에서 그래프의 특정 부분에 표시를 하고 싶으면 다음과 같은 코드를 작성하면 됩니다.

 

axis.plot(0, 0, '*', markersize=15, markerfacecolor='gold', markeredgecolor='k', markeredgewidth=1)

(0, 0)의 좌표에 별 모양의 점을 찍었습니다.

 

이후에 어떤 연속적인 좌표를 찍고 싶을 때 그 일련의 과정을 한번에 보고 싶을 수 있습니다.

 

그럴 때는 단순하게 이미지를 여러번 저장하고 한번에 묶어서 gif 파일을 만들면 되겠다는 생각을 할 수 있습니다.

 

이를 파이썬을 통해서 구현이 가능합니다.

 

def make_plot(x,y):
    gs = gridspec.GridSpec(1, 1)
    axis = plt.subplot(gs[0])

    axis.plot(x, y, linewidth=3, label='Target')
    axis.plot(i, target(i), '*', markersize=15, markerfacecolor='gold', markeredgecolor='k', markeredgewidth=1)

filenames = []

for i in range(-5,6,1):
    make_plot(x,y)
    filename = f'{i}.png'
    filenames.append(filename)
    plt.savefig(filename)
    plt.close()

frames = []
for filename in filenames:
    if filename.endswith(".png"):
        print(filename)
        frames.append(imageio.imread(filename))

exportname = "output.gif"

imageio.mimsave(exportname, frames, format='GIF', duration=duration_rate)

for filename in set(filenames):
    os.remove(filename)

 

-5 에서 5까지 target 함수의 x에 대입한 후 y값을 계산해서 해당 결과를 그래프로 표시해주고, 차례대로 gif 파일로 제작하는 코드입니다.

 

실행 결과는 다음과 같습니다.

 

imageio 라이브러리의 mimsave함수를 활용해서 GIF 파일을 생성했습니다.

 

해당 라이브러리의 duration을 통해서 더 빠르게 만들거나 천천히 만들 수 있습니다.

 

본 코드에서는 png파일을 순서대로 생성하고 이를 한번에 합치고 제거하는 과정으로 코드를 완성했습니다.

 

만약에 수많은 과정을 gif 파일로 만들고 싶다면 thread를 사용하거나 전체 과정을 쪼개서 gif 파일로 따로 묶어야 할 것입니다. 

 

그렇지 않으면 CPU가 힘들어하는 광경을 볼 수 있습니다..

 

앞선 과정까지의 전체 코드입니다.

 

from matplotlib import gridspec
import matplotlib.pyplot as plt
import imageio
import numpy as np
import os

def target(x,y=0):
    return (-20*np.exp(-0.2*np.sqrt(0.5*(x**2 + y**2)))
           - np.exp(0.5*(np.cos(2*np.pi*x) + np.cos(2*np.pi*y)))
           + np.e + 20)

x_axis_val_front = -5
x_axis_val_back = 5
duration_rate = 1

x = np.linspace(x_axis_val_front, x_axis_val_back, 5000).reshape(-1, 1)
y = target(x)

def make_plot(x,y):
    gs = gridspec.GridSpec(1, 1)
    axis = plt.subplot(gs[0])

    axis.plot(x, y, linewidth=3, label='Target')
    axis.plot(i, target(i), '*', markersize=15, markerfacecolor='gold', markeredgecolor='k', markeredgewidth=1)

filenames = []

for i in range(-5,6,1):
    make_plot(x,y)
    filename = f'{i}.png'
    filenames.append(filename)
    plt.savefig(filename)
    plt.close()

frames = []
for filename in filenames:
    if filename.endswith(".png"):
        print(filename)
        frames.append(imageio.imread(filename))

exportname = "output.gif"

imageio.mimsave(exportname, frames, format='GIF', duration=duration_rate)

for filename in set(filenames):
    os.remove(filename)

 

지금까지 matplotlib를 통해 gif 파일을 생성하는 과정을 함께했습니다.

 

제가 보여드린 방법 외에 더 좋은 방법이나 효율적인 방법을 알고 계신다면 댓글로 남겨주세요.

 

반응형