MATLAB plot image margin removal and aspect ratio keeping

조회 수: 12 (최근 30일)
Nick Tsui
Nick Tsui 2022년 11월 17일
편집: Nick Tsui 2022년 11월 21일
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
DGM 2022년 11월 17일
Why not save the image itself instead of saving a rescaled and padded screenshot of the image?

댓글을 달려면 로그인하십시오.

채택된 답변

Nick Tsui
Nick Tsui 2022년 11월 21일
편집: Nick Tsui 2022년 11월 21일
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])
truesize(gcf,[256,256]) % adding this line here to make the image show true aspect ratio
drawnow
videoFrame(n) = getframe(gcf);
writeVideo(vidfile,videoFrame(n));
end
close(vidfile)

추가 답변 (2개)

Walter Roberson
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.

DGM
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
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.
Nick Tsui
Nick Tsui 2022년 11월 21일
In this case I'd like to see the update of the image while generating the video. I don't really care the additional time it might take.
I think you answer it excellent, and it will be very useful when the plot is not needed to be seen.
Thank you very much.

댓글을 달려면 로그인하십시오.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by