Colorbar is empty when saving figure as a tiff or jpeg - matlab

I'm trying to plot some temperature data over a grayscale image, with the temperature data shown using a colorscale. I've been able to do so by overlaying a partially-transparent array with the temperature data over the image data. The problem comes when I try to save it as a tiff (or jpeg). While the colorbar (for the temperature data) shows up exactly as intended in the Matlab figure, when I save it as a tiff, the colorbar comes up empty (solid white). Any ideas?
figure
imagesc(xlims, ylims, image_data)
set(gca,'YDir','normal');
colormap(gray)
title(title)
xlabel('xlabel')
ylabel('ylabel')
hold on
axis equal
axis tight
%Skip lines of code where I build my temperature array (T) here
%Force a single pixel to 2200
T(1,1)=2200;
%Remove any data below 1000
T(T<1000)=0;
% Establish Transparency Mask for Temperature Data
transp = T~=0; % Binary matrix highlighting where temp data exists
% Overlay Temp Data on Background Image
imagesc(xlims, ylims, T,'AlphaData',transp)
% Create Colormaps and Combine Them
% Note: Assumes no overlap between background image values and temp data
% (highest value in background image is 73)
cmap1 = colormap(gray(73));
cmap2 = colormap(gray(999-73));
cmap3 = colormap(jet(2200-999));
cmap = [cmap1; cmap2; cmap3];
% Apply Combined Colormap to Figure
colormap(cmap)
% Add and Modify colorbar
h = colorbar;
set(h,'YLim',[1000 2200]) % Reduces Range of Colorbar to show only Temp Data
ylabel(h,'Temperature, Kelvin')
print(gcf, '-dtiff', 'filename');
When saved the colorbar looks like this:
In the Matlab figure it looks fine:
UPDATE: I had a bit of old code that I had done something kind of similar on and went line by line looking at differences. For some reason, having the figure visible matters? If I change
figure
to
figure ('visible','off');
the whole thing works. Still curious as to why????

Related

Multiple Plot Matlab including image

I use the tiledlayout(2,2) command to create a plot in Matlab. The first three title fields filled with normal plots. The fourth and last field is a field with an image. I used the commands IMG = 'mypic.tif'and imshow(IMG).I wonder why I can not change the size of my image. Is this not possible with the tiledlayoutcommand? I have looked up the documentary for tiledlayout and imshow(), but found nothing which helps me.
It indeed seems as if this is not possible using the tiledlayout functionality. However, it is possible using the subplot functionality. Below, I will give an example how this works.
Consider the following script:
% Generate some dummy data for the four plots
x = linspace(0, 2*pi, 25);
y = sin(x);
% Load sample image
image = imread('ngc6543a.jpg');
% Generate the figure
fig = figure(1);
% The three subplots
for i = 1:3
subplot(2,2,i);
plot(x, y);
end
% The image
subplot(2,2,4);
imshow(image);
% Increase size of the image
size_factor = 1.4; % 1.0 is original size
im_ax = fig.Children(1); % axes belonging to image
dims = im_ax.Position(3:4); % current dimensions
dims_new = size_factor * dims; % scale old dimensions
dxdy = (dims_new - dims) / 2; % offset for left bottom corner of image
im_ax.Position = [im_ax.Position(1:2) - dxdy, dims_new]; % update position
In this script, we start by generating some dummy data for the three 'normal' plots and loading a sample image (this image came with my MATLAB installation). Subsequently, we create a figure. After the figure has been created, I add the three dummy plots to the figure using a for loop and the subplot functionality. Then, we plot the image using imshow in the fourth subplot.
Now, the interesting part begins. First of all, I define a scale factor for the image (size_factor). Then, I retrieve the axes in which the image is plotted and store it in im_ax. From this axes, I retrieve the last two elements of the Position field and store them in dims. These two elements define the size of the axes. Based on the value of size_factor, I calculate the new size of the axes and store this in dims_new. To ensure that the axes (and thus the image) remains centered, we need to calculate by how much we need to shift the left bottom corner of the axes (whose coordinates are stored in the first two elements of the Position field). This result is stored in dxdy. The last thing we do is simply updating the Position field of the axes in which the image is plotted.
Now, to show you some results:
size_factor equals 1.0:
size_factor equals 1.4:
size_factor equals 0.55:

Freeze the axes size in matlab

I have images captured in many frames. All the frames have different sizes so I set the global maximum and minimum of each axes and used axis command like below:
h = figure;
axis([-8.4188e+03 -7.9061e+03 -102.6261 518.2502 -25.4673 0.2780])
%axis tight manual % this ensures that getframe() returns a consistent size
filename = 'testanim.gif';
But the animation boxes still keep changing the sizes although I have found the maximum and minimum limits of Xs, Ys and Zs. Do I need something more in my code?
This is the code I use for plotting:
% read the data
for k=1:length(FileNames)
FName = plyfiles(k).name;
plys=pcread(['Files\',FName]);
pcshow(plys) % Capture the plot as an image
frame = getframe(h);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256); % Write to the GIF File
if k == 1
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
end
pcshow will, just like imshow or plot, reset the axes it writes to. You can prevent this by setting
hold on
after creating the axes. However, now the point clouds will be shown on top of the previous ones, so you will also have to clear the axes before plotting a new one.
The easiest solution is, instead of holding the plot, to set the axes position every time after plotting. That is, do
set(gca, 'PropertyName', property_value)
after the pcshow call. The properties to set are, I believe, 'XLim', 'YLim', and 'ZLim'.

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

Overlaying data on an image in matlab

I have two plots I want to overlay on top of each other as shown in the link below:
The inputs are the two images on the left and the output is the image on the right. Here's the code I used:
reference = imread('ref_foam.png');
figure, imshow(reference);
hold on;
h = imshow(data,[]);
hold off
colormap jet;
alphamap = zeros(size(reference,1),size(reference,2));
for i = 0:size(data,1)-1
for j = 0:size(data,2)-1
if(~(data(i+1,j+1) == 0))
alphamap(i+1,j+1) = 0.75;
end
end
end
set(h, 'AlphaData', alphamap);
Anytime there's a zero in the data array, it sets that transparency to zero or else it will set the transparency to 0.75.
Now, my questions are: How can I get the colormap to apply to only the data array? In this example it works but if I convert "reference" to a grayscale, the colormap applies to that as well. The input for the colormap is an axes handle, is there anyway to input the image's handle (h) so that it only applies to the top (data) array? Also, I'd like to implement a colorbar as well. Is there anyway to apply the colorbar only to the data array? Thanks.
You probably want to use the subimage command - it lets you create images on the same figure with different colormaps.
Once create and modified as in your script, overlay the images by setting their axes positions on top of each other.

Save figure with plots as a matrix for further processing in MATLAB

I have displayed an image and plotted a rectangle over all the useless areas. Now i need to save this image in the form of a matrix, so that i can use it further.
figure,imshow(colz);
hold on;
for i=1:num
if(i~=n)
img=rectangle('Position',box(i,:),'FaceColor','k');
end
end
This is a part of my whole code. I'm covering all the undesired parts with zeros. so now I'm left with my desired area and a background. How can i save the pixel values in another matrix so as to create a new image that contains this enhanced data?
Thanks
here try this
F = getframe(gcf);
% gcf is your figure currently displaying your image with the rectangle
%
y = F.cdata;
hold off
figure(2),imshow(y);