Movie in Matlab is cropped and doesn't show the full figure - matlab

I am learning to make a movie in Matlab. I coped this piece of code from internet to make the movie. I am using OS X Mavericks and Matlab 2013a. I usually dock the figure windows. When I run the code I can see animation perfectly. When when I save the movie either by using movie2avi or VideoWriter command. It doesn't record the movie with full frame of figure. Instead I see a little bit of the figure window and my Matlab desktop view. Can anyone help me with this?
clear;
close all;
% Creates a 2D Mesh to plot surface
x=linspace(0,1,100);
[X,Y] = meshgrid(x,x);
N=100; % Number of frames
for i = 1:N
% Example of plot
Z = sin(2*pi*(X-i/N)).*sin(2*pi*(Y-i/N));
surf(X,Y,Z)
% Store the frame
M(i)=getframe(gca); % leaving gcf out crops the frame in the movie.
end
% myVideo = VideoWriter('wavemotion.avi');
% open(myVideo);
% writeVideo(myVideo,M)
% close(myVideo)
% Output the movie as an avi file
%movie2avi(M,'WaveMovie.avi');

Based on the documentation of both VideoWriter and movie2avi, you need to add a few more instructions to your code.
First, you need to set the renderer for a nice display and set the axes that the next plot will reset only the children and not the entire axes:
set(gca,'nextplot','replacechildren');
set(gcf,'Renderer','zbuffer');
There is also an advice to preallocate the frame buffer:
M(N) = struct('cdata',[],'colormap',[]);
Finally, you just need to call getframe without any argmuent, as gca is the default argument.
On my computer (with Matlab 2013b), with these modifications and using VideoWriter, it works fine. With movie2avi, it does not work properly; I think I need to specify a compression codec to fix that.

Related

Animation of figure with subplots using VideoWriter in MATLAB

I'm trying to create an animation file in MATLAB from a figure with 2 subplots using the VideoWriter. However, the avi file that I get includes only one of the subplots.
Here is the code:
clc
clear
vidObj = VideoWriter('randdata');
open(vidObj)
figure (1)
for i = 1:100
clf
subplot(1,2,1)
imagesc(rand(100))
subplot(1,2,2)
imagesc(rand(100))
drawnow
CF = getframe;
writeVideo(vidObj,CF);
end
There must be something simple going wrong here but I don't know what. I would like to capture the entire figure.
The documentation for getframe states in the first line:
F = getframe captures the current axes
So it's capturing the axes, not figure.
You want to use it as also specified in the documentation
F = getframe(fig) captures the figure identified by fig. Specify a figure if you want to capture the entire interior of the figure window, including the axes title, labels, and tick marks. The captured movie frame does not include the figure menu and tool bars.
So your code should be
clc; clear
vidObj = VideoWriter('randdata');
open(vidObj);
figure(1);
for ii = 1:100
clf
subplot(1,2,1)
imagesc(rand(100))
subplot(1,2,2)
imagesc(rand(100))
drawnow;
% The gcf is key. You could have also used 'f = figure' earlier, and getframe(f)
CF = getframe(gcf);
writeVideo(vidObj,CF);
end
For ease, you might want to just get a File Exchange function like the popular (and simple) gif to create an animated gif.

Matlab GUi How to come back to the command window when axes is refreshing

I am writing a Matlab GUI and I need to show images in one axes. The images come from the camera. So I find when use preview to display the camera with one axes, I can go back to the command window. But when I use get the image with the getsnapshot() function and do some processing then use the other axes to display the processed images in real time, I find I can not go back to the command window. That maybe because the axes is refreshing all the time. So when I click the command window, the axes popup then disturb the command window. So anyone knows the solution. The following is my GUI panel.
The code like this:
while length>0 % length is the video duration that user set
frame = getsnapshot(VidObj); % VidObj is the camera
signal = imageprocess(frame); % image processing
axes(handles.Signal_Monitor); % show in axes Signal_Monitor
imshow(signal); % show result image
end
Thanks a lot!
Image show by function imshow(signal,'InitialMagnification','fit','Parent',handles.Signal_Monitor); 4x4 resolution
Image show by function set(handles.ih, 'cData', signal); It is only a tiny region. Because I process the original image captured by camera to a very small picture. 4x4 resolution
Instead of replotting the signal in every iteration, change the CData of your image using
set(ih, 'cData', signal);
where ih is the handle to the plotted image when you plot it first time using ih = imshow(signal). And remove the axes call, when you do this you switch the focus. For example you can modify your code as follows to achieve this
length = Total_Time;
while length>0 % length is the video duration that user set
frame = getsnapshot(VidObj); % VidObj is the camera
signal = imageprocess(frame); % image processing
if length==Total_Time % plot only during the first iteration
axes(handles.Signal_Monitor); % show in axes Signal_Monitor
handles.ih = imshow(signal); % show result image
else
set(handles.ih, 'cData', signal);
end
length = Total_Time - 1;
end
I am sure there is a nicer way, but I don't have access to all of your code to do this.

Create 2D Spectrogram in Matlab

I am in need of plotting a 2D spectrogram of a signal in Matlab. I need it for a printed assignment, hence the 3D image makes no sense. However, when the signal is plotted using Spectrogram it automatically produces a 3D plot of the signal.
My Code:
Dataset = 1; % Dataset to be analysed
N = 1024; % Window size
Beta = 12; % Kaiser window beta value (small = narrow main lope)
Overlap = 800; % Window overlap
Threshold = -150; % Minimum magnitude before threshold
spectrogram(Enclosure{Dataset}(1:end),kaiser(N,Beta),Overlap,2048,fs,'MinThreshold',Threshold,'yaxis');
which produces a graph that looks like this:
But it is seen from the top, and the graph is really showing this:
The reason why i need it to specifically be 2D (and why i don't settle with a screenshot) is because i am using Matlab2tikz to convert Matlab figures into Tikz figures in LaTex. with the 3D images i get figures of +100 Mb and 2D will reduce the size to <1Mb.
I don't know what version of Matlab you are using but in 2015a you should be able to get a handle to the figure with the 3D plot and change the view angle to 2D:
view(0,90);
I've also got an example of how you can make your own 2D plot from the outputs of spectrogram() using a similar method:
x = [0:0.01:100];
y = sin(5*x);
y = awgn(y,0.1);
[S,F,T,P] = spectrogram(y,200,0,length(y)*5,100);
[m,n] = size(P);
figure(2)
surf(F,T,zeros(n,m),P','EdgeColor','none')
view(0,90)
xlabel('Frequency')
ylabel('Time (s)')
The output looks like this:
Hopefully since there is no altitude information, the figure size might be smaller but I can't test that since I don't have Matlab2tikz.
One option is to capture whatever its plotted and then plot it as an image. You can do this using getframe
if you do
F=getframe(gca);
cla;
imshow(F.cdata);
You'll get exactly what you will be seeing before, but as an image.
However I think it defeats a bit the purpose of Matlab2Tikz, as the idea os that you have Tikz code describing your data...
You can try the following:
[~,F,T,ps]=spectrogram(Enclosure{Dataset}(1:end),kaiser(N,Beta),Overlap,2048,fs,'MinThreshold',Threshold,'yaxis').
% Output the spectrum in ps
imagesc(T,F,10*log10(ps))
% Generate a 2d image
view(270,90)
xlabel('Time [s]')
ylabel('Frequency [Hz]')
c=colorbar;
c.Label.String='Power [dB]';
% Extra setting to make the plot look like the spectrogram
Good luck

Taking images of 3D model using STLRead

I'm trying to take "images" of a 3D model. I am able to load an STL file through this code. What I need to do is be able rotate the object, and take "images" of it as it rotates.
stlread outputs a face and vertex structure that is compatible with patch(), so I can display the object, but I'm not sure how to actually store that image into a matrix.
I think what you are after is the function getframe, which captures the content of an axes and store the data as a regular "image" matrix.
I made a simple GUI to illustrate the concept. Basically I took the code from the link you provided (stldemo.m) and added a few features to take snapshots. In this case I added the command rotate3d on to rotate the femur inside the axes and a pushbutton whose callback calls getframe and captures the content of the axes. Basically you rotate the femur//patch object as you wish and you press the button to get a snapshot. In the code I make a new figure pop up to convince you it works, but you can of course do whatever you want with the data.
Note that using getframe outputs a structure with a field called cdata...that's what you are after in order to get the content of the axis as a matrix.
So here is the code and a few snapshots to illustrate:
function SnapShotSTL(~)
%// Taken from the stldemo.m file.
%% 3D Model Demo
% This is short demo that loads and renders a 3D model of a human femur. It
% showcases some of MATLAB's advanced graphics features, including lighting and
% specular reflectance.
% Copyright 2011 The MathWorks, Inc.
%% Load STL mesh
% Stereolithography (STL) files are a common format for storing mesh data. STL
% meshes are simply a collection of triangular faces. This type of model is very
% suitable for use with MATLAB's PATCH graphics object.
% Import an STL mesh, returning a PATCH-compatible face-vertex structure
handles.fv = stlread('femur.stl');
%% Render
% The model is rendered with a PATCH graphics object. We also add some dynamic
% lighting, and adjust the material properties to change the specular
% highlighting.
%// Create figure, axes and a pushbutton.
hFigure = figure('Units','Pixels','Position',[200 200 500 600]);
hAxes1 = axes('Units','pixels','Position',[50 50 450 400]);
hSnapShot = uicontrol('Style','push','Position',[50 500 60 30],'String','SnapShot','Callback',#(s,e) GetSnapshot);
patch(handles.fv,'FaceColor', [0.8 0.8 1.0], ...
'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.15);
% Add a camera light, and tone down the specular highlighting
camlight('headlight');
material('dull');
% Fix the axes scaling, and set a nice view angle
axis('image');
view([-135 35]);
rotate3d on %// Enable to rotate the object in the axes
guidata(hFigure,handles);
function GetSnapshot
CurrentImage = getframe(gca);
ImageData = CurrentImage.cdata; %// Access the data. I create a variable but that's not strictly necessary.
%// Here a new figure is created and the image displayed in it... you can store it and do as you like with it.
figure;
imshow(ImageData);
guidata(hFigure,handles);
end
end
So the GUI looks like this when opened:
Then after a rotation of the object/femur:
and finally after pressing the pushbutton, a snapshot is taken (i.e. getframe is executed) and the resulting image matrix displayed in a new figure:
Note that I used imshow to actually display the image but the data can be manipulated as well.
Moreover, you can also use the following calling syntax for getframe in case you want to retrieve the colormap associated with your data:
F = getframe;
[X,map] = frame2im(F);
In this case, X would be equivalent to G when using this code:
G = F.cdata;
Finally, you could set up a loop in which the actual patch object is rotated by itself and frames are taken automatically. That should not be too hard to implement :)
Hope that helps!

How to automatically spin a 3d hsitogram in matlab?

I have a 3d histogram in matlab. Is it possible to automatically spin it i.e to get the 3d effects. I want to show it as a video in PowerPoint where the 3d histogram swivels.
thanks
A somewhat cumbersome way to do this would be to rotate the chart manually using the view command. You can update azimuth and elevation views of any 3D plot using this command.
Creating a video of it requires capturing the plot window using a command sequence like this (note, you're going to get the gray background, so you might want to change the background color):
% create figure and get handle to it (store handle in hf)
hf = figure(1);
% [create 3d plot]
% Create file to hold the animation
aviobj = avifile('mymovie.avi', 'compression', 'Cinepak');
% loop with some criteria for rotation
while(...)
% update view using view command
view(az, el);
% get Matlab to flush the drawing buffer (effectively forces a plot update)
drawnow;
% capture frame and write to the avi file
aviobj = addframe(aviobj, hf);
end
% end loop
% Close movie (flushes write buffer and finishes the video)
aviobj = close(aviobj);
You can use the same tactic without the avifile stuff to rotate the plot using a script in Matlab, though you might want to use a pause command to slow down the frame change.
Let us make sure we are talking about the same thing here. A 2-D histogram would have bins of a specified X and Y range and the count would be shown on a Z axis. A 3-D histogram would have bins in the X and Y and Z ranges with the count shown in some other way (color?) You would need slicing for a 3-D histogram to make sense.I am going to assume that you mean a 2-D histogram that looks like a bunch of blocks coming out of the ground.
I think you will be better served to make this 2-D histogram into an image, where each pixel represents a specific bin in X and Y and the color specifies the count in that bin. I think the motion will only confuse the data. Use image or imagesc or imshow for this. Also, I would recommend an intensity based colormap (>>colormap), like spring or winter. This make the differences more apparent. Turn on the colorbar (>>colorbar)