目前已有许多绘制gif动图的matlab代码,但是绘图程序和动图程序杂糅在一起,更换不同图像绘制动图时使用较为不便。此外,由于涉及保存图像操作,动图程序往往运行较慢。
本文将绘图程序和动图程序模块化封装并设计接口,使用时仅需更换不同的绘图程序即可实现不同的动图绘制;使用并行循环parfor提高程序运行速度。
绘制动图的基本思路是用循环绘制动图的每一帧,然后拼接成GIF。
以下是动图函数,其中N是绘图数据的总长度。在循环中,只有当i是speed的整数倍时才绘制图像以降低运行时间。
% 输入:播放速度倍数,绘图数据长度,绘图函数,保存地址,动图名称
% 绘图函数:输入i,绘制0~i的数据图
function dongTuGif(speed, N, plotFun, adress, GifName)
% parpool(4);
%% 生成图片
parfor i = 1: N
if mod(i, speed) == 0 || i == 1
feval(plotFun, i)
drawnow
numPicture = floor(i/speed)+1;
print([adress,num2str(numPicture)],'-dpng'); %保存图片
end
end
%% 提取图片并串联为gif
delay = 0.05; %图片之间延迟
for i = 1:floor(N/speed)+1
A = imread([adress,num2str(i),'.png']); %读取图片
[X, map] = rgb2ind(A, 256); %彩色图像转化成索引图像
if i == 1
imwrite(X, map, GifName, 'gif', 'LoopCount', inf, 'DelayTime', delay)
else
imwrite(X, map, GifName, 'gif', 'WriteMode', 'append', 'DelayTime', delay)
end
% if i > floor(N/speed)-2
% imwrite(X, map, GifName, 'gif', 'WriteMode', 'append', 'DelayTime', delay+0.8)
% end
end
end
使用parfor虽然能提高运行速度,但有时有一些莫名其妙的报错,我不太懂。大家使用的时候如果遇到奇怪的报错,可以把parfor改成for。关于时间间隔delay的选取,一般保证每秒15~20帧即可。
对绘图函数的接口要求为:对于给定输入i,绘图函数将绘制从数据1到数据i的图像。随便写一个绘图函数:
function plotMyFun(kk)
t = 0: 0.1: 100;
x = cos(2*pi*t/100);
y = sin(2*pi*t/100);
z = 0.2*sin(2*pi*t/25);
figure(1);
% 画一条轨迹
plot3(x(1:kk), y(1:kk), z(1:kk), 'linewidth', 2);
xlabel('x');ylabel('y');zlabel('z');
hold on;
% 画一个球
[X, Y, Z] = sphere;
R = 0.1;
surf(x(kk) + R*X, y(kk) + R*Y, z(kk) + R*Z, 'facecolor', "#5690dd");
axis equal;
grid on;
hold off;
view(-19, 21);
xlim([-1.5 1.5]);
ylim([-1.5 1.5]);
zlim([-0.5 0.5]);
end
调用示例如下。运行前请提前新建文件夹,代码不能自己建文件夹。运行时在address中保存每帧图像,在程序的同一目录保存gif。
close all;
clear; clc;
address = 'Y:\File\matlab\drawGIF\secondGroup\pic3\picture';
GifName = 'pic3.gif'; %动图名字
speed = 5;
dongTuGif(speed, 1001, @plotMyFun, address, GifName);
运行结果: