How to remove white borders/space from an RGB image?
Show older comments
I have an RGB image that has white spaces around that I want to remove. I have tried imwrite using getframe but it did not work. It still shows the white spaces around the image. The attached png is the image I am working with and it is a 3-channel image. Thank you.

Answers (3)
filename = 'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1355503/image.png';
img = imread(filename);
R = img(:,:,1);
G = img(:,:,2);
B = img(:,:,3);
mask = R == R(1,1) & G == G(1,1) & B == B(1,1);
vertprofile = ~all(mask,1);
horzprofile = ~all(mask,2);
first_nb_column = find(vertprofile, 1);
last_nb_column = find(vertprofile, 1, 'last');
first_nb_row = find(horzprofile, 1);
last_nb_row = find(horzprofile, 1, 'last');
clipped = img(first_nb_row:last_nb_row, first_nb_column:last_nb_column, :);
imwrite(clipped, 'clipped_img.png');
imshow(img); title('with background')
imshow(clipped); title('without background')
Note that this will not work as well for JPEG images: it is likely to end up with a bit of background around the image. That is because JPEG blurs straight lines. The JPEG blurring process is not deliberately designed as a form of anti-aliasing, but it has the same effect.
1 Comment
Jay Ghosh
on 14 Apr 2023
Image Analyst
on 14 Apr 2023
0 votes
Try using imwrite with the actual image variable, not with using getframe() to get a screenshot of the displayed image.
8 Comments
Walter Roberson
on 14 Apr 2023
I believe they want to trim away the gray around the color background -- I think the title is asking about how to remove the white borders
Image Analyst
on 14 Apr 2023
The image I see doesn't have a white background, just a gray background frame and a cyan background in the image. The gray frame can be avoided by using imwrite instead of getframe, saveas, print, exportgraphics, or however else they generated the image file.
You know I strongly discourage figure capture if it can be avoided, but it's not clear that it can be easily avoided here. We'd really need to know how the figure is being created in order to know if it's an image or can be converted to a standard image compatible with imwrite()'s expectations.
With any luck, it is. If it's just a pseudocolored arbitrarily-scaled data, that might need to be converted.
Jay Ghosh
on 14 Apr 2023
Image Analyst
on 14 Apr 2023
Doing that would not change the image to add a white frame padding around the outside if the image. Please attach the original output_iceland.png so we can check it. But I strongly doubt it because I used that code and it does not add a white outer frame.
Also, it actually looks like you maybe started with a gray scale (i.e. indexed) image and then you applied a colormap to it to produce the pseudocolored RGB image. If you wanted the pseudocolored image you should not use getframe, you should use ind2rgb like this.
cmap = turbo(256); % Whatever colormap you want to use.
rgbImage = ind2rgb(grayImage, cmap);
imwrite(rgbImage, 'output_iceland2.png');
Jay Ghosh
on 27 May 2023
Image Analyst
on 27 May 2023
Again, "Please attach the original output_iceland.png "
and tell us how you saved it. Did you use a toolbar icon? Or save() or saveas() in the command window? Or use imwrite()?
There is no method that I know of that will consistently save an image from a figure at the correct size and without padding or interpolation artifacts, though using truesize() for image objects would be an improvement that the example in that link couldn't afford.
There are various ways to get the image without saving the figure, some of which are more convenient than others. You could do it using mat2gray() to normalize the data with respect to its extents (or optionally to some other limits). At that point, you could quantize it to the desired number of levels with gray2ind() and then apply an appropriate-length colormap using ind2rgb().
The problem with doing it that way is simply that gray2ind() and imagesc() do the quantization slightly differently. It might not matter much for a long color table, but it can be avoided. The answer I posted below uses a simplified version of MIMT gray2pcolor(), which does all the normalization/quantization/colormapping in one, and it can optionally emulate the quantization used by imagesc(). All you need is an arbitrarily-scaled grayscale image and a colormap. If the input range is unspecified, it will normalize with respect to data extrema, as does imagesc().
outpict = gray2pcolor(mydata,parula(256),'cdscale'); % scale WRT extrema
% ... or
outpict = gray2pcolor(mydata,parula(256),myclimits,'cdscale'); % scale WRT some other limits
DGM
on 14 Apr 2023
If you have some arbitrarily-scaled data, you need to map it however you mapped it when you plotted it. There's no reason to assume that it can be interpreted as an indexed image using direct mapping.
% some arbitrarily-scaled data
z = peaks(300); % 300x300
zrange = imrange(z); % the data extrema
% a colormap
CT = turbo(16);
% show the image and save it
imshow(z,[]) % colormapping is scaled to data extrema
colormap(CT)
saveas(gcf,'no.png') % some random size (759x611) and padded

Look at all that padding! How do you get saveas() to reliably save an image in the correct size with no padding? You don't.
% do the same thing, but generate an actual image
% this uses the same colormap, the same scaling limits
% and does the same quantization (gray2ind() won't)
outpict = gray2pcolor(z,CT,zrange,'cdscale');
imwrite(outpict,'yes.png') % the correct size (300x300), no padding

If you had tried to do direct colormapping using the same CT and zdata like so:
outpictdirect = ind2rgb(z,CT);
imwrite(outpictdirect,'notquite.png')
You would just get an error. Indexed images are maps of integer indices into the rows of a color table. Again, there is no reason to expect the z data to be integer-valued or to be on a scale that corresponds to the length of a color table.
Direct mapping like this is what you'd use when you have an actual indexed image (e.g. a GIF file). Scaled mapping is what you might be used to if you just want to display a single-channel image or data in pseudocolor with imagesc() or imshow(). While ind2rgb() alone works for direct mapping, the attached function does the latter.
4 Comments
Image Analyst
on 14 Apr 2023
I agree. That's what I told him : don't use saveas() which I suspect he was using. However first he said he was using getframe(), then he said that he didn't and just a simple call to imread followed immediately by a call to imwrite() (rather than saveas). So now I'm not really sure what was done. But hopefully with 3 of us saying to use imwrite() instead of saveas() and getframe() he will follow our advice.
I thought that he was misunderstanding the solution and thought that rewriting the padded image would remove the padding. I mean the padding has to come from somewhere, and it's not from an imread()/imwrite() cycle.
It is strange that it's gray. The default figure color hasn't been gray for a long time. It may be that the working images are rather old. That wouldn't bode well for the likelihood of the underlying data being available.
EDIT: no wait. I'm being dumb. That's the current figure color (240). The older color was 204. I'm just forgetting what colors things are because I run MATLAB on an inverted display.
Image Analyst
on 15 Apr 2023
Or is the default application background color taken from the operating system colors?
I don't think so. The colors shown in the various screenshots I can find seem to correspond to either 204 or 240, and those were all taken over the course of 20 years on both Linux and Windows. If MATLAB respected system theming, then I wouldn't be running an inverted X display, and we wouldn't have a giant contentious thread about dark themes.
That said, I have no idea what exactly newer versions do, and I haven't touched Windows in about a decade.
Categories
Find more on Images in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
