フィルターのクリア

How do I export an animated figure to some video format for use in a presentation?

86 ビュー (過去 30 日間)
Daniel
Daniel 2023 年 2 月 21 日
回答済み: Kevin Holly 2023 年 3 月 23 日
With code adapted from other help threads, I have an animated figure which plays a video (about 20 sec) in one subplot while simultaneously plotting associated data in the next subplot. I run the code in Live editor (and just normally, for that matter) and the figure works perfectly.
How do I get this animated figure into a video file of some kind for use in a presentation? (code below)
Incidentally, the live editor includes a small export button at the bottom right of the figure, but this seems to freeze the code and I only get a blank gray section when I click it. (pics)
%setup subplots
ax1 = subplot(2,1,1); % For video
ax2 = subplot(2,1,2); % For data plot
%setup videoreader object
CH47Landing = 'D:\Manual Backup\PROJECTS\Ice\Engineer Lake\Landing.mp4';
v = VideoReader(CH47Landing);
nFrames = v.Duration*v.FrameRate; % Number of frames
% Display the first frame in the top subplot
vidFrame = readFrame(v);
image(vidFrame, 'Parent', ax1);
ax1.Visible = 'off';
%Load Data
lt = TIMESTAMP; %use your actual data
y = ld5;
nDataPoints = length(lt); % Number of data points
step = 0.033; % Increase this value to get a higher plot rate
index = 1:step:nDataPoints;
i = 2;
% Diplay the plot corresponds to the first frame in the bottom subplot
h = plot(ax2,lt(1:floor(index(i))),y(1:floor(index(i))),'-k');
%Fix the Axes
ax2.XLim = [lt(1) lt(end)];
ax2.YLim = [min(y) max(y)];
%Animate
while hasFrame(v)
pause(1/v.FrameRate);
vidFrame = readFrame(v);
image(vidFrame, 'Parent', ax1);
ax1.Visible = 'off';
i = i + 1;
set(h,'YData',y(1:floor(index(i))), 'XData', lt(1:floor(index(i))))
subplot(2,1,1)
xlim([1 1921])
ylim([1 925])
subplot(2,1,2)
set(gca, 'YDir','reverse')
ylabel('Deflection (mm)')
xticklabels({'12:02:00 PPM','12:02:15 PM','12:02:29PM'})
title('CH47; 31Jan23; h(i)=70cm; AirT=18°F. PT=#5')
xlim([datetime(2023,2,16,12,2,0)...
datetime(2023,2,16,12,2,40)])
ylim([0 15])
end

採用された回答

Kevin Holly
Kevin Holly 2023 年 3 月 23 日
Daniel,
Please see the files attached and the code below. Saving the video should be faster when the figure's "Visible" property is set to "off" and when running it on a .m script instead of the Live Script.
Setup Figure
figure("Visible","off")
tiledlayout(2,1)
%setup subplots
ax1 = nexttile; % For video
ax2 = nexttile; % For data plot
%setup videoreader object
CH47Landing = 'xylophone.mp4';
v = VideoReader(CH47Landing);
nFrames = v.Duration*v.FrameRate; % Number of frames
% Display the first frame in the top subplot
vidFrame = readFrame(v);
image(vidFrame, 'Parent', ax1);
ax1.Visible = 'off';
%Load Data
lt = seconds(v.CurrentTime:1/v.FrameRate:v.NumFrames/v.FrameRate); %Note, this video is in seconds, so datetime was not used
y = rand(v.NumFrames,1)*15;
nDataPoints = length(lt); % Number of data points
step = 0.033; % Increase this value to get a higher plot rate
index = 1:step:nDataPoints;
ii = 2;
% Diplay the plot corresponds to the first frame in the bottom subplot
h = plot(ax2,lt(1:floor(index(ii))),y(1:floor(index(ii))),'-k');
%Fix the Axes
ax2.XLim = [lt(1) lt(end)];
set(gca, 'YDir','reverse')
ylim(ax2,[0 15])
title('CH47; 31Jan23; h(i)=70cm; AirT=18°F. PT=#5')
ylabel(ax1,'Deflection (mm)')
Save one frame at a time
vsave = VideoWriter('SavedFilebyFrame','MPEG-4');
h = plot(ax2,lt(1:floor(index(ii))),y(1:floor(index(ii))),'-k');
% lt = datetime(lt,'ConvertFrom','datenum','Format','HH:mm:ss.SSS');
open(vsave)
%Animate
while hasFrame(v)
vidFrame = readFrame(v);
image(vidFrame, 'Parent', ax1);
ax1.Visible = 'off';
ii = ii + 1;
set(h,'YData',y(1:floor(index(ii))), 'XData', lt(1:floor(index(ii))))
xlim(ax2,[0 max(h.XData)])
ylabel(ax1,'Deflection (mm)')
img = getframe(gcf);
writeVideo(vsave,img.cdata)
end
close(vsave)
Save entire video at once
Create 4D matrix of video
ii=0;
v = VideoReader(CH47Landing);
lt = 1/v.FrameRate:1/v.FrameRate:v.NumFrames*v.FrameRate;
while hasFrame(v)
ii = ii + 1;
vidFrame(:,:,:,ii) = readFrame(v);
end
Write video
figure("Visible","off")
vsave = VideoWriter('SavedFile','MPEG-4');
h = plot(ax2,lt(1:floor(index(ii))),y(1:floor(index(ii))),'-k');
% lt = datetime(lt','ConvertFrom','datenum','Format','HH:mm:ss.SSS');
open(vsave)
for ii = 1:v.NumFrames
% pause(1/v.FrameRate);
image(vidFrame(:,:,:,ii), 'Parent', ax1);
ax1.Visible = 'off';
set(h,'YData',y(1:floor(index(ii))), 'XData', lt(1:floor(index(ii))))
xlim(ax2,[0 max(h.XData)])
img = getframe(gcf);
writeVideo(vsave,img.cdata);
end
close(vsave)

その他の回答 (2 件)

Anton Kogios
Anton Kogios 2023 年 2 月 22 日
編集済み: Anton Kogios 2023 年 2 月 22 日
In your while loop, at the end add
vid(i) = getframe(gcf);
and then at the end of the script add
v = VideoWriter('recordedAnimation,'MPEG-4');
open(v)
for i = 1:length(vid)
writeVideo(v,vid(i))
end
close(v)
You may have to modify the above code since I cannot test it given you haven't provided the Landing.mp4 video. There is plenty of helpful documention if you search this topic up on Google. This may also help: https://mathworks.com/matlabcentral/answers/455886-how-to-save-animated-plots
  7 件のコメント
Daniel
Daniel 2023 年 3 月 1 日
Ok looks like this outputs the Matlab figure which plays the video, but then it does not plot the data or output a video file.
Anton Kogios
Anton Kogios 2023 年 3 月 1 日
編集済み: Anton Kogios 2023 年 3 月 1 日
This should be at the very end, outside the for loop (the while loop in your code above):
v = VideoWriter('recordedAnimation','MPEG-4');
open(v)
for i = 1:length(vid)
writeVideo(v,vid(i))
end
close(v)
And this should be before the for loop (the while loop in your code above):
vid(1:990) = struct('cdata',zeros(420,560,3,'uint8'),'colormap',[]);
It may be best if you start with a simple example first and get that to work. You should also read the documentation I mentioned in my first answer so you know what the code is actually doing, rather than copy-pasting what I say at the incorrect locations.

サインインしてコメントする。


Simon Chan
Simon Chan 2023 年 2 月 22 日
  1 件のコメント
Daniel
Daniel 2023 年 3 月 1 日
I would definitely be fine with that option. The difficulty I think is that there is a video in the script already, and I am not sure how to handle that. If it were a simple matter of animating a plotting function or something, it might be easier, but I need this video in the output as well.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeAudio and Video Data についてさらに検索

製品


リリース

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by