MATLAB plot image margin removal and aspect ratio keeping
12 次查看(过去 30 天)
显示 更早的评论
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 个评论
DGM
2022-11-17
Why not save the image itself instead of saving a rescaled and padded screenshot of the image?
采纳的回答
更多回答(2 个)
Walter Roberson
2022-11-17
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 个评论
DGM
2022-11-17
编辑:DGM
2022-11-17
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 个评论
DGM
2022-11-18
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.
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!