Posted by Armin on Friday, February 11, 2011
Below is a PDF of my presentation and the code for a tutorial on making elaborate multi-axes movies with Matlab. The tutorial was part of the "hallway salon" series that has become a tradition in the Daniel Lab.
The code contained on this page contains a framework for saving movies from MATLAB that should be easily adaptable for your own work. I tried to add as many comments in the code, so it should be fairly self-explanatory.
Code output: an AVI file
The embedded video below shows you the output of the code featured on this page. (It's of much lower quality than the AVI file you would get on your computer by running the script.)
MATLAB code in chunks
Copy the following pieces of code into your MATLAB editor. You should create two new m files. Copy cells 1 to 4 (below) into one document, saved as something like "myanimation.m". The other file has to be named "plotfilledcircle.m". This is a helper function for plotting a circle.Cell 1: Creating data for our animation
This piece of code just creates the path for our circle to move along; a simple spiral. There are two vectors, xpos and ypos, that contain the center coordinates of our circle for each frame. The last line in the listing below creates a vector that defines the circle's radius for each frame.
%% Create test data for our animation: a dot moving along a path % Our aim is to make a circle move around an image along a specified path. % First, we'll create that path (xpos and ypos) revolution_no = 5; % how often around the circle ang_resolution = 40; % how many points (i.e. frames) per circle % why not a spiral: % show what we have so far: % We now want to use these x-y coordinates to place a cirle on an image. % Each iteration, we want the position to be updated so that it appears as % if the circle moved around the specified path. % In addition, we want the circle diameter to change as it goes along.
Cell 2: Plotting a circle that moves along the path specified above
This piece of code draws a circle on a figure with white background. It allows us to check whether everything looks OK, before going to the next cell in which we'll save the result of each iteration into a TIFF stack. This code depends on the helper function called "plotfilledcircle". Copy the code for this function (found a few paragraphs further down) into it's own m file. It has to be saved with the function's name (plotfilledcircle.m) and should either be in the same directory as your other m file, or in a directory that MATLAB knows about (i.e. in its path).
%% Test the moving circle and save it as an image sequence % We'll now plot a circle for each time steps, according to the path and % size specifications above. I created a separate function to create the % circle, called 'plotfilledcircle'. axlim = 100; ph = plotfilledcircle(circlesize(c), [xpos(c) ypos(c)]); % plot circle axis off; % we need to set the axes to an appropriate limit, otherwise they'll % resize to always show the full circle: axis square; end
Cell 3: same as cell 2, but now we save an image sequence
%% Same as above, but now we save it as an image sequence (TIFF stack) % axlim = 15; ph=plotfilledcircle(circlesize(c), [xpos(c) ypos(c)]); % plot circle axis off; % we need to set the axes to an appropriate limit, otherwise they'll % resize to always show the full circle: axis square; % We'll save this animation as a tiff stack, so we can load it % back later for our grand finale currentframe = frame2im(getframe(figh)); % convert fig into image data currentframe = im2bw(currentframe,0.4); % make it binary to save space if c == 1 else end end
Cell 4: Putting it all together to make a multi-axes figure and save an AVI file
The following, long piece of code is the recipe for creating a movie file that I use. There are multiple ways of doing this, but using the avifile() and addframe() functions works well for me...
%% Putting it all together % We now want a fancy animation that includes the circle object, as well % as its position and size data in the form of 'evolving' graphs. % % At this point you should think about what resolution your final movie % might have. This depends on what you want to do. If you need a full-size % slide for an animation, you might as well just create the animation at % that size. Chances are, it looks better if PowerPoint doesn't have to % scale the movie. % If it's for an HD segment of a movie, use HD sizes (eg. 720p: 1280x720px % or 1080p: 1920x1080px). HD will result in HUGE movie files if no % compression is used. Here we'll use 1024x768 pixels, which is the native % resolution of many projectors and the default on my Keynote documents. % % We also want to think about where to place the individual graphs % It helps to draw it out on a piece of paper. % For the purpose of this tutorial, we want four axes: % 1) fill plot of the circle (just like above, but with diff. colors) % 2) plot of the images we exported above % 3) evolving graph of the circle size % 4) evolving graph of the circle's X and Y position % % I like to start by setting up the positions of all those elements: fig_pos = [100 40 1024 768]; % position and size of the figure window fillplot_ax_pos = [80 320 400 400]; % position and size of fill plot image_ax_pos = [580 320 400 400]; % image plot axlim = 15; sizedata_ax_pos = [50 170 1024-60 70]; % circle size graph posdata_ax_pos = [50 50 1024-60 100]; % circle position graph % It's also often useful to define all the colors with variables set up % top: fig_col = [1 1 1]; % figure background color text_col = [0 0 0]; % text color light_grey = [.4 .4 .4]; dark_grey = [.2 .2 .2]; nice_blue = [51/255 51/255 102/255]; light_red = [.6 .4 .4]; % I like to have a little if-statement, so that only when I set a flag to 1 % will a movie file be created. Set to zero for setting stuff up. When % you're ready, set it to one. movieflag = 0; moviefilename = 'tutorialmovie.avi'; % only if our flag is set to 1, will we open up a movie object: if movieflag == 1 aviobj = avifile(moviefilename, 'fps', 15, 'compression', 'none'); end startframe = 100; endframe = 120; % which frames to plot (useful for debugging) % startframe = 1; endframe = length(t); % complete loop 'Position', fig_pos); tic; % *************** START THE BIG LOOP AFTER CREATING FIG. *************** for k = startframe:endframe % *************** 1) FILL PLOT AXES *************** fillplot_ax = axes; hold on; p1h(2) = plotfilledcircle(circlesize(k), [xpos(k) ypos(k)], nice_blue); % plot circle hold off; % we need to set the axes to an appropriate limit, otherwise they'll % resize to always show the full circle: axis square; % *************** 2) TIFF IMAGE IMPORT PLOT AXES *************** image_ax = axes; try catch ME1 % Get last segment of the error message identifier. idSegLast = regexp(ME1.identifier, '(?<=:)\w+$', 'match'); end img = xor(1,img); % invert image to make it more exciting... XOR rules! % *************** 3) SIZE DATA PLOT AXES *************** sizedata_ax = axes; % create evolving data graph: hold on; hold off; % *************** 4) POSITION DATA PLOT AXES *************** posdata_ax = axes; hold on; % Hack to move xlabel in line with the upper one (try without): % *************** FINISH THE FRAME (AVI if selected) *************** if movieflag == 1 aviobj = addframe(aviobj,frame); % use addframe to append frame end if k < endframe clf; % clear figure except for very last frame end end % of the big loop if movieflag == 1 end
Helper function: plotfilledcircle.m
Save this file as "plotfilledcircle.m".
function ph = plotfilledcircle(circle_radius,circlecenter, fcol) % % plotfilledcircle(circle_radius,circlecenter, fcol) % % Function to plot a filled circle with radius 'circle_radius' % 'circlecenter' ... center location [0 0] is default % 'fcol' is optional and defines the face color (black default) % % Armin H 2011 circlecenter = [0 0]; end fcol = [0 0 0]; end end
Category:
Code
Comments
Elizabeth replied on Permalink
Tracking Moving Ball
Hi, if I want to create a ball with a 'tail' that moves in asymmetrical sinusodial fashion, is there a way to track both the position of the ball and the positions along the tail? Ideally the ball/string would move across the video frame as if it were a moving sperm cell with a head and flagellum. Please let me know if that is possible! Thank you!
Armin replied on Permalink
certainly possible