2014年11月29日 星期六

[Matlab] 動畫製作-影片篇

sound_movie

先前我們曾經學過如何製作GIF動畫,但這不夠過癮吧!說到底,GIF也只是會動的圖片而已,而且一定沒有聲音。今天來跟大家介紹幾行動畫生成的指令。

在動畫製作過程中,getframe指令大家應該已經會使用了(用法參考),當我們把所有的畫格取出後,接下來只要輸入下方的程式碼,影片就可以簡單的生成囉!!


程式碼

writerObj=VideoWriter('sound_movie.avi');
open(writerObj);
writeVideo(writerObj,frames);
close(writerObj);

應該很簡單吧,可是生成AVI檔時,會佔有相當大的硬碟容量,我們也可以要求改變影片格式,將其輸出成mp4影片。

writerObj=VideoWriter('sound_movie.mp4',’MPEG-4’);

如果你的影片必須以特定速率撥放時,那就必須設定FrameRate以控制影片撥放速度,設定方法如下:

writerObj.FrameRate=12; %預設值為30,也就是每秒30畫格

簡簡單單幾行就可以做成影片囉!!!


上方影片範例程式碼

%% 參數更改區
%子圖顯示秒數

plot_s=3;

%聲紋圖相關參數
fre=6000;%最高頻率
window=1024;

%版權訊息
copyright1=['製作者:C.Z. Wu'];
copyright2=['http://learning-sky.blogspot.tw/'];
fprintf('-> 參數讀取完成\n');
%% 其他基本參數
%colormap
a=0:0.01:1;a=a'.^5;
z=ones(101,1)-a;
map(:,1)=z;map(:,2)=z;map(:,3)=z;
clear a z
%時刻線
y1=[-1.1;1.1];
y2=[0;fre];
% 資料擷取後的其他參數設定
fs=44100;
recorder = audiorecorder(44100,16,1);
recordblocking(recorder,7); %我只錄7秒鐘,要幾秒可以自行更改
x = getaudiodata(recorder);
t=(0:length(x)-1)/fs;
bar_sec=3;
barline=[max(t)-bar_sec max(t)];
xbar=[-1.12 -1.12];
words=[num2str(bar_sec) ' s']; %製作比例尺說明文字
overlap=floor(window*0.97);% 97%覆蓋率,floor為無條件捨去至整數
  
[S,F,T]=spectrogram(x, 1024, overlap, [], fs);
F_part=0;
ii=1;
while max(F_part)<fre*2
    F_part=F(1:ii,1);
    ii=ii+1;
end

%繪圖開始
j=1;a=1;aa=1;
for i=1:fs/12:length(x) %繪圖間隔與撥放速率可透過fs/12決定
    q=[t(i);t(i)];
    figure (j)
    set(figure(j),'position',[1 1 1280 750],'renderer','painters')
    set(gcf,'color','white')
    subplot(211),plot(t,x);
       axis([0 max(t) -1.3 1.3])
       set(gca,'xcolor',[1 1 1],'ycolor',[1 1 1],'ytick',[],'xtick',[])
       hold on
       plot(barline,xbar,'k','linewidth',3); %畫上時間比例尺,並設定線寬
       text(barline(1)+bar_sec/50,-1.25,words,'FontSize',14,'FontName','Times New Roman'); %幫比例尺上文字
       text(max(t)*1.08,-5.4,copyright1,'HorizontalAlignment','right','FontSize',14,'FontName','Times New Roman')
       text(max(t)*1.08,-5.62,copyright2,'HorizontalAlignment','right','FontSize',14,'FontName','Times New Roman')
       plot(q,y1,'color',[0.7 0 0],'linewidth',0.5);
       hold off
    subplot(223),plot(t,x);
       hold on
       axis([t(i)-plot_s/2 t(i)+plot_s/2 -1.1 1.1])
       plot(q,y1,'color',[0.7 0 0],'linewidth',0.5);
       box off
       hold off
       ylabel('Amplitude','FontSize', 14)
       xlabel('Time (s)','FontSize', 14)
       set(gca, 'FontName', 'Times New Roman','FontSize', 14)
   %聲紋片段
    while T(a)<t(i)-plot_s/2
        a=a+1;
    end
    while T(aa)<t(i)+plot_s/2
        if aa<length(T)
            aa=aa+1;
        else
            break;
        end
    end
    T_part=T(1,a:aa);
    S_part=S(1:length(F_part),a:aa);
   
    subplot(224),pcolor(T_part,F_part(1:end/2)/1000,10*log10(abs(max(S_part(1:length(F_part)/2,:),0.001))));
       shading flat
       xlim([t(i)-plot_s/2 t(i)+plot_s/2])
       colormap(map)
       ylabel('Frequency (Hz)','FontSize', 14)
       xlabel('Time (s)','FontSize', 14)
       set(gca, 'FontName', 'Times New Roman','FontSize', 14)
       box off
       hold on
       plot(q,y2,'color',[0.7 0 0],'linewidth',0.5);
       hold off
    mov(j)=getframe(gcf);
    close all
       
    j=j+1;
end
filename=['sound_movie.mp4'];
writerObj=VideoWriter(filename,'MPEG-4');
writerObj.FrameRate=12;
writerObj.Quality=100;
open(writerObj);
writeVideo(writerObj,mov);
close(writerObj);

若上述程式碼有不懂的可以再問我^^
另外,有高人推薦更好的程式碼請告訴我,感謝!!小弟目前最困擾的是聲音沒辦法同時輸出,只能以後制的方式插入聲音訊號。

3 則留言:

  1. 您好
    若是只要輸出影片不需要聲音檔
    該使用那些code呢
    謝謝

    回覆刪除
    回覆
    1. 程式碼所生成的影片是讀取每一劃格再組成影片,並未加入聲音資訊。而如何將音訊混入影片,可能要看有沒有其他指令可供使用。

      刪除
  2. 請問mp4檔會輸出到哪呢?

    回覆刪除

有任何問題可以詢問,我們會盡量回答