Image gradually erased when overlayed with lines - matlab

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!

Related

MATLAB axes colors change when writing a GIF

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.

MatLab reducing bitdepth in plotted images?

I am plotting the feature matches between two scenes like this:
%...import, preprocessing, and stuff
%"Sandwich" Image1 and Image2 in a new image Image
ImSize=[size(Image1,1)+size(Image2,1),max(size(Image2,2),size(Image2,2))];
Image=zeros(ImSize);
Image(1:size(Image1,1),1:size(Image1,2))=Image1;
Image(size(Image1,1)+1:end,1:size(Image2,2))=Image2;
%show Image
imshow(Image,[]);
hold on
%plot keypoints and matching lines in all colors
cc=hsv(size(Keypoints1,1));
for ii=1:size(Keypoints1,1)
plot(Keypoints1(ii,1),Keypoints1(ii,2),'o','color',cc(ii,:))
plot(Keypoints2(ii,1),Keypoints2(ii,2)+size(Image1,1),'o','color',cc(ii,:))
line([Keypoints1(ii,1),Keypoints2(ii,1)],[Keypoints1(ii,2),Keypoints2(ii,2)+size(Image1,1)],'color',cc(ii,:),'LineWidth',0.5)
end
This normaly works alright and Matlab plots the entire bitdepth
but with increasing number of lines, I will start seeing a reduction in the bitdepth leading to binary images and even all black:
I know plotting this many lines is far from ideal, but still I would like to know why this is happening. Are there any mechanisms of matlab figures I should understand to explain this behaviour?
Note: this is only a problem displaying the images, saving them as .bmp,jpg,... will produce normal pictures.
try different renderers? Add this at the beginning of your script
h=figure;
set(h,'renderer','opengl');
Instead of 'opengl', also try 'painters' and 'zbuffer'

Convert just the content of a figure to an image in MATLAB

I am currently using getframe() and frame2im in MATLAB to convert a figure of a plot to an image.
I just realized that this is working almost like a screenshot of the figure, with all the axes and labels taken into account as well.
How can I convert JUST the contents of the figure (aka the "plot") into an image?
I don't really want to save all of them to file first.
You can use the getframe / cdata idiom. What this will do is that if you call getframe on the current frame in focus without any parameters, it will return a structure to you that contains a structure element called cdata. This stores the RGB pixel array of just the figure contents themselves. The axes and labels are not captured - only what is painted onto the figure is captured.
Here's an example to get you started:
im = imread('cameraman.tif');
imshow(im);
h = getframe;
out = h.cdata;
figure;
imshow(out); %// Should give you the contents within the imshow frame.
FWIW, I also answered this same question here, though it was for a different situation: keep new image when drawing lines by dragging the mouse in matlab
As far as i know, cdata DOES NOT WORK. I had a major problem recently with the same thing - the only work around i could find is to crop each image after using getframe and cdata - this will work fine for images that are all the same size (ugly as it is - you just need to find the grey edges in the image), but if the images are all different, this wont work (well, it wont work well. there might be some way to automatically adjust the crop size)

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

How do I overlap image with a graph in MATLAB?

I want to write a software that reads the satellite data from a text file and plots graph for different parameters of the oceans. The idea came from Oceonographic Data View(ODV).
My problem is plotting a graph on an image of the Indian ocean, where the image must be overlapped with the graph. Also, on zooming the area, the image with the graph could be zoomed.
How can I do this?
To load and display images, the Displaying Bit-Mapped Images tutorial from MathWorks may not be a bad place to start.
To overlay plots on the image, using hold on followed by plot should work.
An important part will be to have a sensible metric when displaying your image that allows you to place your overlays accurately. In the example below, notice the first and second arguments to image that define this; you could replace it by say linspace(0,1,size(X,1)) if you wanted it scaled between 0 and 1 instead of between 1 and 480 as below.
load mandrill
image(1:480,1:500,X) % display image
colormap(map)
hold on % prevent subsequent plot commands from destroying the image
plot([1 480],[100 100],'w','LineWidth',2) % plot an overlay line