plotyy,Python如何实现数据动态化?
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会非常好用,因为这是它的首要任务。最后一个例子,我们通过视频帧阈值和白色像素计数,估计一个细菌种群大小。第三面板显示,人口规模呈指数增长的时间。
代码
一个库就可以做所有动画了?
我希望给了你足够的例子,来提升你的同事对你下次展示中的印象。总之要他的输出能被转换成Numpy数组,其他的库也能用MoviePy来做动画。
一些库有自己的动画模块,但是修复和维护很痛苦!感谢那些在不同背景下测试MoviePy的人们,它变得更稳定了(除非没人再报bug),而且可以适用于各种环境。MoviePy 仍有很多要去做的,但如果作者开始依靠它来做视频和GIF渲染,像Pandas和scikit-Learn依赖matplotlib做绘制,那会很好。
为了本文的完整性,同时也为了更好地满足您的需要,我必须提到的ImageIO,这是另一个可以编写视频的Python库,它专注于提供一个非常简单的接口来读取或写入任何图像,视频或容积数据。比如你用imwrite()写图像,用mimwrite()写视频/ GIF,用volwrite()写体积数据,或只是write()写流数据。
matlab2014a图形坐标怎么改变?
1、首先做一条自动生成的图形;plot(randn(100,1));可以看到图形中坐标轴已经有了自动生成的标注。
2、使用axis命令可以自行修改坐标轴的范围。如:axis();可以看到坐标轴又自行发生了变化,怎样进行修改呢?
3、这里会牵扯到两个值,gcf和gca;这里需要说明gcf表示的是整个图形,包括上面的工具栏等等;而gca只是代表了其中的坐标轴及内部的数据。set(gca,'Xtick',,'Ytick',,'fontsize',20);在修改了标注之后,顺便还修改了字体大小。
4、当然也可以修改标注的字:set(gca,'Xticklabel',{'xx','yy','zz'},'Yticklabel',{'aa','bb'});需要注意的是,标签和上面的数量要一一对应。
5、还可以修改字体和字体的方向。set(gca,'XTickLabelRotation',45)。
6、除了使用命令修改,还可以进行手动修改。进入“显示绘图工具和停靠图形”界面后,选中坐标轴,在坐标轴的属性中有刻度属性,可以根据要求自行修改。
matlab怎么求散点密度?
您可以使用MATLAB中的kde2函数来计算散点密度。以下是一个简单的示例:
x = randn(100,1); % 生成100个随机数
y = randn(100,1); % 生成100个随机数
xy = [x, y]; % 将两个向量合并成一个矩阵
kde = kde2(xy); % 计算二维核密度估计
plot(xy(:,1),xy(:,2),'.','MarkerSize',8); % 绘制散点图
hold on; % 保持当前图形
plot(kde(:,1),kde(:,2),'r'); % 绘制核密度估计曲线
hold off; % 关闭保持模式
```
Python闭包有什么作用?
python支持过程式,函数式和面向对象的的编程
Python是一种优秀的编程语言,可以支持过程式,函数式和面向对象的的编程并开发几乎任何东西。 在编写代码和使用某些基础架构时,你需要扩展重用而不去动原始代码。 在面向对象编程中,靠继承来实现,但如果用过程式编程则,需要函数装饰器。
函数即对象在python中,函数就是对象,你可以实时创建函数,将函数发送到另一个函数并从另一个函数返回函数。 使用lambda表达式容易实现这个功能。
例如,使用lambda表达式创建一个函数并将其发送给另一个函数:
from __future__ import print_function
def cc(fn):
print("**************")
fn()
print("*************")
f1 = lambda : print("Hello ChongChong!");
cc( f1 )
注意第一句“from __future__ import print_function” 为了兼容2.x的语法,让其支持print当成函数来使用。
输出为:
*************
Hello ChongChong!
*************
内部函数
是用内部函数可以让你更好的理解函数即对象。我们可以声明一个内部函数并动态返回一个函数。
例如,比我们计算一个斐波那契数列,计算1到20的数列值,函数可以用迭代地或递归来做,并且我们希望在运行时选择该方法。 我们也可以使用一个内部函数,不对外访问(在这个例子中是checkn)
def fibf(i):
def checkn( n ):
return n == 0 or n == 1
def addfib( n ):
if checkn( n ):
return n
a, b = 0, 1
for item in range(0, n-1):
b = a + b
a = b - a
return b
def morefib( n ):
if checkn( n ):
return n
return morefib( n-1 ) + morefib( n-2 )
if i == 0:
return addfib
return morefib
fib = fibf( 1 )
for i in range(1,20):
print( fib(i) )
在这个例子中,我们可以使用带参数的fibf来实现我们需要的功能。
结果:
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
闭包(Closure)我们可以动态地返回一个内部函数,并且将并根据我们在外部函数中得到的参数赋值给他。 举个简单加法器的例子:
def add( i ):
def fun( j ):
return i + j
return fun
f1=add(10)
f2=add(5)
print ( f1(2) )
print ( f2(2) )
两次调用中,可以根据不同函数,就赋给内部函数不同的基准值j,就好像两个函数一样,而且每次调用都能保存这个基准值,互不干涉,就像是把函数执行和数据打成一个包一样,所以,把这种机制叫做闭包。
闭包的作用闭包在支持函数式语言中广泛使用比如perl,js,java等都有使用。
闭包的一个作用就是实现编程模式里面的工厂模式,非常有用。
我们再组个例子,这个例子来源于网络。如果我们有一组点(x,y),我们用想要插值法生成一个曲线,并画出图来,用来预测y值:
from scipy.interpolate import interp1d
from pylab import plot, axis, legend, scatter
import numpy as np
x = np.array( [10,13,16,22,28,30,32,35,39,44] )
y = np.array( [90,120,170,210,290,300,330,370,390,410] )
scatter(x, y)
则,可以使用interp1d函数来生成函数:
interfn = interp1d(x, y, kind = 3)
yy = interfn(25)
print(yy)
答案为:
253.42
spline函数的原理?
spline是样条曲线数据插值函数,用法:yy = spline(x,Y,xx),x和Y是原矢量,xx是要求各点位置矢量,yy是生成的新值。画图可用:plot(xx,yy)
该命令用三次样条插值计算出由向量x 与y 确定的一元函数y=f(x)在点xx 处的值。若参量y 是一矩阵,则以y 的每一列和x 配对,再分别计算由它们确定的函数在点xx 处的值。则yy 是一阶数为length(xx)*size(y,2)的矩阵。
还没有评论,来说两句吧...