MATLAB axes colors change when writing a GIF - matlab

Relevant Information: MATLAB R2015b, Mac
I am currently trying to write a GIF from a series of datasets (txt files) I took. I have no trouble writing the GIF file, however, when played back (in PowerPoint) or previewed in the OS X Finder, the axes labels change in color. In addition to the color change, I receive this warning:
Warning: Image data contains values that are out of range. Out of range values will be given the nearest valid value.
Currently, I grab all the data files in the directory, plot them, grab each frame, and put them into a GIF. Here is my code:
%Create MATLAB movie from plots
clearvars
%addpath('C:\Users\ucmuser\Documents\MATLAB')
filename='cooldown_movie.gif';
ext_in='txt';
[~,listing]=f_search(ext_in);
[r,~]=size(listing);
listing=natsortfiles(listing);
F=figure;
%r=20 is used for quick debugging (original is 460 files).
r=20;
% y=linspace(1,2*pi,100);
% x=linspace(1,100,100);
%C(1,1,1,r)=0;
for i=1:r
A=dlmread(listing{i});
listing{i}=strrep(listing{i},'_','\_');
x=A(1,:); %X Array
y=A(2,:); %Y Array
plot(x./1E9,y.*1E3,'-','LineWidth',1.2,...
'Color',[0.8500 0.3250 0.0980]);
grid off
xlabel('Frequency (GHz)','FontSize',18,'FontWeight','bold')
ylabel('Voltage (mV)','FontSize',18,'FontWeight','bold')
title('Cooldown Movie','FontSize',24,'FontWeight','bold')
G(i)=getframe(gcf);
drawnow
frame = G(i);
% im = frame2im(frame);
[C(:,:,1,i),map] = rgb2ind(frame.cdata,256,'nodither');
% if r == 1;
% imwrite(C,map,filename,'gif','LoopCount',Inf,'DelayTime',0);
% else
% imwrite(C,map,filename,'gif','WriteMode','append','DelayTime',0);
% end
end
imwrite(C,map,filename,'gif','LoopCount',Inf,'DelayTime',0);
A sample image is shown below. The axes labels change in color. If I turn on the grid, the effect is even more apparent with the grid changing in grayscale intensity. I've tried setting limits and the effect is still present.

I've found a solution for the time being although I'm not quite sure why it works. I started going through the figure properties and turned off the GraphicsSmoothing property (type F=figure;F.GraphicsSmoothing='off'; before the "for loop"). This seemed to fix the problem as well as clear the original out of range error.
With the GraphicsSmoothing property turned "on" and going through the first 20 data files, I have a maximum indexed color value of 22 via max(max(max(C))). Performing the same code with the GraphicsSmoothing turned "off" yields a maximum value of 4.
I am attaching two images displaying the extreme color differences with the GraphicsSMoothing turned on and off.
GraphicsSmoothing turned On (default)
GraphicsSmoothing turned Off
If someone knew why this is the case, I would greatly appreciate it.
UPDATE: I attempted to use this solution with grid on and the background border turned orange. I am confused on this whole issue.

Related

Matlab doesn't save the new dimension of the plot

I'm trying to save a figure with a no-default dimension, but I always obtain the default size plot.
figure
for i=1:6
for j=1:4
subplot(6,4,j+(i-1)*4)
[...]
end
end
w=600; h=800;
set(gcf,'Position',[30 60 w h]);
set(gcf, 'PaperUnits', 'centimeters');
set(gcf,'PaperPositionMode','manual')
print('test','-depsc');
It is mainly a 6-by-4 subplot. I looked for a solution on internet, I found many comments about Position, PaperUnits, PaperPositionMode, but none has worked so far. The only solution that works is when I export as .fig.
What I actually realized, is that after the set(gcf,'Position',[30 60 w h]) the window dimension of the plot is correct, but the subplot are squeezed like when the dimension is the default. If I just insert a pause and manually resize the window (even by almost nothing), the subplots expand nicely within the larger window. But still, with the print command the result is not the desired one.
I tried also with saveas and I got the same result.
Ah, if I manually save the figure, it works perfectly, but, of course, I need to automatize the process!
Thanks for your help!
Although i can't reproduce this behaviour as MATLAB 2014b automatically handles axes resizing, i'll still post an answer, that may need some adjustments.
Basically, what you need to do is :
% Get a handle to your figure object
Myfig=gcf;
% Get all of your figure Children - Warning : if you have a global
% legend in your figure, it will belong to your figure Children and you
% ll have to ignore it
AllChildren=get(Myfig,'Children');
MyAxes=findobj(AllChildren,'type','axes');
% Now you have your axes objects, whose Position attributes should be in
% normalized units. What you need to do now is to store these positions
% before changing the size of your figure, to reapply them after
% resizing (the beauty of normalized positions).
Positions=zeros(size(MyAxes,1),4);
for ii=1:size(MyAxes,1)
Positions(ii,:)=get(MyAxes(ii),'Position');
end
% Resize your figure
w=600;
h=800;
set(gcf,'Position',[30 60 w h]);
% Reuse the positions you stored to resize your subplots
for ii=1:size(MyAxes,1)
set(MyAxes(ii),'Position',Positions(ii,:));
end
This should do the trick.

Why no feature is being tracked using KLT-tracking in Matlab?

I am trying to track some features (extracted using multiscale-harrys detector) between two frames using the Kanade-Lucas-Tomasi (KLT) algorithm using the functions you can find here (Mathworks documentation).
I cannot understand what goes wrong. None of the points can be tracked. I tried making bigger the number of iterations and changing the size of the window around the features but the result is always the same, no feature is tracked.
Is it a problem in the data (images resolution is too low (240x180 pixels))?
Is the problem in the selected features?
These are the two images I am using:
This is my code:
img = single(imread('img.png'));
end_img = single(imread('end_img.png'));
coord_first = [24,21;25,97;29,134;37,25;37,55;37,64;38,94;38,103;40,131;41,139;43,14;44,22;44,54;44,63;46,93;46,101;47,111;49,131;49,140;52,166;55,52;62,151;76,51;78,89;81,151;81,165;83,13;92,165;111,18;111,96;155,42;155,62;155,81;155,100;156,129;163,133;168,126;170,40;170,65;172,26;173,134;174,59;174,84;174,103;174,116;175,73;178,97;186,142;186,149;190,119;190,132;194,75;209,99;210,42;210,66;212,133;212,152;215,61;215,79;218,119];
% display of the target image and all the features I want to track
figure
imshow(img,[]),
colormap gray
hold on
plot(coord_first(:,1), coord_first(:,2), 'r*');
% point tracker creation
% the paramters reported here are the default ones
pointTracker = vision.PointTracker('MaxIterations', 30, 'BlockSize', [31,31]);
% point tracker initialization
initialize(pointTracker,coord_first,img);
% actual tracking
[coord_end, point_validity] = step(pointTracker, end_img);
% display of all the correctly tracked featrures
figure
imshow(end_img,[]),
colormap gray
hold on
plot(coord_end(point_validity,1), coord_end(point_validity,2), 'r*');
Actually I have just solved the problem. Of course the problem was the fact that no point was tracked.
The problem is that the images given in input must have grayscale values in [0, 1] and not in [0, 255] (as I was doing).
There is no specific need to tune any of the parameter once the data are passed the right way (at least in my case with these low resolution grayscale images).
Check the contents of point_validity. If all elements of points_validity are false, then you would not see any points. If that is the case, the next question is why points were not tracked.
For an image of this size, try setting 'NumPyramidLevels' to 1.

Replace pixels with symbols

I am trying to write a function that would take an indexed image as an input and will replace all its pixels by symbols or characters.
An image is worth more than a 1000 words: This is the desired look output. Each of the symbols represent an unique color value of the image.
My problem is that I don't know how to print in the screen the symbols in the correct place. My first approach has been to use the "Wingdings" font and to put text on the places, but does not work as expected. The text changes sizes when zoomed, and does not behave accordingly to the rest of the plot.
I leave here a small piece of code that creates a small grid and uses an example image.
function drawChars (img)
if nargin==0
load mandrill
img=X(1:4:end,1:4:end);
end
chars=randperm(numel(unique(img)));
[h,w]=size(img);
% Form a grid
figure
hold on
for ii=0:h
plot([ii ii],[0 w],'k');
end
for ii=0:w
plot([0 h],[ii ii],'k');
end
axis equal;
axis([0 h 0 w])
%% This does not work as expected
for ii=1:h
for jj=1:w
text(ii, jj, char(chars(img(ii,jj))), 'fontname', 'Wingdings', 'fontsize',10);
end
end
end
Short question: What approach would you use to solve the problem?
NOTE: there is a problem with the choice of chars also, but ignore it for the time being (if char { is chosen does not work nicely)
With figure changed to f=figure
r=size(img).*16;
set(f,'paperunits','points')
set(f,'papersize',r)
set(f,'paperposition',[0 0 r]);
print(f,'example.png','-dpng');
Prints the created figure to a png of sufficient size.

Image gradually erased when overlayed with lines

Apart from the fact there exist special functions to plot vector fields, I have encountered a strange Matlab behaviour: Plotting an image (with imagesc or imshow) and overlaying it with colored lines (with plot or line) leads at some point to an erasement of the background image.
%% some data...
% random image
Image = rand(200,400);
% 900 lines of random color
color1 = rand(1,900);
color2 = rand(2,900);
color3 = rand(3,900);
% some positions
x = 31:60;
y = 31:60;
[X,Y] = meshgrid(x,y);
%% plot process
% plot Image (with 'imshow' or 'imagesc')
imshow(Image);
hold on;
% plot the lines (with 'line' or 'plot')
for i = 1:900
line([X(i), X(i)+1],[Y(i),Y(i)+2],'color',[color1(i),color2(i),color3(i)]);
if i == 100 % nothings happens to background image after 100 vectors
pause();
elseif i == 200 % gradually starts to change...
pause();
end
end
% ... at the end it is completely erased
Result: 100 lines
Result: 200 lines
Result: 900 lines
Nice side fact Saving the image as PNG restores the image (but destroys the line resolution).
This is not properly an answer, as it doesn't exactly explain why this is happening, but it provides a workaround, along with some more observations of the weird behaviour.
Scope:
I tried your example and indeed:
pre HG2 (R2013a): Same behavior than you described
HG2 (R2015a) : No problem, everything is there.
Workaround:
After a few trial and error, I worked out that it is a specific behaviour of the painter renderer in pre HG2 versions.
If you change the renderer to any other than the default painter, you get back your image and your superimposed lines.
set(gcf,'Renderer','zbuffer')
%// OR
set(gcf,'Renderer','opengl')
Observations:
Note that I also tried to:
display the lines first (no problem), then the image (and reorder using uistack) => same black image.
use multiple axes => black frame
And to show you how persistent is the glitch:
if you delete all the lines, the image does not reappear (=black frame).
if you delete all graphics objects, then re display the image => black frame
if you cla or even clf then re display the image => black frame
The only way I found to get the image displayed is to change the renderer as described above.
Printing/Saving
Initially, I thought the change of renderer was happening behind the scene when you were saving the figure, thereby allowing the final output to be fully displayed. Unfortunately, by exploring a bit more it doesn't seem to be so simple.
I tried different version with print (instead of saveas) since it allows you to select the renderer. For each renderer I chose 2 formats, PDF which uses the ghostscript engine, and PNG which uses the Matlab engine:
%%
print(1,'-dpng','-painters','testimageP.png')
print(1,'-dpng','-zbuffer' ,'testimageZ.png')
print(1,'-dpng','-opengl' ,'testimageO.png')
%%
print(1,'-dpdf','-painters','testimageP.pdf')
print(1,'-dpdf','-zbuffer' ,'testimageZ.pdf')
print(1,'-dpdf','-opengl' ,'testimageO.pdf')
Well, after results I am still unsure of what is happening. All these saved figures show the proper image and the lines on top... But:
The 3x png images (Matlab engine) are exactly similar. They do not even show slight difference in saturation like you can observe when you switch the renderer manually. This made me think that Matlab chose to ignore my renderer specification. It just decided which one was the most relevant and went ahead printing 3 times the same figure. So I thought may be the painter renderer wasn't used and that's why the images were shown.
Well not so fast. On the 3x pdf images (ghostscript engine) ... I can observe the small nuances between the 3 pictures ... so the renderer wasn't the same between them. The painter was used on one of them, and successfully rendered the image.
So in conclusion, it seems the painter renderer is only glitchy when applied to a (pre-HG2) figure!

When saving a figure as eps file, Matlab cuts off colormap labels

I have a figure generated using contourf with a colorbar. Most of my plots are fine, but when the values on the colorbar are of the order 10^{-3}, either the numbers 0.005 etc are written by the colorbar, or x10^{-3} is written at the top.
In both cases, part of the label gets cut off - either the 3 in x10^{-3} or half of the 5 in 0.005.
I can fix this using
set(gca, 'ActivePositionProperty', 'OuterPosition')
for the figure onscreen, but I need to save it in eps format. When I do this, the 3 (or 5) is cut off again!
I can also fix this if I manually pull the bottom right corner of the figure window to make it larger. But this changes the sizes of the axis labels etc in comparison to the plot itself so that they're different to all my other figures, i.e. the figures that I don't resize.
Any suggestions?
Matlab uses two sizes for figures: screen size (Position figure property) and the PaperSize. The former is used for displaying on screen, and the latter for printing or exporting to image formats other than .fig. I suspect this is the source of your problem.
Here is what you can try:
size = get(gcf,'Position');
size = size(3:4); % the last two elements are width and height of the figure
set(gcf,'PaperUnit','points'); % unit for the property PaperSize
set(gcf,'PaperSize',size);
This sets the size of the "paper" to export to .eps to the size of the figure displayed on screen.
If this doesn't work, you can try to play a bit with PaperSize or other "paper" related properties. The Figure Properties documentation page gives more info about properties.
Hope this helps!
The former suggestion is partly correct. Here is what i did:
set both, figure and paper units, to the same measure (figure has pixels, not points!)
set(gcf,'Units','points')
set(gcf,'PaperUnits','points')
do the same as suggested before:
size = get(gcf,'Position');
size = size(3:4);
set(gcf,'PaperSize',size)
the thing now is, that it might be shifted off the paper, as in my case, so put it back on
set(gcf,'PaperPosition',[0,0,size(1),size(2)])
I am not sure about the offset of [0,0], but what is a single point cut off :)
Try this to save your file to filename.eps:
set(gcf,'Units','points')
set(gcf,'PaperUnits','points')
size = get(gcf,'Position');
size = size(3:4);
set(gcf,'PaperSize',size)
set(gcf,'PaperPosition',[0,0,size(1),size(2)])
print(gcf,'filename','-depsc','-loose'); % Save figure as .eps file