今天的推文,我們主要來介紹matlab中幾種繪製動態圖像的方法。首先,以之前介紹過的心形圖為例,來說明在matlab中如何將繪圖過程保存為gif動態圖像。
1. Matlab繪製GIF圖像Step1:生成三維心形線坐標,三維空間下的心形線方程為:為了求解滿足該方程所有點坐標,首先定義了在xyz坐標軸上[-3,3]範圍內分別取101個點,用meshgrid得到101*101*101的三維網格點數據,計算每個網格點上函數的取值val,所有val為0的點即為心形線坐標點。Step2:在YOZ平行平面上繪製心形線,令X取定值,提取該平面上所有val取值為0的網格點(Y,Z)坐標,繪製心形線。在這裡,提取val為0的點,通過提取等值線來實現,(Y,Z)=contourc(val(:,X,:),[0,0]),具體這部分matlab代碼為:for X = 35:67 %提取不同X取值下,與YOZ平行的平面上,f(y,z)取值 plane = reshape(val(:,X,:),101,101); %提取val為0的等值線,即滿足f(y,z)=0的坐標點 c_data = contourc(plane,[0,0]); x_data = X*ones(1,c_data(2,1)); %繪製在YOZ平行平面上的心形線 plot3(x_data,c_data(2,2:end),c_data(1,2:end),'r'); axis([30,80,30,80,30,80])axis offEndStep3:將圖像保存為gif文件,在matlab可以使用imwrite將圖像保存為gif,但需要將圖像數據保存為索引圖像。其中,保存第一張圖像時,需要創建gif文件,之後的圖像全部採用append的方式進行添加即可。保存gif文件的基本框架為:pic_index = 1;%記錄圖像編號for i = 1:end plot(data(i)); %抓取當前的figure,保存為rgb圖像後,再轉化為索引圖像 [A,map] = rgb2ind(frame2im(getframe),256); if pic_index == 1 imwrite(A,map,'test.gif','gif','Loopcount',inf,'DelayTime',0.2); else imwrite(A,map,'test.gif','gif','WriteMode','append','DelayTime',0.2); end pic_index = pic_index + 1;end其中,getframe是為了抓取當前繪製的圖像,frame2im函數將當前圖形保存為rgb圖像,rgb2ind函數將rgb圖像保存為索引圖像。所謂索引圖像是指一個數據矩陣A,一個顏色映像矩陣Map。其中Map是一個包含三列、若干行的數據陣列,其中每個元素的值均為[0, 1]之間的雙精度浮點型數據。Map矩陣的每一行分別表示紅色、綠色和藍色的顏色值。在MATLAB中,索引圖像是從像素值到顏色映射表值的「直接映射」。像素顏色由數據矩陣X作為索引指向矩陣Map進行索引,例如,值1指向矩陣Map中的第一行,值2指向第二行,以此類推。索引圖像的使用解決了圖像數據矩陣消耗內存過大的問題,rgb圖像需要一個三維數據矩陣才可以表示,索引圖像只需要一維數據矩陣和一個map就可以表示了。Setp4:同理,繪製XOY平行平面和XOZ平面的心形線,並繼續保存到gif文件中即可。2. Matlab創建動畫線條我們在繪製動態圖像的目的一般是為了展示圖像的繪製過程,或者是為了在串行獲取數據時,實時展示圖像。為了實現實時繪圖的動畫,我們需要藉助於matlab中的animatedline函數(注意:這是matlab在2014a版本之後才才更新的一個函數,2014a包括2014a之前版本的matlab都不能實現這個功能)。an = animatedline 創建一根沒有任何數據的動畫線條並將其添加到當前坐標區中;
an = animatedline(x,y) 創建一根包含由 x 和 y 定義的初始數據點的動畫線條;
an = animatedline(x,y,z) 創建一根包含由 x、y 和 z 定義的初始數據點的三維動畫線條;
an = animatedline(___,Name,Value) 使用一個或多個名稱-值對組參數指定動畫線條屬性。例如,'Color','r' 將線條顏色設置為紅色。
當然,animatedline創建了一個動畫線條,為了讓這個線條動起來,我們需要給它繼續添加坐標點,這裡就需要用到addpoints函數。addpoints(an,x,y) 向動畫線條an中,添加二維點;
addpoints(an,x,y,z) 向動畫線條an中,添加三維點。
h = animatedline('Color','r','LineWidth',3);for k = 1:length(x) addpoints(h,x(k),y(k)); end基於這兩個函數,就可以完成上圖的動態繪圖效果了,結合第一節中介紹的gif文件保存方式,我們還可以將繪圖過程輸出為gif文件。t = 0:0.1:2*pi;x = 16*(sin(t)).^3;y = 13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t);axis off;set(gcf,'color',[1 1 1]);[A,map] = rgb2ind(frame2im(getframe),256);imwrite(A,map,'xin2.gif','LoopCount',65535,'DelayTime',0.1);h = animatedline('Color','r','LineWidth',3);for k = 1:length(x) addpoints(h,x(k),y(k)); axis([-20,20,-20,20]) [A,map] = rgb2ind(frame2im(getframe),256); imwrite(A,map,'xin2.gif','WriteMode','append','DelayTime',0.1);end3. Matlab動畫循環播放Movie函數可以實現電影動畫,一次運行結果可以保存起來進行多次播放,同時可以生成avi視頻文件,獨立於matlab進行使用。在進行movie函數創建動畫之前,需要用moviein函數保存繪製的圖形數據,創建一個足夠大的矩陣,使之能夠容納基於當前繪製的圖形(此處稱為幀)。當創建了一系列的動畫幀後,可以利用movie函數按照指定的速度和次數運行該電影動畫。movie函數的調用格式為:movie(M) 將矩陣M中的動畫幀播放一次;
movie(M,n) 將矩陣M中的動畫幀播放n次;
movie(M,n,fps) 將矩陣M中的動畫幀以每秒fps幀的速度播放n次。
接下來,我們以三維曲面的動態變化為例,展示一下movie函數效果。x = -6:0.1:6;y = -6:0.1:6;[X,Y] = meshgrid(x,y);r = sqrt(X.^2 + Y.^2);Z = sin(r)./(r + eps);p = surf(X,Y,Z);set(p,'LineStyle','None');axis([-6,6,-6,6,-1,1])%axis off%theAxes = axis;M = moviein(20);filename = '動畫.gif';for j = 0.1:0.1:10 p = surf(X,Y,sin(j*pi)*Z); axis([-6,6,-6,6,-1,1]) axis off; set(p,'LineStyle','None'); M(:,end+1) = getframe; %輸出為gif [A,map] = rgb2ind(frame2im(getframe),256); if j == 0.1 imwrite(A,map,filename,'gif', 'Loopcount',inf,'DelayTime',0.1); else imwrite(A,map,filename,'gif','WriteMode','append','DelayTime',0.1); endend%循環2兩次顯示動畫movie(M,2)本文介紹了幾種關於matlab繪製動畫的基本函數,在這些基本的函數基礎上,可以結合圖像處理技術還可以做出更多豐富的動畫特效,這些內容可以在之後的推文中慢慢了解。