I have 225 image with put together with the montage function in matlab. And I can show them with montage. But i cannot save the montage as a complete image, please help me.
path = uigetdir;
D=dir(fullfile(path,'*.tif'));
imcell = cell(1,numel(D));
imcropped = cell(1,numel(D));
figure(1);
title('Drag square to crop picture, end with a double click',...
'FontSize', 15 , 'HandleVisibility' , 'off' ) ;
axis equal
set( gca , 'NextPlot' , 'replacechildren') ;
imcell1 = imread(D(50).name);
[~, rect] = imcrop(imcell1);
close(figure(1));
%
for i = 1:numel(D)
imcell{i} = imread(D(i).name);
imcropped{i} = imcrop(imcell{i}, rect);
end
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
The output on montage "h" is just a number.
I would like to point out a better way to do it. While Benoit_11's way is technically correct, it limits the resolution of the image to the size of your screen. When you use getframe(gca), Matlab is effectively taking a screenshot of the current axes contents, at whatever size your figure window is currently in.
A better way to do this is to use the handle, as it references the actual graphical output of montage() instead of what it displays as. To save an image from the handle, you need to get the cdata from the object it references with get:
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
MyMontage = get(h, 'CData');
imwrite(MyMontage, 'FancyName.tif', 'tif');
This way you get the full resolution of the montage, not just the resolution from displaying it.
For more information on image handles: http://www.mathworks.com/help/matlab/creating_plots/the-image-object-and-its-properties.html
You're almost there! The value 'h' is actually the handles to the image object created by the montage you made in the figure. What you can do is use getframe to capture the content of the figure (graphics object) and save it as an image. Here is a very simple example, with the code going directly after yours
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
MyMontage = getframe(gca) %// Get content of current axes. I did it with sample images.
The output is the following:
MyMontage =
cdata: [384x1024x3 uint8] % Yours will be different
colormap: []
Hence you can save the actual data, stored in cdata, in a new file and you're good to go!
imwrite(MyMontage.cdata,'FancyName.tif','tif');
Related
I have a set of polygon vertices in in X, Y matrices and their colors are in RGB values in another matrix C.
I then use fill() function to generate patch objects that is displayed in a Matlab figure.
I want to create a bmp object from this figure. What I mean by a bmp object is the x,y coordinates of the pixels and there RGB values.
If I use the print() function, with '-dbmp' and a file name, matlab can write the bmp to a file. But then I have to read the file with imread() to create the bmp object.
Is there a way to create the bmp object without writing and reading to from a file?
Becauswe I have to perform this operation many times and writing and reading to file is time consuming and will reduce the life time of my disk too I guess.
Edit: code after editing according to answer
N = 5;
Tri = 100;
res = 200; %200 pixles per inch
G = zeros(Tri,9,N);
X = 2*rand(Tri,3,N);
Y = 2*rand(Tri,3,N);
R = randi([0 255],Tri,N)/255;
G = randi([0 255],Tri,N)/255;
B = randi([0 255],Tri,N)/255;
for c1=1:N
G(:,1:3,c1)= X(:,:,c1);
G(:,4:6,c1)= Y(:,:,c1);
G(:,7,c1)= R(:,c1);
G(:,8,c1)= G(:,c1);
G(:,9,c1)= B(:,c1);
end
for c2=1:N;
h = figure('Visible','off');
set(h, 'PaperUnits', 'inches', 'PaperPosition', [0 0 400 400]/res);
for c3 =1:Tri
h1 = fill(G(c3,1:3,c2), G(c3,4:6,c2), [G(c3,7,c2) G(c3,8,c2) G(c3,9,c2)]);
set(h1,'EdgeColor','None');
hold on;
end
%print(h,'-dbmp',['-r' num2str(res)],['file' num2str(c2)]);
F = getframe(h);
[a, b] = frame2im(F);
Tmp_v1 = a;
Tmp_v1 = Tmp_v1(:);
Norm_v1(c2) = norm(single(Tmp_v1));
end
Thank you.
If you have the current figure open, you can try the getframe idiom. Once you have access to this, you can access the frame's image data by looking at the cdata field in the structure. After you have this, you can use the imwrite command from MATLAB's image processing toolbox (let's hope you have it...) to write the image to file.
Here's an example:
x = 1 : 5;
y = 1 : 5;
plot(x,y); %// Plot a line
h = getframe;
img = h.cdata;
imwrite(img, 'testFrame.bmp');
This should be able to grab what is inside the current figure and save it to file. In this case, this will be a straight line from (x,y) = (1,1) to (x,y) = (5,5), with a slope of 1. Bear in mind that this won't save the title of the graph or the axes. This will only grab what is rendered inside the frame.
Edit from comments
Now that I know what you're really after, you want to generate a bunch of random polygons, then extract just the core image, without any axes or tick marks and so on. You'll have to modify your for loop where you're creating the images so that you want the figure to fill the entire window without any gray padding You'll also want to turn off the axis too. Also, when you're generating each image, you'll need to turn off the ticks. This is done with a combination of not writing any tick labels, as well as setting the tick length to 0. In other words, you'll need to modify your code so that it looks like this. You'll see where I inserted code by seeing the %// NEW statements in your code:
for c2=1:N;
h = figure('Visible','off');
subplot('position', [0 0 1 1]); %// NEW
axis off; %// NEW
set(h, 'PaperUnits', 'inches', 'PaperPosition', [0 0 400 400]/res);
for c3 =1:Tri
h1 = fill(G(c3,1:3,c2), G(c3,4:6,c2), [G(c3,7,c2) G(c3,8,c2) G(c3,9,c2)]);
set(h1,'EdgeColor','None');
set(gca,'xcolor','w','ycolor','w','xtick',[],'ytick',[]) %// NEW
set(gca,'Ticklength',[0 0]); %// NEW
hold on;
end
%print(h,'-dbmp',['-r' num2str(res)],['file' num2str(c2)]);
F = getframe(h);
close all; %// NEW
[a, b] = frame2im(F);
a = imresize(a, [400 400], 'nearest'); %// NEW
Tmp_v1 = a;
Tmp_v1 = Tmp_v1(:);
Norm_v1(c2) = norm(single(Tmp_v1));
end
This will still show you the frames being popped up for each image you're creating, but you should be able to get just pure image data at this point. Note that the images are still coming out as a bit larger than 400 x 400. This is due to the fact that once we have removed the borders and the tick marks and so on, the figure will stretch to fill the entire figure. To get around this, I use imresize and shrink the images back down to 400 x 400 as per your desired size.
Also, take note that every time you generate a new image, a new figure is spawned. Every time you call getframe, the figure with this randomly generated polygon image pops up, and getframe takes a snapshot of that current frame. There isn't a way to prevent this from happening, as you won't be able to take a snapshot of that figure. One way to get around this would be to close the figure after you grab the image. You can do a close all; after each call to getframe. That way, only one figure gets shown at any one time, but this still won't prevent the figure from showing up.
If I do find a solution to this, I'll let you know!
I want to save color image in original size (here is 146 by 220 pixel), but by this method the image will be saved in 1200 by 897 including extra marging. Actually the image will be save in larger size. I want to save it exactly in 146 by 220 pixel. Because i want to compare its pixels one by one with original image's. If i gain extra pixel comparing activity will be problematic for me.
Thank you in advance for your attention.
function []=doCmeans (imInput)
H = single(imInput(:));% original image is gray scale
nRegions = 5;
options = [2 100 1e-5 0];
[Center, U, obj_fun] = fcm (H,nRegions,options);
maxU = max(U);
for i = 1:nRegions
tmpindex = find (U(i,1))==maxU;
H (tmpindex)= i;
end
[r c]=size (imInput);
imFClass = reshape (H, r,c);
colormap(hsv(5));
h = figure('visible', 'off'); imshow(imFClass,[]);
print(h,'-djpeg',sprintf('ImFuzzy.jpg'));
end
The answer from Daniel is correct and is how you should do it, but if you still really need to save the image from the figure you have to do a couple of extra steps.
First you want to make sure that the figure has the exact same size of the image you're showing and then you want to get the content of the figure.
To do so, just give to imshow the arguments 'Border','tight'.
h = figure('visible', 'off'); imshow(imFClass,[], 'Border','tight');
Then you obtain and save the colour data from the frame as follow
myPic = getframe(h);
imwrite(myPic.cdata, 'yourPathName','yourFormat')
And this should do the trick.
However this is obviously useless if you just need to save the image and not really the content of a figure.
print saves the object you are passing, in this case a figure and not an image. The figure has probably a larger size. Use imwrite instead, and don't forget to pass the map.
In a for loop, I create a variable number of subplots that are displayed on a single figure. Can I also save each subplot as a separate, full size plot and image file (preferably JPG)?
Use copyobj to a new figure and then use saveas with the new figure handle:
Example code that YOU should have provided (see SSCCE):
figure
nLines = 2;
nColumns = 3;
handles = zeros(nLines,nColumns)
for line = 1:nLines
for column = 1:nColumns
handles(line,column)=subplot(nLines,nColumns,column+(line-1)*nColumns);
plot([line column]);
title(sprintf('Cool title (%d,%d)',line,column))
ylabel(sprintf('Ylabel yeah (%d,%d)',line,column))
xlabel(sprintf('Xlabel nah (%d,%d)',line,column))
end
end
Here I have the subplot handles saved, but supposing you don't have them saved:
axesH = findobj(gcf,'Type','axes','-not','Tag','legend'); % This will change the order from which the axes will be saved. If you need to save in the correct order, you will need access to the subplot handles
nAxes = numel(axesH)
newFig = figure;
for k=1:nAxes
newAxes=copyobj(axesH(k),newFig);
% Expand subplot to occupy the hole figure:
set(newAxes,'OuterPosition',[0 0 1 1]);
tightInset=get(newAxes,'TightInset');
set(newAxes,'Position',[tightInset(1:2) [1 1]-(tightInset(3:4)+tightInset(1:2))])
saveas(newFig,sprintf('axes_%d.jpg',k),'jpg');
delete(newAxes);
end
delete(newFig);
Example of one axes saved:
To remove the deadspace I used information available on this topic.
Say you have the handle to the subfigure's axis, ha, you can use getframe and frame2im as follows,
F = getframe(ha);
[im,map] = frame2im(F);
if isempty(map)
imwrite(im,'subframe.jpg');
else
imwrite(im,map,'subframe.jpg');
end
Note that this will save the axis exactly how it appears on your screen, so resize the figure to your liking before saving. To use as much figure real estate as possible, tryout the subfigure_tight function on MATLAB Central.
EDITTED:
Hii,
sorry not mentioning it earlier, what I need to do is to display 6 images in the same figure at the same time. Besides, at every image (frame) I need to draw some points (my code tracks the moves of the face - the eyes, nose, lips.)
I have 246 images (frames)
this is the main functions I use:
// The points/ coordinates of the lips, eyes and nose of the image "i".
Points = createPointsStructure (landmarks , i , NumOfLandarkPerFrame);
// Draw landmarks and splines on the frame i (and draw/show the frame)
DrawAllPointsOnFace (pointArr , Points , img , 1 , position, i);
Any ideas how can I do it?
I need to write a code that displays 6 images in the same figure (at the same time). and lets the user to choose one of the images to edit it (by clicking on it).
Any help how can I do it?
Thanks in advance.
Here is a simple example to get you started:
function ImagesExample()
%# read images in a cell array
imgs = cell(6,1);
for i=1:6
imgs{i} = imread( sprintf('AT3_1m4_%02d.tif',i) );
end
%# show them in subplots
figure(1)
for i=1:6
subplot(2,3,i);
h = imshow(imgs{i}, 'InitialMag',100, 'Border','tight');
title(num2str(i))
set(h, 'ButtonDownFcn',{#callback,i})
end
%# mouse-click callback function
function callback(o,e,idx)
%# show selected image in a new figure
figure(2), imshow(imgs{idx})
title(num2str(idx))
end
end
Another function to look into is the MONTAGE function from the IPT Toolbox:
%# given the above cell array `imgs`
montage( cat(4,imgs{:}) )
I want to read an image into MATLAB, draw a rectangle on it, and then save the image.
Also, I'm just learning MATLAB--please be gentle. It seems like it should be simple, but I can't seem to do it.
im = imread('image.tif');
imshow(im);
rectangle('Position', [100, 100, 10, 10]);
imwrite(im, 'image2.tif');
Even though I can see the rectangle on the image, the saved image does not display the rectangle. How can I save the image and have the rectangle show up?
FWIW, I've already tried saveas(), but that gives me a HUGE image. Is there a way to use saveas() and make the saved image the correct size?
The reason the rectangle doesn't show up in the saved image is because you are not modifying the variable im, which stores the image data. The rectangle is simply a plot object displayed over the plotted image. You have to modify the image data itself.
Typically, images read into MATLAB are loaded as an N-by-M-by-3 matrix (i.e. an N-by-M pixel image with RGB (red-green-blue) values for each pixel). Usually, the image data is a uint8 data type, so the RGB values range from 0 to 255. If you wanted to change the RGB value for a given pixel, you would do the following:
im = imread('test.jpg'); % Load a jpeg image
im(1,1,1) = 255; % Change the red value for the first pixel
im(1,1,2) = 0; % Change the green value for the first pixel
im(1,1,3) = 0; % Change the blue value for the first pixel
imwrite(im,'new.jpeg'); % Save modified image
There are different ways you can modify more than one pixel at a time (i.e. a rectangular area), which will require that you look into how to index into multidimensional arrays. For more detail about how different types of images are read into MATLAB (i.e. truecolor vs. indexed), I would check the documentation for imread.
to the question in the top, there is quite a simple solution provided by matlab:
% you so far
im = imread('image.tif');
imshow(im);
rectangle('Position', [100, 100, 10, 10]);
% now you use "getframe" and "frame2im"
f = getframe(gca);
im = frame2im(f);
imwrite(im,'image2.tif');
that worked great for me when i also drew a rectangle on an image and tried to save it. If you want to keep on working with it, just add
imread('image2.tif');
and keep on working with it :)
Regards, Laura
There's actually a bug at The MathWorks site about this issue. Too bad they don't spell out a real answer (as, IMHO, holding up a ruler to your monitor is not a real solution).
Using the print command, you must manually change the -r parameter until the size of the saved image matches the size of the input image. The -r parameter specifies the DPI of the saved image. Since most screens have different DPIs, there's no one-size-fits-all solution.
im = imread('image.tif');
f = figure, imshow(im, 'Border', 'tight');
rectangle('Position', [100, 100, 10, 10]);
print(f, '-r80', '-dtiff', 'image2.tif');
Use the code above, tweak the -r parameter until it looks right, and voilĂ !
following up to jacobko answer. Setting the figures paperposition and paperunits properties and the axis units and position properties usually gives me the desired results without having to tweak the resolution. So,
>> im = imread('image.tif');
>> f = figure, imshow(im);
>> r=rectangle('Position',[100, 100,10,10]);
>> set(r,'edgecolor','b') % change the color of the rectangle to blue
>> set(f,'units','centimeters','position',[1 1 2.5 2.5]) % set the screen size and position
>> set(f,'paperunits','centimeters','paperposition',[1 1 2.5 2.5]) % set size and position for printing
>> set(gca,'units','normalized','position',[0 0 1 1]) % make sure axis fills entire figure
>> print(f, '-r80','-dtiff','image2.tif')
The output image, image2.tif, will now be 2.5cm by 2.5cm at a resoultion of 80dpi without the border around the axis.
If you want to save im, you must first modify its value.
I am not familiar with the rectangle function,
but you can do the following (brute force):
im = imread('image.tif');
im(100:110,100)=0;
im(100:110,110)=0;
im(100,100:110)=0;
im(110,100:110)=0;
imshow(im);
imwrite(im, 'image2.tif');
Note, the code above is for gray scale image, if your image is an RGB image, you will need to do the following:
im(100:110,100,:)=0;
....
You might be able to use getframe to grab the modified image from the figure window. I think you could pass the cdata and colormap fields of the structure returned by getframe to imwrite as the image and its colormap, respectively.
[f,p] = uigetfile('*.*');
I = imread([p,f]);
imwrite(I,'img12.tif');%
Any name we can give for saving the image
Automatically it will save in your folder and you can browse any image.
close all; clear; clc;
r = 240 ; c = 320;
fig = figure('Visible', 'off');
imshow( zeros(r,c) );
hold on;
plot([c-fix(c/2),c-fix(c/2)],[r-fix(r/2),r-fix(r/2)],'r*', 'MarkerSize', 10 );
% Sets position and size of figure on the screen
set(fig, 'Units', 'pixels', 'position', [100 100 c r] );
% Sets axes to fill the figure space
set(gca, 'Units', 'pixels', 'position', [0 0 c+1 r+1 ]);
% Sets print properties; Looks like 1 pixel = (3/4)th of a point
set(fig, 'paperunits', 'points', 'papersize', [fix((c-1)*(3/4))+1 fix((r-1)*(3/4))+1]);
set(fig, 'paperunits', 'normalized', 'paperposition', [0 0 1 1]);
print( fig, sprintf('-r%d', ceil(72*(4/3))), '-dpng', 'image.png' );
im = imread( 'image.png');
figure; imshow(im);