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)
Related
Quite a simple question but just couldn't find the answer online... I want to visualise a point cloud gathered from a lidar. I can plot the individual frames but wanted to loop them to create a "animation". I know how to do it for normal plots with drawnow but can't get it working with a scatter3. If I simply call scatter3 again like I have done in the commented code then the frame that I am viewing in the scatter plot jumps around with every update (Very uncomfortable). How do i get the scatter3 plot to update to the new points without changing the UI of the scatter ie. Still be able to pan and zoom around the visualised point cloud while it loops through.
EDIT: The file is a rosbag file, I cannot attach it because it is 170MB. The problem doesn't happen when using scatter3 in a loop with a normal array seems to be something with using scatter3 to call a PointCloud2 type file using frame = readMessages(rawBag, i).
EDIT: The problem does not seem to be with the axis limits but rather with the view of the axis within the figure window. When the scatter is initialised it is viewed with the positive x to the right side, positive y out of the screen and positive z upwards, as shown in view 1. Then after a short while it jumps to the second view, where the axis have changed, positive x is now out of the screen, positive y to the right and positive z upwards (both views shown in figures). This makes it not possible to view in a loop as it is constantly switching. So basically how to update the plot without calling scatter3(pointCloudData)?
rawBag = rosbag('jackwalking.bag');
frame = readMessages(rawBag, 1);
scatter3(frame{1});
hold on
for i = 1:length(readMessages(rawBag))
disp(i)
frame = readMessages(rawBag, i);
% UPDATE the 3D Scatter %
% drawnow does not work?
% Currently using:
scatter3(frame{1})
pause(.01)
end
The trick is to not use functions such as scatter or plot in an animation, but instead modify the data in the plot that is already there. These functions always reset axes properties, which is why you see the view reset. When modifying the existing plot, the axes are not affected.
The function scatter3 (as do all plotting functions) returns a handle to the graphics object that renders the plot. In the case of scatter3, this handle has three properties of interest here: XData, YData, and ZData. You can update these properties to change the location of the points:
N = 100;
data = randn(N,3) * 40;
h = scatter3(data(:,1),data(:,2),data(:,3));
for ii = 1:500
data = data + randn(N,3);
set(h,'XData',data(:,1),'YData',data(:,2),'ZData',data(:,3));
drawnow
pause(1/5)
end
The new data can be totally different too, it doesn't even need to contain the same number of points.
But when modifying these three properties, you will see the XLim, YLim and ZLim properties of the axes change. That is, the axes will rescale to accommodate all the data. If you need to prevent this, set the axes' XLimMode, YLimMode and ZLimMode to 'manual':
set(gca,'XLimMode','manual','YLimMode','manual','ZLimMode','manual')
When manually setting the limits, the limit mode is always set to manual.
As far as I understood what you describe as "plots jumpying around", the reason for this are the automatically adjusted x,y,z limits of the scatter3 plot. You can change the XLimMode, YLimMode, ZLimMode behaviour to manual to force the axis to stay fixed. You have to provide initial axes limits, though.
% Mock data, since you haven't provided a data sample
x = randn(200,50);
y = randn(200,50);
z = randn(200,50);
% Plot first frame before loop
HS = scatter3(x(:,1), y(:,1), z(:,1));
hold on
% Provide initial axes limits (adjust to your data)
xlim([-5,5])
ylim([-5,5])
zlim([-5,5])
% Set 'LimModes' to 'manual' to prevent auto resaling of the plot
set(gca, 'XLimMode', 'manual', 'YLimMode', 'manual', 'ZLimMode', 'manual')
for i=2:len(x,2)
scatter3(x(:,i), y(:,i), z(:,i))
pause(1)
end
This yields an "animation" of plots, where you can pan and zoom into the data while continuous points are added in the loop
I am trying to write a MATLAB script to give me a contour map. The contour map must be created from inputs that I generated from 100 images.
The story is like this:
I have 100 images on which I ran an image processing algorithm for optimization. Now, I got their energy curves. So, I have 100 energy curves. I want to create a contour map that will show me where the points are denser on the plot. (the energy curves are plotted as energy vs. iteration with fixed number of iterations)
The following is my variable:
energy(iteration,numImages)
Hope I explained it well.
Thanks in advance.
I interpret your question to boil down to how can I create a surface plot with colors according to the energy found in energy. I would solve this by using the contour function with a grid generated using meshgrid. If each image is described in 1000 data points with 100 files the plot can be generated as follows:
% using stuff as random junk instead of energy
numPoints = 1000;
numFiles = 100;
stuff = rand(1000,100); % replace with actual information
[X, Y] = meshgrid(1:numFiles, 1:numPoints);
contour(X,Y,stuff);
You can also create a 3D surface plot using surf and the same logic.
From what i see of you graph (and using the comments also), one possible way is to use plot3 to plot a line in 3D for every plot.
For doing so, you can use something like this code:
x=(0:0.01:1)';
aexp=zeros(100,numel(x));
hold on
for ii=1:100;
% aexp(ii,:)=exp((-x+ii/10)); %exponential
aexp(ii,:)=exp(-(x-ii/100).^2); %~gaussian
% aexp(ii,:)= x*ii; %linear increase
plot3(x,aexp(ii,:),ii*ones(1,numel(x)));
end
% set(gca,'yscale','log'); % uncomment if you need logscale.
giving
I have a few options of plot. It always plot from the XY view. I changed by hand, but you can use the view command. Notice that i used a simple counter to make the spacing in the z direction.
In a similar manner, you can plot using the contour. For my code, after the data have been generated in the for loop, remove/comment the plot3 and add:
contour(aexp) %outside the for loop,
giving
Notice that i have not really take care what i'm plotting. You can find more info on contour in the Matlab page .
You commented that the x-axis should be number of iterations, y-axis should be energy and z-axis should be the information containing how many lines are passing through from some areas. For this, make a qq variable, being it qq=number_of_lines(number of iterations,energy) . Make a discrete grid for the energy if you don't have one. Number of iterations is probably discrete anyway. The function is you who need to devise, but i would go for something which checks the number of lines for every energy and every iteration. In this case you will have the z-function that depends on y and x, that is the case to use contour or surface.
My function above make a line for every ii point, to have a 3d function. An edition for another extra loop is not hard. Just remember to have the same regular grid for every point, otherwise you will have trouble.
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
I've got 10 grayscale images. I'd like to plot a simple YELLOW line over each image separately, then show them all over one plot (montage style).
I tried to draw all images first, but that made plotting lines very tricky (X,Y axes weren't standard for plotting over each separate image).
I thought about burning the line over the image, but I don't have the computer vision toolkit (easy functions to do this), otherwise it seemed complicated to both convert the grayscale to color and get it to burn the image.
I thought I might be able to use the function newplot to create a temporary plot space for each image, draw the line with a simple plot(...) call, then save it and just montage(...) all the individual plots at the end.
Is this possible? I've never played with the function newplot or tried to loop through individual plots, saving them up for a call to montage(...) this way, but it seems like a logical/simple approach.
I finally worked it out with subplot, subimage, and plot, using subplot with the position arguments does what I want easily enough. Using subplot kept the axis relative to the subplot I was on so I could plot the line with a standard fplot/plot call. The trick was normalizing the position to percentages vs. thinking of it in terms of pixels.
here's some code demoing it:
% Loop through this code, each time moving the subplot by position
LOOP {
% calculate left & bottom position as percentages (0..1)
subplot( 'Position', [ left bottom (1/cols) (1/rows) ] );
hold on
% (1) Draw the image
subimage(tmpImg, [0 255]);
axis off;
% (2) Plot the line over the original image
F = #(x) polyval(p, x);
fplot(F, [1 dimX 1 dimY], '-y');
}
I want to plot the sphere function as a surface or a contour plot, and the position and fitness value of the best individual which are evaluated by a sphere function of data generated from a Gaussian distribution superimposed with it. The plot will change in each generation so i get a movie. Also, on another figure, i want to plot the contour of the sphere function superimposed with the entire population generated from Gaussian distribution, with the retained fit individuals colored in red. This from generation to generation should give another movie.
This is basically an implementation of estimation of distribution algorithm(EDA). Anyone know how to do this?
EDIT
K= 4
for l = 1 : K
contour(X,Y,ph);
hold on
plot(bestId, 'rx');
end
The above code should superimpose contour plot and BestId. For each loop of l, a bestId is generated and superimposed with the contour plot. This generation of BestInd should take place for each l. but among the generations of bestId from 1 to 4, there is one which is the best of them and we should get that after four generation which is superimposed with the contour plot. Now i want this generation to be a movie for reach iteration from 1 to 4, so that i can see how the bestId are generated untill the best(optimal) one is achieved.
this is what i meant by movie in matlab. Any idea on how this could be done?
To create movie reflecting changes in figures, I am using combination of the class avifile and functions getframe() and addframe()
Here is an example
aviobj = avifile('example.avi','compression','None');
t = linspace(0,2.5*pi,40);
fact = 10*sin(t);
fig=figure;
[x,y,z] = peaks;
for k=1:length(fact)
h = surf(x,y,fact(k)*z);
axis([-3 3 -3 3 -80 80])
axis off
caxis([-90 90])
F = getframe(fig);
aviobj = addframe(aviobj,F);
end
close(fig);
aviobj = close(aviobj);
You can find more info here
http://www.mathworks.nl/help/matlab/ref/avifile.html
http://www.mathworks.nl/help/matlab/ref/movie.html
http://www.math.canterbury.ac.nz/~c.scarrott/MATLAB_Movies/movies.html
-----------------Edit after the discussion in the comments------------------
pm89 suggested another way in the comments. The VideoWriter class seems more modern and up to date. The example of use can be found at the end of the page below
http://www.mathworks.nl/help/matlab/ref/videowriterclass.html