Python有些出色的數據可視化庫,但很少能渲染GIF或視頻動畫。本文介紹如何運用MoviePy作為其他庫的通用動畫插件。
有了 MoviePy ,你可以用一個函數 make_frame(t) 自定義動畫,并返回相應的時間t的視頻幀(秒):
Python123456789101112from moviepy.editor import VideoClip def make_frame(t): """ returns an image of the frame at time t """ # ... create the frame with any library return frame_for_time_t # (Height x Width x 3) Numpy array animation = VideoClip(make_frame, duration=3) # 3-second clip # For the export, many options/formats/optimizations are supportedanimation.write_videofile("my_animation.mp4", fps=24) # export as videoanimation.write_gif("my_animation.gif", fps=24) # export as GIF (slow)在之前的文章中,我用這種方法來做制作矢量圖形動畫(用Gizeh庫),和光線追蹤三維場景(由POV-Ray做出)。這篇文章包括 MayaVi、vispy、matplotlib、NumPy 和 Scikit-image 這些科學庫。
用Mayavi的動畫
Mayavi是一個針對有簡單接口的交互3D數據可視化的Python模塊。在第一個例子中,我們做一個高度隨時間t變化的表面的動畫:
Python12345678910111213141516171819202122import numpy as npimport mayavi.mlab as mlabimport moviepy.editor as mpy duration= 2 # duration of the animation in seconds (it will loop) # MAKE A FIGURE WITH MAYAVI fig_myv = mlab.figure(size=(220,220), bgcolor=(1,1,1))X, Y = np.linspace(-2,2,200), np.linspace(-2,2,200)XX, YY = np.meshgrid(X,Y)ZZ = lambda d: np.sinc(XX**2+YY**2)+np.sin(XX+d) # ANIMATE THE FIGURE WITH MOVIEPY, WRITE AN ANIMATED GIF def make_frame(t): mlab.clf() # clear the figure (to reset the colors) mlab.mesh(YY,XX,ZZ(2*np.pi*t/duration), figure=fig_myv) return mlab.screenshot(antialiased=True) animation = mpy.VideoClip(make_frame, duration=duration)animation.write_gif("sinc.gif", fps=20)另一個例子是一個坐標和觀看角度都隨時間變化的線框網:
Python12345678910111213141516171819202122232425262728import numpy as npimport mayavi.mlab as mlabimport moviepy.editor as mpy duration = 2 # duration of the animation in seconds (it will loop) # MAKE A FIGURE WITH MAYAVI fig = mlab.figure(size=(500, 500), bgcolor=(1,1,1)) u = np.linspace(0,2*np.pi,100)xx,yy,zz = np.cos(u), np.sin(3*u), np.sin(u) # Pointsl = mlab.plot3d(xx,yy,zz, representation="wireframe", tube_sides=5, line_width=.5, tube_radius=0.2, figure=fig) # ANIMATE THE FIGURE WITH MOVIEPY, WRITE AN ANIMATED GIF def make_frame(t): """ Generates and returns the frame for time t. """ y = np.sin(3*u)*(0.2+0.5*np.cos(2*np.pi*t/duration)) l.mlab_source.set(y = y) # change y-coordinates of the mesh mlab.view(azimuth= 360*t/duration, distance=9) # camera angle return mlab.screenshot(antialiased=True) # return a RGB image animation = mpy.VideoClip(make_frame, duration=duration).resize(0.5)# Video generation takes 10 seconds, GIF generation takes 25sanimation.write_videofile("wireframe.mp4", fps=20)animation.write_gif("wireframe.gif", fps=20)因為Mayavi有著強大的ITK可視化引擎,它還可以處理復雜數據集。這里有一個源自于Mayavi例子的動畫
代碼
Animations with Vispy 用Vispy的動畫
Vispy是另一個以OpenGL為基礎的交互3D可視化庫。至于Mayavi,我們用MoviePy先做出一個圖和一個網。
Python12345678910111213141516171819202122232425262728from moviepy.editor import VideoClipimport numpy as npfrom vispy import app, scenefrom vispy.gloo.util import _screenshot canvas = scene.SceneCanvas(keys='interactive')view = canvas.central_widget.add_view()view.set_camera('turntable', mode='perspective', up='z', distance=2, azimuth=30., elevation=65.) xx, yy = np.arange(-1,1,.02),np.arange(-1,1,.02)X,Y = np.meshgrid(xx,yy)R = np.sqrt(X**2+Y**2)Z = lambda t : 0.1*np.sin(10*R-2*np.pi*t)surface = scene.visuals.SurfacePlot(x= xx-0.1, y=yy+0.2, z= Z(0), shading='smooth', color=(0.5, 0.5, 1, 1))view.add(surface)canvas.show() # ANIMATE WITH MOVIEPY def make_frame(t): surface.set_data(z = Z(t)) # Update the mathematical surface canvas.on_draw(None) # Update the image on Vispy's canvas return _screenshot((0,0,canvas.size[0],canvas.size[1]))[:,:,:3] animation = VideoClip(make_frame, duration=1).resize(width=350)animation.write_gif('sinc_vispy.gif', fps=20, opt='OptimizePlus')還有一些更高級的例子(源自于Vispy庫),它是用C代碼片段中嵌入Python代碼,微調了3D渲染的:
代碼
代碼
用Matplotlib的動畫
2D/3D繪圖庫Matplotlib已經有了動畫模塊,但我發現moviepy可以做出更輕量級,質量更好的視頻,卻達到了兩倍的速度(不知道為什么?在這里看到更多細節)。這里有個如何使用matplotlib和moviepy的例子:
Python123456789101112131415161718192021222324import matplotlib.pyplot as pltimport numpy as npfrom moviepy.video.io.bindings import mplfig_to_npimageimport moviepy.editor as mpy # DRAW A FIGURE WITH MATPLOTLIB duration = 2 fig_mpl, ax = plt.subplots(1,figsize=(5,3), facecolor='white')xx = np.linspace(-2,2,200) # the x vectorzz = lambda d: np.sinc(xx**2)+np.sin(xx+d) # the (changing) z vectorax.set_title("Elevation in y=0")ax.set_ylim(-1.5,2.5)line, = ax.plot(xx, zz(0), lw=3) # ANIMATE WITH MOVIEPY (UPDATE THE CURVE FOR EACH t). MAKE A GIF. def make_frame_mpl(t): line.set_ydata( zz(2*np.pi*t/duration)) # <= Update the curve return mplfig_to_npimage(fig_mpl) # RGB image of the figure animation =mpy.VideoClip(make_frame_mpl, duration=duration)animation.write_gif("sinc_mpl.gif", fps=20)Matplotlib有很多漂亮的主題,而且和像Pandas或Scikit-Learn這些數字模塊能很好配合。讓我們看一個SVM分類器,以更好地明白訓練點的數量增加時的地圖。
Python1234567891011121314151617181920212223242526272829303132import numpy as npimport matplotlib.pyplot as pltfrom sklearn import svm # sklearn = scikit-learnfrom sklearn.datasets import make_moonsfrom moviepy.editor import VideoClipfrom moviepy.video.io.bindings import mplfig_to_npimage X, Y = make_moons(50, noise=0.1, random_state=2) # semi-random data fig, ax = plt.subplots(1, figsize=(4, 4), facecolor=(1,1,1))fig.subplots_adjust(left=0, right=1, bottom=0)xx, yy = np.meshgrid(np.linspace(-2,3,500), np.linspace(-1,2,500)) def make_frame(t): ax.clear() ax.axis('off') ax.set_title("SVC classification", fontsize=16) classifier = svm.SVC(gamma=2, C=1) # the varying weights make the points appear one after the other weights = np.minimum(1, np.maximum(0, t**2+10-np.arange(50))) classifier.fit(X, Y, sample_weight=weights) Z = classifier.decision_function(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) ax.contourf(xx, yy, Z, cmap=plt.cm.bone, alpha=0.8, vmin=-2.5, vmax=2.5, levels=np.linspace(-2,2,20)) ax.scatter(X[:,0], X[:,1], c=Y, s=50*weights, cmap=plt.cm.bone) return mplfig_to_npimage(fig) animation = VideoClip(make_frame, duration = 7)animation.write_gif("svm.gif", fps=15)簡單明了,背景色代表分類器辨識黑點和白點屬于哪里。在一開始沒有真正的線索,但隨著更多的點出錢,月牙形分布區域漸漸顯現了。
用Numpy的動畫
如果你正用著Numpy數組(Numpy是一個Python的中央數字庫),你不需要任何外部繪圖庫,你可以直接將這些數組饋入MoviePy。
這通過模擬在法國的僵尸爆發(靈感來自Max Berggren的博客,伯樂在線已有全文翻譯:《用Python在地圖上模擬疫情擴散》)。法國被仿作一個所有分散和感染的計算都完成的網格(NumPy數組)。每隔一段時間,一些NumPy操作變換網格為有效的RGB圖像,并將其發送到Moviepy。
代碼
把動畫放到一起
什么比一個動畫更好呢?兩個動畫!你可以利用MoviePy視頻合成功能,來混合來自不同庫的動畫:
Python123456import moviepy.editor as mpy# We use the GIFs generated earlier to avoid recomputing the animations.clip_mayavi = mpy.VideoFileClip("sinc.gif")clip_mpl = mpy.VideoFileClip("sinc_mpl.gif").resize(height=clip_mayavi.h)animation = mpy.clips_array([[clip_mpl, clip_mayavi]])animation.write_gif("sinc_plot.gif", fps=20)Or for something more artistic:
Python12345678# Make the white color transparent in clip_mayaviclip_mayavi2 = (clip_mayavi.fx( mpy.vfx.mask_color, [255,255,255]) .set_opacity(.4) # whole clip is semi-transparent .resize(height=0.85*clip_mpl.h) .set_pos('center')) animation = mpy.CompositeVideoClip([clip_mpl, clip_mayavi2])animation.write_gif("sinc_plot2.gif", fps=20)也許有點太快了,但有時你必須給你的觀眾一些可以讓他們議論的東西。
你也可以注解動畫,當比較不同的過濾器或算法時,注解動畫很實用。讓我們看看四張由庫scikit-image變換的圖像:
Python1234567891011121314151617181920212223242526import moviepy.editor as mpyimport skimage.exposure as ske # rescaling, histogram eq.import skimage.filter as skf # gaussian blur clip = mpy.VideoFileClip("sinc.gif")gray = clip.fx(mpy.vfx.blackwhite).to_mask() def apply_effect(effect, title, **kw): """ Returns a clip with the effect applied and a title""" filtr = lambda im: effect(im, **kw) new_clip = gray.fl_image(filtr).to_RGB() txt = (mpy.TextClip(title, font="Purisa-Bold", fontsize=15) .set_position(("center","top")) .set_duration(clip.duration)) return mpy.CompositeVideoClip([new_clip,txt]) # Apply 4 different effects to the original animationequalized = apply_effect(ske.equalize_hist, "Equalized")rescaled = apply_effect(ske.rescale_intensity, "Rescaled")adjusted = apply_effect(ske.adjust_log, "Adjusted")blurred = apply_effect(skf.gaussian_filter, "Blurred", sigma=4) # Put the clips together on a 2x2 grid, and write to a file.finalclip = mpy.clips_array([[ equalized, adjusted ], [ blurred, rescaled ]])final_clip.write_gif("test2x2.gif", fps=20)如果我們把CompositeVideoClip和clips_array替代成concatenate_videoclips,我們得到標題效果式動畫:
Python12345678910111213141516171819202122232425import moviepy.editor as mpyimport skimage.exposure as skeimport skimage.filter as skf clip = mpy.VideoFileClip("sinc.gif")gray = clip.fx(mpy.vfx.blackwhite).to_mask() def apply_effect(effect, label, **kw): """ Returns a clip with the effect applied and a top label""" filtr = lambda im: effect(im, **kw) new_clip = gray.fl_image(filtr).to_RGB() txt = (mpy.TextClip(label, font="Amiri-Bold", fontsize=25, bg_color='white', size=new_clip.size) .set_position(("center")) .set_duration(1)) return mpy.concatenate_videoclips([txt, new_clip]) equalized = apply_effect(ske.equalize_hist, "Equalized")rescaled = apply_effect(ske.rescale_intensity, "Rescaled")adjusted = apply_effect(ske.adjust_log, "Adjusted")blurred = apply_effect(skf.gaussian_filter, "Blurred", sigma=4) clips = [equalized, adjusted, blurred, rescaled]animation = mpy.concatenate_videoclips(clips)animation.write_gif("sinc_cat.gif", fps=15)最終,處理視頻數據時,MoviePy會非常好用,因為這是它的首要任務。最后一個例子,我們通過視頻幀閾值和白色像素計數,估計一個細菌種群大小。第三面板顯示,人口規模呈指數增長的時間。
代碼
一個庫就可以做所有動畫了?
我希望給了你足夠的例子,來提升你的同事對你下次展示中的印象??傊妮敵瞿鼙晦D換成Numpy數組,其他的庫也能用MoviePy來做動畫。
一些庫有自己的動畫模塊,但是修復和維護很痛苦!感謝那些在不同背景下測試MoviePy的人們,它變得更穩定了(除非沒人再報bug),而且可以適用于各種環境。MoviePy 仍有很多要去做的,但如果作者開始依靠它來做視頻和GIF渲染,像Pandas和scikit-Learn依賴matplotlib做繪制,那會很好。
為了本文的完整性,同時也為了更好地滿足您的需要,我必須提到的ImageIO,這是另一個可以編寫視頻的Python庫,它專注于提供一個非常簡單的接口來讀取或寫入任何圖像,視頻或容積數據。比如你用imwrite()寫圖像,用mimwrite()寫視頻/ GIF,用volwrite()寫體積數據,或只是write()寫流數據。
作為一名IT從業者,同時也是一名教育工作者,我來回答一下這個問題。
首先,對于31歲的職場人來說,當前學習Python語言對于自身的職場發展會有一定的積極意義,在未來的產業互聯網時代,掌握一門編程技術不僅能夠提升自身的工作效率,同時也會為自己帶來更強的資源整合能力。
但是,如果在31歲時希望通過學習Python語言而進入IT(互聯網)行業發展,那么還是需要慎重考慮的。Python語言雖然是全場景編程語言之一,而且在IT行業內也有比較高的流行程度,但是Python開發的高附加值工作崗位往往集中在大數據和人工智能領域,而這兩個領域對于從業者的要求還是比較高的。所以,如果自身的數學基礎比較扎實,同時又具有較強的學習能力,那么在31歲開始學習Python也會有一定的機會。
IT行業對于從業者的年齡還是比較敏感的,尤其是應用級開發崗位往往年齡越小則競爭力越強,所以31歲如果應聘初級開發崗位還是具有一定困難的。但是,如果掌握新技術,比如大數據、云計算等技術,即使年齡大一些也會有一定的競爭力。
從目前產業互聯網發展的大趨勢來看,如果職場人能夠在立足本行業的基礎上,通過掌握新技術來解決一些傳統行業的“痛點”,那么會獲得一些新的發展機會。在具體的崗位選擇上,除了程序員崗位之外,還可以重點考慮一下產品經理、項目經理等崗位,這些崗位通常對于年齡并不十分敏感。
最后,如果想在31歲進入IT行業發展,還可以考慮一下通過讀研的方式進入IT行業。
我從事互聯網行業多年,目前也在帶計算機專業的研究生,主要的研究方向集中在大數據和人工智能領域,我會陸續寫一些關于互聯網技術方面的文章,感興趣的朋友可以關注我,相信一定會有所收獲。
如果有互聯網、大數據、人工智能等方面的問題,或者是考研方面的問題,都可以在評論區留言,或者私信我!
小朋友思想挺超前的,我接觸編程也是在初三的時候,高一才真正開始學編程,當時我學的是vbs,bat這兩門,到后來才接觸高級語言,python是第四代語言,擁有面向對象開發,最大的特點就是簡單,這里的簡單是指入門簡單,不要產生誤解了,想學會一點都不難,您所說的學好就比較有難度了。開始學習基礎只有幾個重點,一些基本語法,和面向對象開發過程。學完這些就算入門了,之后呢,還有大量的庫需要了解,如果學爬蟲需要了解requests,bs4,等等。除此之外還有:Web框架、網絡爬蟲、網絡內容提取、模板引擎、數據庫、數據可視化、圖片處理、文本處理、自然語言處理、機器學習、日志、代碼分析等。能夠把這些能夠熟練掌握基本上算是大神了,不要認為python是一門簡單的語言,還是那句話學會簡單,學好難。你現在五年級還是要以學業為主,把編程當做興趣固然可以,如果影響了學習就得不償失了。過來人奉勸一句,這個真的有點影響學習,有時候會因為一個小小的問題困惑很久,期間會錯過課堂上的學習。小學最好學習思維而不是學習編程。
還反駁啥??!自學python別的都不會,本來就沒啥前途。不信出去應聘試試,大廠考各種算法直接問蒙。小廠各種瑣碎需求,開荒種地也應付不來。沒看現在頭條上python都往量化投資上掛嘛!就是在編程圈不好混,才跨界發展呢!在頭條上搜搜看看講python有幾個正經搞開發的,國內python都快成培訓行業的專用語言了。上至成人下至兒童忽悠個便!熱愛編程是一回事,用編程養家糊口是另一回事。登月大家只能記住阿姆斯特朗,誰知道背后的那些科學家都叫啥?編程開發也是這樣,大家只知道今日頭條。背后的寫算法的那些人沒人了解!反駁同學無非就是證明自己的觀點,讓自己更有尊嚴。這和編程語言有啥關系?要是真熱愛編程當初上學就應該選擇相關的專業。在自己本專業里用心學得了,在配合編程知識輔助自己才是正道。