How can I put a background image in a movie in matlab - matlab

I need to put a background image in a movie created using MATLAB?
I have posted below an example code of how I am generating a movie in Matlab. I need to add a background image to this movie. Thanks for your help.
for i=1:128
for j=1:128
p(i,j,:)=randn(1,200);
end
end
[u,v,w]=size(p);
frm_r=1:128;
frm_c=1:128;
figure; j=1;
for t=1:w
surface(frm_c,frm_r,p(:,:,t),'EdgeColor','none');
pause(0.1)
colorbar;
F(j) = getframe;
j=j+1;
end
movie(F,1,50)

If you have access to MATLAB code that creates movie, you can place an axes with IMAGE or IMSHOW as a background and make axes on the top of it transparent.
Here is a simple example:
im = image; % create image object (default pic)
imax = get(im,'parent'); % get image axes handle
axis ij
set(imax,'position',[0 0 1 1]) % make it to fill the whole figure
ax = axes; % new axes
h = plot(ax,rand(100),'ro'); % initial plot
for i=1:20
set(h,'ydata',rand(100,1)); % change the data in a loop
pause(0.1)
end
You can get get better answer if you show your code how you create a movie.
EDIT:
I simplified the code in your answer a little. For example you don't need loops to fill up 3D array. And you don't need to repeat surface function in the loop. Just change zdata property.
Try this code (substitute yourimage.jpg to real file name):
p = randn(128,128,200);
[u,v,w]=size(p);
frm_r=1:128;
frm_c=1:128;
figure;
im = imshow('yourimage.jpg'); % create and display image object from a file
imax = get(im,'parent'); % get image axes handle
set(imax,'position',[0 0 1 1]) % make it to fill the whole figure
ax = axes('color','none'); % new axes
hsurf = surface(frm_c,frm_r,p(:,:,1),'EdgeColor','none','Parent',ax);
colorbar;
xlim([1 u])
ylim([1 v])
j=1;
for t=1:w
set(hsurf,'zdata',p(:,:,t))
F(j) = getframe;
j=j+1;
end
movie(F,1,50)

Related

Change the width of a subplot. There is no position property on the Line class

I have the following figure
that I created using the following code
%% figures
DateNumObs=datenum(table2array(ADCPCRUM2(1:1678,ColumnYear)),table2array(ADCPCRUM2(1:1678,ColumnMonth)),table2array(ADCPCRUM2(1:1678,ColumnDay)),table2array(ADCPCRUM2(1:1678,ColumnHour)),table2array(ADCPCRUM2(1:1678,ColumnMinutes)),table2array(ADCPCRUM2(1:1678,ColumnSeconds)));
Flipecart=permute(ecart(1:1677,:),[2,1]);
Flipecartreel=permute(ecartreel(1:1677,:),[2,1]);
bottomVel=min(min(min(Magnitude)),min(min(velocityModel*1000)));
topVel=max(max(max(Magnitude)),max(max(velocityModel*1000)));
bottomVer=min(min(Flipecart))
topVer=max(max(Flipecart))
figure
subplot(4,1,1);
FlipMag=permute(Magnitude,[2,1]);
[C,h] =contourf(DateNumObs,1:1:22,FlipMag);
datetick('x','dd/mm/yy','keeplimits','keepticks')
caxis manual
caxis([bottomVel topVel])
c=colorbar;
c.Label.String = 'Horizontal velocity(mm/s)';
xlabel('Date');
ylabel('Depth(m from bottom)');
set(h,'LineColor','none')
title('Observation');
subplot(4,1,2);
[C,h] =contourf(DateNumObs(1:1677),1:1:22,MagMatrixH1*1000);
datetick('x','dd/mm/yy','keeplimits','keepticks')
caxis manual
caxis([bottomVel topVel])
c=colorbar;
c.Label.String = 'Horizontal velocity(mm/s)';
xlabel('Date');
ylabel('Depth(m from bottom)');
set(h,'LineColor','none')
title('Model D1');
subplot(4,1,3)
% x0=10;
% y0=10;
% width=550;
% height=400
gcf=plot(DateNumObs(1:1677),Flipecart(10,:))
% set(gcf,'LineWidth',1,'position',[x0,y0,width,height]) % Part giving the error
datetick('x','dd/mm/yy','keeplimits','keepticks')
caxis manual
caxis([bottomVer topVer])
subplot(4,1,4)
c=colorbar;
plot(DateNumObs(1:1677),Flipecartreel(10,:))
datetick('x','dd/mm/yy','keeplimits','keepticks')
caxis manual
caxis([bottomVer topVer])
I am trying to got the normal plot to be the same size as the (blue) contourf plots by using the code which is commented in the code I posted. I got this code from https://nl.mathworks.com/matlabcentral/answers/65402-how-to-set-graph-size .
However, when I try to run it it gives me the following error:
Error using matlab.graphics.chart.primitive.Line/set
There is no position property on the Line class.
Error in StatisticsSOLA (line 315)
set(gcf,'LineWidth',1,'position',[x0,y0,width,height])
I also tried is it possible to change the height of a subplot? but I get the same error. How do I prevent this error and change the width of the bottom two figures?
You are trying to set the position of the axes and the linewidth of the line object in one go, but are not providing the correct handles. Furthermore, don't store the handles of the lines in gcf, since this is a reference to the currently active figure.
Instead you can do:
data = rand(100,200); % some data
fig = figure(1); clf;
% first subplot with colorbar
ax(1) = subplot(211);
imagesc(data)
c = colorbar;
% second subplot without colorbar
ax(2) = subplot(212);
p = plot(data(1,:))
% set height and width of second subplot
drawnow % needed to get right position value of ax(1) and ax(2)
ax_pos = [ax(2).Position(1:2) ax(1).Position(3:4)]; % keep ax(2)'s left and bottom position, and set same width and height as ax(1)
set(ax(2), 'Position', ax_pos)
Alternative
Sometimes it is easier to create colorbar in the second axes, and hide it. This way you don't have to set the positions of the axes yourself.
data = rand(100,200); % some data
fig = figure(1); clf;
% first subplot with colorbar
ax(1) = subplot(211);
imagesc(data)
c = colorbar;
% second subplot without colorbar
ax(2) = subplot(212);
p = plot(data(1,:))
c = colorbar; % draw useless colorbar,
c.Visible = 'off'; % and hide it
Figure should look the same:

How do i produce an animated GIF in MATLAB?

I want to produce a animated gif of a solution to a partial differential equation. That is the gif should show the solution at specific time.
Currently I can only make pictures in which all times are plotted.
Below is my entire program, with figure(3) being my attempt of making a gif.
clear all;
close all;
%%%%%%%%%%%%
% For slide 27 of Diffusion 1D
% The equation to be graphed in latex form is
% u(x,t)=\frac{1}{L}+\frac{2}{L}\sum^{\infty}_{n=1}cos(\frac{n\pi x_0}{L})cos(\frac{n\pi x}{L})e^{-k(\frac{n\pi}{L})^2t}
%%%%%%%%%%%%
%define constants
%note that the constants listed in the file are arbitrary
L = 2; %length of the rod
k= 0.01; % Diffusivity, which is assume to be constant but can be a function of x
x0 = 1; %location of the inital condition i.e. f(x)=delta(x-x0)
tmax= 50; %maximum amount of time the simulation runs
nmax = 200; % maximum value for n, increase to accuracy
tgrid = 21; %The number of points to be evaluated in the time domain
xgrid = 51; %The number of points to be evaluated in the space domain
%initialize variables
u=zeros(tgrid,xgrid); %preallocate array used for storing values of the solution
t=linspace(0,tmax,tgrid);%We assume that time is evenly distributed
x=linspace(0,L,xgrid); %We assume that space is evenly distributed
%Plotting variables
figure(1);
hold on;
axis([0 L -inf inf]);
xlabel('x');
ylabel('u(x,t)');
%Calculation,
for i=1:tgrid
for j=1:xgrid
seriesSum=0;
%Calculate the fourier series up to nmax for each point u(x,t)
for n= 1:nmax
seriesSum= seriesSum + cos(n*pi*x0/L)*cos(n*pi*x(j)/L)*exp(-k*t(i)*(n*pi/L)^2);
end
%Finish calcuation for solution at a specific point
u(i,j)= 1/L+(2/L)*seriesSum;
end
%After we have calculated all points at time t, we graph it for time t
plot(x,u(i,:),'linewidth',4);
end
saveas(gcf,'PDE_sol.png')%Save figure as png in current directory
%run a second loop that does not include the initial condition to get a
%better view of the long term behaviour.
%Plotting variables
figure(2);
hold on;
axis([0 L -inf inf]);
xlabel('x');
ylabel('u(x,t)');
for i=2:tgrid
plot(x,u(i,:),'linewidth',4);
end
saveas(gcf,'PDE_sol_without_inital.png')%Save figure as png in current directory
%Create a gif verison of figure 2
figure(3);
axis([0 L -inf inf]);
xlabel('x');
ylabel('u(x,t)');
filename = 'PDE_sol.gif';
for i=2:tgrid
plot(x,u(i,:),'linewidth',4);
drawnow
frame = getframe(1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if i == 2;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
end
The output gif that I get is
which is clearly not animated.
Note: If you think there is a better place to post this question please direct me to it. As my issue is with the MATLAB programming language and not the math involved I thought this would be the best place to post my question.
The first input to getframe is the handle of the figure that you'd like to take a screenshot of. As you have it written, you are grabbing figure 1 which is actually referring to the first figure that you create that you aren't updating within your loop.
You have assigned a numeric handle of 3 to the figure that you create right before your last loop so you'll want to tell getframe to use that figure instead.
Additionally, I would create one plot object and update the XData and YData rather than continuously creating new plot objects. The issue with calling plot continuously is that it's slow AND it completely resets all of your axes settings such as x and y labels as well as x and y limits.
% Store the handle to the figure in hfig
hfig = figure(3);
% Create the initial plot object
hplot = plot(NaN, NaN, 'LineWidth', 4);
axis([0 L 0 2]);
xlabel('x');
ylabel('u(x,t)');
filename = 'PDE_sol.gif';
for i=2:tgrid
% Update the plot appearance
set(hplot, 'XData', x, 'YData', u(i,:));
drawnow
% Get a screenshot of THIS figure
frame = getframe(hfig);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if i == 2;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
end

Matlab, print() function generates a png file without Y asymptote data

I have been currently using a Matlab script that plots a function and prints its data into a png file, but I have a problem with this last phase.
The fact is that, moving from plotted image to png files, some data points disappear.
Here are my images.
What Matlab (correctly) plots (note that the maximum is (0; 7.7)):
And here's what Matlab prints into the file:
Note that all the points in the Y asymptote are missing!
Why does this happen?
Here's my code:
grafico2D('filename.dat', -1);
...
function [result] = grafico2D(filename, max_X)
% function that loads data from a two-column file and plot them in 2D image
close all;
dati = load(filename); % load data from file
X = dati(:,1); % X axis
Y = dati(:,2); % Y axis
temp = size(X);
lungX = temp(1);
hFig = figure();
set(hFig, 'Visible', 'on');
plot(X, Y, 'red');
hold on;
ylim([0 1]);
if(max_X==-1)
xlim([1 X(lungX)]);
else
xlim([1 max_X]);
end
xlim
title(strrep(filename,'_','\_')); % substitute _ with \_
xlabel('annotation prediction position'), ylabel('likelihood');
grid
print(hFig, '-dpng', filename); % stampa su file
% }
result = 1;
end
Is there someone who can help me?
Thanks!
You can increase the resolution of your image with the -r option which specifies the resolution in dot per inch (with 90 as default). It should solve your problem (at least it did for me). See the Matlab print function documentation.
PS: you could also use thicker lines with the line property LineWidth.
You could just extend the x-limit a little bit:
xlim(xlim() - [0.05 0])

Creating a point moving along a graph in MATLAB

I am looking to create a simple log(x) graph within MATLAB in which the model shows the point moving along the curve with time.
The overall aim is to have two of these graphs alongside one another and to apply an algorithm to them. I am really unsure where to start here.
I am relatively new at MATLAB coding so any help would be very useful!
Thanks
Luke
Here is a variation on #Jacob's solution. Instead of redrawing everything at each frame (clf) we simply update the point's location:
%# control animation speed
DELAY = 0.01;
numPoints = 600;
%# create data
x = linspace(0,10,numPoints);
y = log(x);
%# plot graph
figure('DoubleBuffer','on') %# no flickering
plot(x,y, 'LineWidth',2), grid on
xlabel('x'), ylabel('y'), title('y = log(x)')
%# create moving point + coords text
hLine = line('XData',x(1), 'YData',y(1), 'Color','r', ...
'Marker','o', 'MarkerSize',6, 'LineWidth',2);
hTxt = text(x(1), y(1), sprintf('(%.3f,%.3f)',x(1),y(1)), ...
'Color',[0.2 0.2 0.2], 'FontSize',8, ...
'HorizontalAlignment','left', 'VerticalAlignment','top');
%# infinite loop
i = 1; %# index
while true
%# update point & text
set(hLine, 'XData',x(i), 'YData',y(i))
set(hTxt, 'Position',[x(i) y(i)], ...
'String',sprintf('(%.3f,%.3f)',[x(i) y(i)]))
drawnow %# force refresh
%#pause(DELAY) %# slow down animation
i = rem(i+1,numPoints)+1; %# circular increment
if ~ishandle(hLine), break; end %# in case you close the figure
end
A simple solution is:
x = 1:100;
y = log(x);
DELAY = 0.05;
for i = 1:numel(x)
clf;
plot(x,y);
hold on;
plot(x(i),y(i),'r*');
pause(DELAY);
end
You may want to have a look at the COMET function, which will make an animation of the curve.
For example (using the same numbers as #Jacob)
x = 1:100;
y = log(x);
comet(x,y)
If you want to show the point moving on the line (not 'drawing' it), you simply plot the line before
x = 1:100;
y = log(x);
plot(x,y,'r')
hold on %# to keep the previous plot
comet(x,y,0) %# 0 hides the green tail
a little more complex solution along the same lines as #Jacob. Here I add some optimization using handle graphics and a MATLAB movie object for playback.
x=1:100;
y=log(x);
figure
plot(x,y);
hold on; % hold on so that the figure is not cleared
h=plot(x(1),y(1),'r*'); % plot the first point
DELAY=.05;
for i=1:length(x)
set(h,'xdata',x(i),'ydata',y(i)); % move the point using set
% to change the cooridinates.
M(i)=getframe(gcf);
pause(DELAY)
end
%% Play the movie back
% create figure and axes for playback
figure
hh=axes;
set(hh,'units','normalized','pos',[0 0 1 1]);
axis off
movie(M) % play the movie created in the first part
solution can be this way
x = .01:.01:3;
comet(x,log(x))

Producing subplots and then combine them into a figure later in MATLAB

My program produces small figures during the command cycle. Is there a way to just save these figures and then combine them in one figure later?
Consider the code:
hFig = figure;
%# create temporary subplots as template
for i=1:2, h(i) = subplot(2,1,i); end %# create subplots
pos = get(h, 'Position'); %# record their positions
delete(h) %# delete them
%# load the .fig files inside the new figure
fileNames = {'a.fig' 'b.fig'}; %# saved *.fig file names
for i=1:2
%# load fig
hFigFile = hgload( fileNames{i} );
%# move/copy axis from old fig to new fig
hAx = get(hFigFile, 'Child'); %# hAx = gca;
set(hAx, 'Parent',hFig)
%#hAx = copyobj(hAx,hFig);
%# resize it to match subplot position
set(hAx, 'Position',pos{i});
%# delete old fig
delete(hFigFile)
end
This was adapted from this newsgroup discussion
Use saveas. Save your subplot as a FIG file so you have complete control over it later (as opposed to a JPG).
Choose a tiling pattern and then use subplot to display multiple figures in one.
I have an answer here as an example:
h1 = figure(1)
plot(1:10,'o-r');
title('title');
xlabel('xlabel');
ylabel('ylabel');
% Copy contents
ch(1) = copyobj(gca,gcf);
% Figure 2
h2 = figure(2)
plot(1:30,'o-r');
title('title fig2');
xlabel('xlabel');
ylabel('ylabel');
% copy contents
ch(2) = copyobj(gca,gcf);
figure(3)
sh = subplot(1,2,1);
clear axes
p = get(sh,'position');
ah = copyobj(ch(1),gcf);
set(ah,'position',p);
% Create axis template
sh = subplot(1,2,2);
clear axes
p = get(sh,'position');
ah = copyobj(ch(2),gcf);
set(ah,'position',p);
% Delete template
% delete(sh);
Amro's solution works greatly, but with boxplots you have to reset the Xtick and Xtick labels, otherwise, for some reason, they will not be resized according to the the subplot. When you create the boxplot or after opening the figure add:
set(gca,'XTick',<1d vector>,'XTickLabel',<1d cell vector>)
or put automatic ticks and labels
set(gca,'XTickMode','auto','XTickLabelMode','auto')