Using movie to record subplot frames in for loop

11 visualizzazioni (ultimi 30 giorni)
Hi Mathworks,
I have the following code:
N1=rand(121,20e3);
X1=rand(1,121);
Y1=rand(1,121);
Z1=rand(1,121);
N2=rand(121,20e3);
X2=rand(1,121);
Y2=rand(1,121);
Z2=rand(1,121);
dt=100;
for i=1:dt:length(N1)
ax=gca
subplot(1,2,1);
ax=gca;
cmap=N1(:,i)';
hAxes=scatter3(X1,Y1,Z1,50,cmap,'filled');
title(strcat('Time = ',num2str(i*0.1),' ms'));
colorbar;
caxis(ax,[0 1]);
subplot(1,2,2)
ax2=gca
cmap2=N2(:,i)';
hAxes2=scatter3(X2,Y2,Z2,50,cmap2,'filled');
title(strcat('Time = ',num2str(i*0.1),' ms'));
colorbar;
caxis(ax2,[0 1]);
drawnow
end
It generates some subplots that update at each iteration of the FOR loop. Crucially the colorbars do not change their MIN and MAX on each iteration.
How do I record this into a movie?
I have tried creating a structure F and using movie(F) but it doesn't seem to work.
Thanks! Linford
PS also any clues on how better to have a "time = " updating during the movie would be really appreciated!
  1 Commento
Jan
Jan il 31 Gen 2017
Please post the code for teh creatrion of the struct F and explain, what "doesn't seem to work" exactly means. It is easier to suggest an improvement than to guess, what you have done and which problem occurred. :-)
Concerning a "better" way to display the time: What do you see as drawback currently?

Accedi per commentare.

Risposta accettata

Jan
Jan il 31 Gen 2017
Modificato: Jan il 2 Feb 2017
% [EDITED] Updated version, 31-Jan-2017 16:19:11 UTC]
FigH = figure;
ax1 = subplot(1, 2, 1, 'NextPlot', 'add'); % as: hold on
colorbar;
caxis(ax1,[0 1]);
t1 = title('dummy');
view(ax1, 3);
ax2 = subplot(1, 2, 2, 'NextPlot', 'add'); % as: hold on
colorbar;
caxis(ax2,[0 1]);
t2 = title('dummy');
view(ax2, 3);
dt = 100;
nFrame = numel(1:dt:length(N1)); % [EDITED]
F(nFrame) = struct('cdata',[],'colormap',[]);
ScatterH1 = [];
ScatterH2 = [];
iFrame = 0;
for i = 1:dt:length(N1)
if ~isempty(ScatterH1) % Clean up former objects
delete(ScatterH1); % Alternative: Update the 'CData' only
delete(ScatterH2);
end
cmap=N1(:,i)';
ScatterH1 = scatter3(X1,Y1,Z1,50,cmap,'filled', 'Parent', ax1);
set(t1, 'String', sprintf('Time = %.1f ms', i*0.1)); % [EDITED]
cmap2=N2(:,i)';
ScatterH2 = scatter3(X2,Y2,Z2,50,cmap2,'filled', 'Parent', ax2);
set(t2, 'String', sprintf('Time = %.1f ms', i*0.1)); % [EDITED]
drawnow
iFrame = iFrame + 1;
F(iFrame) = getframe(FigH); % Not i, because this steps in dt
end
figure;
MovieSize = [size(F(1).cdata, 2), size(F(1).cdata, 1)];
AxesH = axes('Visible', 'off', 'Units', 'pixels', ...
'Position', [10, 10, MovieSize]);
movie(AxesH, F);
I runtime matters, create the scatter3 objects once and only update the 'XData', 'YData' and 'ZData', or 'CData' in the loop.
If you speficy your problems, I will update this suggestion in the "..." line.
  12 Commenti
Linford Briant
Linford Briant il 2 Feb 2017
Thanks Jan and Image Analyst, very useful material.
Here is my solution:
v = VideoWriter('example.avi');
open(v);
N1=rand(121,20e3);
X1=rand(1,121);
Y1=rand(1,121);
Z1=rand(1,121);
N2=rand(121,20e3);
X2=rand(1,121);
Y2=rand(1,121);
Z2=rand(1,121);
dt=100;
% [EDITED] Updated version, 31-Jan-2017 16:19:11 UTC]
FigH = figure;
hold on
ax1 = subplot(1, 2, 1, 'NextPlot', 'add'); % as: hold on
colorbar;
caxis(ax1,[0 1]);
t1 = title('dummy');
view(ax1, 3);
ax2 = subplot(1, 2, 2, 'NextPlot', 'add'); % as: hold on
colorbar;
caxis(ax2,[0 1]);
t2 = title('dummy');
view(ax2, 3);
dt = 1000;
nFrame = numel(1:dt:length(N1)); % [EDITED]
F(nFrame) = struct('cdata',[],'colormap',[]);
ScatterH1 = [];
ScatterH2 = [];
iFrame = 0;
for i = 1:dt:length(N1)
if ~isempty(ScatterH1) % Clean up former objects
delete(ScatterH1); % Alternative: Update the 'CData' only
delete(ScatterH2);
end
cmap=N1(:,i)';
ScatterH1 = scatter3(X1,Y1,Z1,50,cmap,'filled', 'Parent', ax1);
set(t1, 'String', sprintf('Time = %.1f ms', i*0.1)); % [EDITED]
cmap2=N2(:,i)';
ScatterH2 = scatter3(X2,Y2,Z2,50,cmap2,'filled', 'Parent', ax2);
set(t2, 'String', sprintf('Time = %.1f ms', i*0.1)); % [EDITED]
drawnow
iFrame = iFrame + 1;
F(iFrame) = getframe(FigH); % Not i, because this steps in dt
writeVideo(v,F(iFrame));
end
close(v);
I had to hold on to the figure because the frame changes size on every iteration... not sure why though because when the video is playing it doesn't seem to change size!

Accedi per commentare.

Più risposte (1)

Image Analyst
Image Analyst il 31 Gen 2017
  3 Commenti
Linford Briant
Linford Briant il 2 Feb 2017
I actually opened these initially but it was above my station.
So I have to extract movie frames to make a video?
Image Analyst
Image Analyst il 3 Feb 2017
Well I didn't have the time, at that time, to adapt the demo for you - I was hoping you'd see how to do it. No, you don't have to write images or graphs to intermediate/temporary files. You can go right from the graph/axes to a video file and that's what my movie_made_from_surf.m demo shows. You can either make up the entire movie structure in memory, as I did, or if the movie would take up too much memory, you can skip that and go right from read() to writeVideo() without any intermediate complete movie being made. Something like this snippet
% Extract the frame from the movie.
thisFrame = read(videoObject, frame);
% Write this frame out to a new video file.
writeVideo(writerObj, thisFrame);
For what it's worth, I'm attaching another demo that I did for someone who wanted to convert an .avi format movie into a .mp4 format movie.

Accedi per commentare.

Categorie

Scopri di più su Graphics Performance in Help Center e File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by