13

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?

gnovice
  • 125,304
  • 15
  • 256
  • 359
jacobko
  • 8,740
  • 7
  • 32
  • 36
  • for the last part, this is possibly related: http://stackoverflow.com/questions/3600945/printing-a-matlab-plot-in-exact-dimensions-on-paper – Amro Jun 29 '11 at 19:40

8 Answers8

19

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.

gnovice
  • 125,304
  • 15
  • 256
  • 359
13

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

Laura
  • 131
  • 1
  • 2
  • 1
    saving the gca frame does the trick but will not save the image in its original resolution. – Luqman Jul 23 '14 at 10:45
  • The output image size is the same as the input image size, so this does appear to preserve the resolution of the original image. This was the THE solution for me. Many Thanks! – Norbert S Mar 04 '18 at 22:05
10

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à!

jacobko
  • 8,740
  • 7
  • 32
  • 36
  • This sounds like a good solution; just 2 small issues. First, having to try a bunch of settings for the -r parameter is a little annoying. Second, I think that the output image would include the border that appears around the axes, which is undesirable in some cases. – gnovice Feb 22 '09 at 22:12
  • 1
    I updated the imshow() function with the 'Border' parameter as 'tight' so the gray border around the image does not appear. – jacobko Feb 25 '09 at 14:58
7

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.

Community
  • 1
  • 1
Azim J
  • 8,260
  • 7
  • 38
  • 61
3

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;
 ....
LiorH
  • 18,524
  • 17
  • 70
  • 98
2
[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.

Sanoop Surendran
  • 3,484
  • 4
  • 28
  • 49
Som
  • 21
  • 1
2

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.

SCFrench
  • 8,244
  • 2
  • 31
  • 61
  • getframe is a nice and quick solution. However, I think there is one caveat. The dimensions of the image it creates will depend on the figure size. If you plotted a big image (say 1024-by-1024) in a small window (say 700-by-700), you will lose some resolution on your image. – gnovice Feb 22 '09 at 21:19
1
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);