How can I modify an image without showing it? - image

I have a code that loads an image to a plot, draws a rectangle on it an after this saves the image into a png file:
figure('Visible', 'off');
imshow(im)
hold on
for n=1:size(windowCandidates,1)
rectangle('Position',[x,y,w,h],'EdgeColor','g','LineWidth',2)
end
f=getframe;
[img_bound,map]=frame2im(f);
imwrite(img_bound, strcat(directory, 'name.', 'png'));
hold off
How can I do the same without displaying it in a figure? Just modifying it and saving, I dont want the user to see all this process)
Thanks!

You can make a figure invisible with:
figure('Visible', 'off');
And then just write it out as Matlab fig via:
saveas(gcf, 'path/to/filename');
or using the print command to png is this case
print('-dpng', 'path/to/filename');
Similar question with good answers and explanations else where on stackoverflow
Update
Thanks to Steve for pointing to this undocumented matlab function
function so;
close all;
im = imread('cameraman.tif');
hfig = figure('Visible', 'off'), imshow(im, 'Border', 'tight');
for n=1:2
rectangle('Position', [20*n, 20*n, 50, 50], 'EdgeColor', 'g', 'LineWidth', 2)
hold on;
end
F = im2frame(zbuffer_cdata(gcf));
imwrite(F.cdata, 'test.png');
% Function copied from
% http://www.mathworks.com/support/solutions/en/data/1-3NMHJ5/?solution=1
% -3NMHJ5
%
function cdata = zbuffer_cdata(hfig)
% Get CDATA from hardcopy using zbuffer
% Need to have PaperPositionMode be auto
orig_mode = get(hfig, 'PaperPositionMode');
set(hfig, 'PaperPositionMode', 'auto');
cdata = hardcopy(hfig, '-Dzbuffer', '-r0');
% Restore figure to original state
set(hfig, 'PaperPositionMode', orig_mode);

Related

How do I save an image generated by imshow(image) into a variable?

This is my code. I want to save the image displayed on imshow(img) into a variable to use it later. Thanks!
img=imread('image1.bmp');
figure(1), imshow(img);
[r c]=ginput(4);
Bw=roipoly(img,r,c);
% figure,imshow(Bw)
[R C]=size(Bw);
for i=1:R
for j=1:C
if Bw(i,j)==1
img(i,j)=img(i,j);
else
img(i,j)=0;
end
end
end
figure,
imshow(img); title ('Output Image');
You can use the classic getframe / cdata idiom. With the figure window open, simply do this:
figure;
imshow(img); title('Output Image');
h = getframe;
im = h.cdata;
h is a handle to the current frame that is open, and the cdata field contains image data for the frame. The above code stores the frame image data into a variable called im for use for later.
Minor Comment
That for loop code to set the output is a bit inefficient. You can do this completely vectorized and you'll notice significant speedups.
This code:
for i=1:R
for j=1:C
if Bw(i,j)==1
img(i,j)=img(i,j);
else
img(i,j)=0;
end
end
end
... can be replaced with:
img(~BW) = 0;
I also don't understand why you'd need to store the image data inside the frame of imshow... when img already contains your data and you are ultimately showing the data contained in img. Why can't you just use img directly for your application? Nevertheless, the above solution will work.

Print image to pdf without margin using Matlab

I'm trying to use the answers I found in these questions:
How to save a plot into a PDF file without a large margin around
Get rid of the white space around matlab figure's pdf output
External source
to print a matlab plot to pdf without having the white margins included.
However using this code:
function saveTightFigure( h, outfilename, orientation )
% SAVETIGHTFIGURE(H,OUTFILENAME) Saves figure H in file OUTFILENAME without
% the white space around it.
%
% by ``a grad student"
% http://tipstrickshowtos.blogspot.com/2010/08/how-to-get-rid-of-white-margin-in.html
% get the current axes
ax = get(h, 'CurrentAxes');
% make it tight
ti = get(ax,'TightInset');
set(ax,'Position',[ti(1) ti(2) 1-ti(3)-ti(1) 1-ti(4)-ti(2)]);
% adjust the papersize
set(ax,'units','centimeters');
pos = get(ax,'Position');
ti = get(ax,'TightInset');
set(h, 'PaperUnits','centimeters');
set(h, 'PaperSize', [pos(3)+ti(1)+ti(3) pos(4)+ti(2)+ti(4)]);
set(h, 'PaperPositionMode', 'manual');
set(h, 'PaperPosition',[0 0 pos(3)+ti(1)+ti(3) pos(4)+ti(2)+ti(4)]);
% save it
%saveas(h,outfilename);
if( orientation == 1)
orient portrait
else
orient landscape
end
print( '-dpdf', outfilename );
end
Results in this output:
As you can see the 'PaperSize' seems to be set not properly. Any idea of possible fixes?
NOTE
If I change the orientation between landscape and portrait the result is the same, simply the image is chopped in a different way.
However if I save the image with the saveas(h,outfilename); instruction the correct output is produced.
Why is this? And what is the difference between the two saving instructions?
Alltogether the answers you mentioned offer a lot of approaches, but most of them didn't worked for me neither. Most of them screw up your papersize when you want to get the tight inset, the only which worked for me was:
set(axes_handle,'LooseInset',get(axes_handle,'TightInset'));
I finally wrote a function, where I specify the exact height and width of the output figure on paper, and the margin I want (or just set it to zero). Be aware that you also need to pass the axis handle. Maybe this functions works for you also.
function saveFigure( fig_handle, axes_handle, name , height , width , margin)
set(axes_handle,'LooseInset',get(axes_handle,'TightInset'));
set(fig_handle, 'Units','centimeters','PaperUnits','centimeters')
% the last two parameters of 'Position' define the figure size
set(fig_handle,'Position',[-margin -margin width height],...
'PaperPosition',[0 0 width+margin height+margin],...
'PaperSize',[width+margin height+margin],...
'PaperPositionMode','auto',...
'InvertHardcopy', 'on',...
'Renderer','painters'... %recommended if there are no alphamaps
);
saveas(fig_handle,name,'pdf')
end
Edit: if you use painters as renderer saveas and print should produce similar results. For jpegs print is preferable as you can specify the resolution.

updating data within same GUI in MATLAB

I've created one image editor window in MATLAB, which includes various operations including brightness, contrast, crop, rotate etc.., In this GUI, each operations has its own function call backs.
My problem is with linking one function with another. if i crop image, then if i change brightness my current code changes brightness of original image rather than cropped image.
similarly at first i if change brightness and then if i crop, my code will crop original image rather than brightened image.
Below code is to change brightness.
function slider2_Callback(hObject, eventdata, handles)
fname = getappdata(0, 'fname');
[a, map] = imread(fname);
x = ind2rgb(a, map);
b = get(handles.slider2,'value');
j = imadjust(x,[],[],b);
axes(handles.axes1);
imshow(j);
Below code is to crop
function crop_Callback(hObject, eventdata, handles)
fname = getappdata(0, 'fname');
[a, map] = imread(fname);
x = ind2rgb(a, map);
new = imcrop(x);
axes(handles.axes1);
imshow(new);
Suppose say at first if i crop image, then next step if i change brightness of cropped image later some other operation on above edited image, How can i link one operation with another?
I think it's because you are not updating your handles after changing them, hence the code is still referring to the old handle.
Try guidata(hObject, handles); right after cropping.
Instead of having global variable for the file name, you need to have a global variable for the image. So in each of your callbacks you can manipulate with your image without reading the image every time. Also, you should keep your changes at the end of each call back by setappdata. Thus, your callbacks would be something like this:
function changeimage_Callback(hObject, eventdata, handles)
image = getappdata(0, 'image');
% manipulation on image
% show image
setappdata(0, 'image', image);
If you have one GUI, I think it would be more convenient if you do such a thing with handles. That is, load your image in your GUI and keep it like this:
handles.image = imread(filename);
guidata(hObject, handles);
Then your callbacks would be like this:
function changeimage_Callback(hObject, eventdata, handles)
% manipulation on handles.image
% show handles.image
guidata(hObject, handles);
Instead of loading the original image file to perform your manipulation on, load the image from the figure.
In other words, replace
fname = getappdata(0, 'fname');
[a, map] = imread(fname);
x = ind2rgb(a, map);
with
x = getimage(handles.axes1);
I didn't test the code but it should fix your problem with a minimal amount of work.

Movie redraws contour lines

I made a contourfm plot with white contour lines.
I used 'LineColor', 'white' but in a movie, the white lines propagate after each image instead of redrawing. The colors on the image itself redraws automatically. What am I doing wrong?
Also, when viewing the image, it shows up small on the top left hand corner. A similar script before did not cause this issue. Anyone know why?
% Create movie
nFrames = 893; % Number of frames
for k = 1:nFrames % Create movie
% Eqdconic script
% Define figure and axes
fg1 = figure(1);
axesm('MapProjection','eqdconic', 'MapParallels', [], 'MapLatLimit',[-79.625 -59.625],'MapLonLimit',[190.625 250.625])
framem on; gridm on; mlabel on; plabel on; hold all;
% Plot data
frame = dataSST_movie(:,:,k);
image = contourfm(Y,X,frame, 'LineColor', 'white'); % Change contour lines to white
mov(k) = getframe(gcf);
end
close(gcf)
% % Save as AVI file
movie2avi(mov, 'SST_20110101to20130611_0.25grid.avi', 'compression', 'none', 'fps', 4);
The image = contourfm() part is what I'm talking about; is there some command like redraw that I need to use?
Just use clf before end. As for the size issue, check MapLatLimit and MapLonLimit. If they are correct, it should work.

Matlab: How can I display several outputs in the same image?

Let's say my image is img=zeros(100,100,3), my outputs are several ellipse which i get using a created function [ret]=draw_ellipse(x,y,a,b,angle,color,img), I can display one ellipse using imshow(ret).For the moment, I'm trying to show serval ellipse in the image. But i don't know how to code it. will ‘for loop’ work or I need to hold them?
If this is related to what you were doing in your previous question, then what you need to do is to pass the result of one iteration as input to the next.
So assuming that the function [ret]=draw_ellipse(x,y,a,b,angle,color,img) you mentioned takes as input an image img and returns the same image with an ellipse drawn on it, you could do this:
%# ellipses parameters
%#x = {..}; y = {..};
%#a = {..}; b = {..};
%#angle = {..}; color = {..};
img = zeros(200,100,'uint8'); %# image to start with
for i=1:10
img = draw_ellipse(x{i},y{i}, a{i},b{i}, angle{i}, color{i}, img);
end
imshow(img)
I'm a bit unsure of what you want. You want to show several ellipse in one image, like plotting several graphs with hold on?
There is no equivalent command for images, but a simple solution is to add the ellipses into one image and show that one:
several_ellipse = ellipse1 + ellipse2 + ellipse3;
imshow(several_ellipse)
Presumably you want to pass ret as the final input to the next call to draw_ellipse.

Resources