MATLAB plot image margin removal and aspect ratio keeping
13 views (last 30 days)
Show older comments
I have following code which basically trying to create a video based on a series images of size 256 X 256 X 3, where 3 is the RGB channls:
close all
clc
%% creating image volum
img = phantom(256);
img = repmat(img, [1,1,3]);
figure(1)
vidfile = VideoWriter('testVideo.mp4','MPEG-4');
open(vidfile);
%% loop to ceate images with different colors
for n = 1:120
a = n/120;
img(:,:,1) = img(:,:,2)*a;
img(:,:,3) = img(:,:,2)*(1-a);
imagesc(img), axis off
set(gca, 'Position', [0 0 1 1])
drawnow
videoFrame(n) = getframe(gcf);
writeVideo(vidfile,videoFrame(n));
end
close(vidfile)
However, although I got rid of the margin, I cannot get the image aspect ratio right. The image looks like this:
The goal is to remove the margin of the plot and maintain the aspect ratio of the images. In this case, it should be a square image with size 256 X 256 X3 that looks like this:
Any pointers? Some sample code would be very nice. Thanks
1 Comment
DGM
on 17 Nov 2022
Why not save the image itself instead of saving a rescaled and padded screenshot of the image?
More Answers (2)
Walter Roberson
on 17 Nov 2022
nonblack = any(img,3);
horzprofile = any(nonblack, 1);
firstcol = find(horzprofile,1,'first');
lastcol = find(horzprofile,1,'last');
occupied_col = lastcol - firstcol + 1;
vertprofile = any(nonblack, 2);
firstrow = find(vertprofile,1,'first');
lastrow = find(vertprofile,1,'last');
occupied_row = lastrow - firstrow + 1;
occupied_space = max(occupied_row, occupied_col);
leftpad = floor((occupied_space - occupied_col)/2);
rightpad = occupied_space - occupied_col - leftpad;
uppad = floor((occupied_space - occupied_row)/2);
downpad = occupied_space - occupied_row - uppad;
padded = zeros(occupied_space, occupied_space, size(img,3), class(img));
padded(uppad+1:uppad+occupied_space, leftpad+1:leftpad+occupied_space, :) = img(firstrow:lastrow, firstcol:lastcol, :);
Now padded is a square image with no margin at all on one pair of sides and with possible margin on the other pair of sides, with the image centered.
The difference between this code and using imcrop() to crop slightly away from the occupied portion of the image, is that there is the theoretical possibility that the original occupied area was too close to an edge to extract padding evenly from both sides.
If you need the output to be a particular size, then you can imresize() it, knowing that padded is square to start with and so there will not be any aspect ratio changes if resized to a square.
0 Comments
DGM
on 17 Nov 2022
Edited: DGM
on 17 Nov 2022
Save the image, not a screenshot of the image. Saving things by capturing figures is a poorly controlled workflow and is often destructive to image quality.
% creating image volum
img = phantom(256);
img = repmat(img, [1,1,3]);
figure(1)
vidfile = VideoWriter('testVideo.avi'); % for some reason mp4 won't work in my version/env
open(vidfile);
% loop to ceate images with different colors
for n = 1:120
a = n/120;
img(:,:,1) = img(:,:,2)*a;
img(:,:,3) = img(:,:,2)*(1-a);
% this isn't necessary to construct the file
%imagesc(img), axis off
%set(gca, 'Position', [0 0 1 1])
%drawnow
writeVideo(vidfile,min(max(img,0),1));
end
close(vidfile)
The result (as a GIF)
3 Comments
DGM
on 18 Nov 2022
You can still just uncomment those lines to get a preview. I normally avoid displaying previews in a loop like that, since it tends to just slow everything down.
The point is that images of figures are not the original image. So long as it's the source image that's being saved, the display process is not necessary to save the image. You can still do both if you want.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!