matlab r2012a关于movie命令的问题
[x y z]=peaks(50);surfl(x,y,z);axis([-10 10 -10 10 -10 10]);axis vis3d offaxis equalshading interpcolormap(copper)for i=1:360 view(-37.5+i,30); m(i)=getframe;endcla
然后这样就创建了m,然后movie(m),只能出现一个空白左右晃动的二维坐标图
然后在getframe之前添加set(gcf,'renderer','zbuffer');
得到的事一个边旋转边左右平移的动画, 展开
网上有很多人用getframe和movie实现动画的,有的还把动画写入GIF文件,但真正搞明白getframe和movie用法的人好像并不多,大多数只是找来一段代码,稍加改动就用了,而对出现一些看起来有些奇怪的现象并未深究。
结合题主这个问题,我把相关的知识点稍微总结一下,供后来者参考。
1、首先应该搞明白getframe函数的用法。
很多人直接用getframe,还有人用getframe(1),但似乎都没有认真考虑,这样做得到的结果是什么。getframe的基本调用方式有以下几种:
F = getframe
F = getframe(h)
F = getframe(h,rect)
第2种调用是比较规范的做法,可以通过句柄h指定要捕获的帧是坐标系(axes)或是绘图窗口(figure),而第1种用法省略了参数h,则默认的为当前坐标系,也就是相当于getfram(gca)。至于第3种调用,可以指定捕获特定的矩形区域,不是很常用,这里就不说了。
题主的代码里用的是第1种调用方式,这种方式是对当前坐标系操作的。需要特别注意:捕获的帧不包括坐标系的标题、坐标轴标识以及刻度标识(the contents of the current axes, exclusive of theaxis labels,title, ortick labels),换言之,也就是坐标系中由Color属性决定颜色(默认为白色)的那部分区域。对二维图而言,一般不会有太大问题;但对三维图而言,由于不同的视角会导致该部分区域大小发生变化,所以,getframe得到的不同帧的大小可能是不同的。
题主得到上述奇怪结果的原因正在于此。由于循环过程中不断切换视角,三维图在屏幕上投影的区域也在变化,这样导致最终获取的数据各帧大小不一,而用movie播放时的基准是相对于左下对齐,所以就会看到【边旋转边左右平移的动画】。关于这一点,如果题主把axis vis3d off
最后的off去掉,能看的更清楚一些。
解决这个问题的做法是,捕捉帧的时候要对figure进行操作,也就是getframe(gcf),这样能保证捕捉的帧大小一致。上面说到,有人用getframe(1),很可能是没有搞明白这个参数“1”是什么意思,否则没理由句柄不用gcf而直接指定1,因为谁能保证运行程序时就没有别的绘图窗口存在?
但按照上面说的改了之后,又会出现新问题:用movie函数播放的时候发现动画整体上向右上偏移了一段距离。这就涉及到下一个话题——movie函数的使用。
2、关于movie函数的用法。这个看起来很简单,一般直接movie(m)就可以了,了解多一点的还知道可以指定播放次数n以及帧速fps:
movie(M)
movie(M,n)
movie(M,n,fps)
但有一种用法通常会被忽略:
movie(h,...)
也就是,在前面的基本调用格式之前,增加了一个参数,可以指定播放是在绘图窗口或者坐标系中进行。如果省略了句柄h,则播放是在当前坐标系中进行的,这也就是刚才说到偏移的原因。
3、知道了上面两点,要想避免题主说到的问题,可采取的做法是:getframe捕获帧的时候针对figure进行,播放的时候也相对figure进行。
参考代码:
[x y z]=peaks(50);
surfl(x,y,z);
axis([-10 10 -10 10 -10 10]);
axis vis3d off
axis equal
shading interp
colormap(copper)
clear m
for i=1:360
view(-37.5+i,30);
m(i)=getframe(gcf);
end
movie(gcf,m)
4、这一句:set(gcf,'renderer','zbuffer'),似乎并无必要。在多数环境下,三维图的默认render是opengl,偶尔会出现渲染问题,但也和题主所说的这种现象无关,遇到问题再改吧。