先占個(gè)位崖咨,以后解釋原理
如何用 Matplotlib 畫 GIF 動(dòng)圖
- 原文來源:http://codingpy.com/article/drawing-gifs-with-matplotlib
- 轉(zhuǎn)帖鏈接:編程派
- 類型:
python
今天分享的這篇譯文中介紹了 matplotlib
繪圖庫的一個(gè) 使用示例荚醒,即如何制作 GIF
動(dòng)圖。本文原作者為 Eli Bendersky
,譯者為 唐曉霆 Jason 嗅钻,由編程派 EarlGrey 校對(duì)屿储。
譯者簡(jiǎn)介:唐曉霆,在香港的成都人吠裆,城市大學(xué)研究助理伐谈,會(huì)寫python,興趣是深度學(xué)習(xí)试疙。
這篇短文介紹如何用 Python
里的 matplotlib
畫出 GIF 動(dòng)圖诵棵。下面的代碼我在一臺(tái)安裝了 ImagMagick
的 Ubuntu
機(jī)器上運(yùn)行過。 若想要用 matplotlib
的 save
方法渲染 GIF
動(dòng)圖的話祝旷,就必須安裝 ImageMagick
履澳。
下面給一個(gè)動(dòng)畫樣本:
有幾點(diǎn)需要注意:
- 圖里的散點(diǎn)部分是不變的;變的是直線
- X 軸的標(biāo)題每一幀都在變化
下面上制作該圖的代碼:
import sys
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
fig.set_tight_layout(True)
# 詢問圖形在屏幕上的尺寸和DPI(每英寸點(diǎn)數(shù))怀跛。
# 注意當(dāng)我們把圖形儲(chǔ)存成一個(gè)文件時(shí)距贷,我們需要再另外提供一個(gè)DPI值
print('fig size: {0} DPI, size in inches {1}'.format(
fig.get_dpi(), fig.get_size_inches()))
# 畫出一個(gè)維持不變(不會(huì)被重畫)的散點(diǎn)圖和一開始的那條直線。
x = np.arange(0, 20, 0.1)
ax.scatter(x, x + np.random.normal(0, 3.0, len(x)))
line, = ax.plot(x, x - 5, 'r-', linewidth=2)
def update(i):
label = 'timestep {0}'.format(i)
print(label)
# 更新直線和x軸(用一個(gè)新的x軸的標(biāo)簽)吻谋。
# 用元組(Tuple)的形式返回在這一幀要被重新繪圖的物體
line.set_ydata(x - 5 + i)
ax.set_xlabel(label)
return line, ax
if __name__ == '__main__':
# FuncAnimation 會(huì)在每一幀都調(diào)用“update” 函數(shù)忠蝗。
# 在這里設(shè)置一個(gè)10幀的動(dòng)畫,每幀之間間隔200毫秒
anim = FuncAnimation(fig, update, frames=np.arange(0, 10), interval=200)
if len(sys.argv) > 1 and sys.argv[1] == 'save':
anim.save('line.gif', dpi=80, writer='imagemagick')
else:
# plt.show() 會(huì)一直循環(huán)播放動(dòng)畫
plt.show()
如果你想換一個(gè)更精美的主題漓拾,安裝 seaborn 庫之后添加一行:
import seaborn
然后你就會(huì)得到這個(gè)圖:
提一句關(guān)于文件大小的警告:雖然我在這里分享的 GIF
只有 10 幀阁最,而且圖像也很簡(jiǎn)單戒祠,但是它們每一幀都占大約 160K 。就我理解而言速种,GIF
動(dòng)圖不使用跨幀壓縮姜盈, 所以這使得長(zhǎng)一點(diǎn)的 GIF
占的空間異常大。減少幀數(shù)到最最小并且讓每一幀的圖像小一點(diǎn)(通過在 matplotlib
里調(diào)整圖形尺寸或者 DPI
)哟旗,就可以多多少少幫助緩解一下這個(gè)問題贩据。
EarlGrey:我自己測(cè)試生成的 line.gif 文件大概 86 KB 左右。
說明
我將源碼測(cè)試過闸餐,但是在彈出框中的保存沒有保存為 gif
饱亮。另外,按照代碼中的說明舍沙,這樣操作是可以保存為gif
的
python test.py save
但是之前作者說過近上,需要安裝ImagMagick
,這個(gè)不是python
的包拂铡,是依賴于php
的一個(gè)工具壹无,具體安裝步驟可以見這里【windows下的ImageMagick安裝詳細(xì)過程】,感覺有點(diǎn)麻煩感帅,其實(shí)也可以下載一個(gè)錄屏的軟件斗锭,然后制作為gif就好啦!
另外來自于知乎的 - 【如何用Python實(shí)現(xiàn)動(dòng)態(tài)圖失球? - 帶蘿卜的回答】
import matplotlib.pyplot as plt
import time
def insert_sort(lst):
lsts = []
for i in range(len(lst)):
temp = lst[i]
j = i-1
while j>=0 and lst[j]>temp:
lst[j+1] = lst[j]
j -= 1
lst[j+1] = temp
l = lst[:]
lsts.append(l)
return lsts
if __name__ == "__main__":
lst = [13,32,42,1,53,4,66,2,5,7,74,23]
lsts = insert_sort(lst)
plt.ion()#打開交互模式
fig = plt.figure()#新建繪圖窗口
ax = plt.gca()#獲取當(dāng)前子圖
bars = ax.bar(range(len(lst)),height=lst)#繪制條形圖
for l in lsts:
print(l)
bars.remove()#刪除條形圖
bars = ax.bar(range(len(lst)),height=l)#繪制條形圖
plt.pause(0.5)
while True:#防止圖片關(guān)閉
plt.pause(1)
最上面的主要是用的FuncAnimation()
的功能岖是,設(shè)定幀數(shù),這樣在運(yùn)行代碼的時(shí)候會(huì)一直循環(huán)实苞。這里主要是利用了plt.pause()
這個(gè)方法來讓plt繪圖時(shí)候的暫停豺撑,因?yàn)閳D形中大部分的元素是沒有發(fā)生改變的,所以看起來是連貫的黔牵,如果想要播放的間隔變短聪轿,可以調(diào)整間隔的時(shí)間長(zhǎng)短,但是這種的不能一直循環(huán)猾浦,如果需要的話陆错,可以在while True
的循環(huán)里面加上break
,然后把for
嵌套在while
里面金赦,也實(shí)現(xiàn)了循環(huán)
import matplotlib.pyplot as plt
import time
def insert_sort(lst):
lsts = []
for i in range(len(lst)):
temp = lst[i]
j = i-1
while j>=0 and lst[j]>temp:
lst[j+1] = lst[j]
j -= 1
lst[j+1] = temp
l = lst[:]
lsts.append(l)
return lsts
if __name__ == "__main__":
lst = [13,32,42,1,53,4,66,2,5,7,74,23]
lsts = insert_sort(lst)
plt.ion()#打開交互模式
fig = plt.figure()#新建繪圖窗口
ax = plt.gca()#獲取當(dāng)前子圖
bars = ax.bar(range(len(lst)),height=lst)#繪制條形圖
while True:
for l in lsts:
print(l)
bars.remove()#刪除條形圖
bars = ax.bar(range(len(lst)),height=l)#繪制條形圖
plt.pause(0.5)
while True:#防止圖片關(guān)閉
plt.pause(1)
break