Handling video frames: how to get the frame with the original frame size after plotting?

Hi,
I am relatively new in handling videos in Matlab, so I am a bit confused. I am reading a video (with a certain frame size) and for every frame in the video, I want to plot something on top of the frame. Then, I'd like to take the frame (hence I am using getframe()), and save it into a new video file. So the goal is to have a new video with the same characteristics (frame size), but with additional information plotted on top of the frames.
My script goes something like this:
% Imports video
vid = VideoReader(path_input);
% Creates structure array
vidHeight = vid.Height;
vidWidth = vid.Width;
s = struct('cdata', zeros(vidHeight, vidWidth, 3, 'uint8'), 'colormap', []);
% Creates new video
vid_tj = VideoWriter(path_output, 'Motion JPEG AVI');
vid_tj.FrameRate = fr;
vid_tj.Quality = 100;
open(vid_tj);
% Generates video
for f = 1:15000 % f = frame
s(f).cdata = readFrame(vid);
imshow(s(f).cdata);
hold on
% Plots extra information
% Gets final frame and records video
frame_print = getframe(gca);
writeVideo(vid_tj, frame_print);
end
The main issue here is that "vid_tj" has indeed the original dimensions from "vid", but when I run "imshow", the plot I get has different dimensions (it gets smaller and I dont understand why), which leads to getting the wrong frame size when using getframe(), and therefore, the new video file is wrong and shows the frames cut on the edges. I tried changing getframe(gca) to getframe(gcf), which at least makes it possible to save the entire frame, but it saves the frame along with a white margin from the figure, which is not what I want either. I just want to get the same frame size (full picture) in the new video. Thanks in advance!

 Accepted Answer

getframe() essentially gets a screenshot of the contained image plus any graphics in the overlay. Thus it depends on what the displayed size of your image is on your screen. You could display it full screen, and then resize it down to match the size of the input image using imresize(). If you resized it after calling getframe, then it might resize it bigger and thus be blurry. So make sure it's bigger before you resize it. Or you might take a look at truesize().
Take a look at my attached demo.

4 Comments

% Imports video
vid = VideoReader(path_input);
% Creates structure array
vidHeight = vid.Height;
vidWidth = vid.Width;
s = struct('cdata', zeros(vidHeight, vidWidth, 3, 'uint8'), 'colormap', []);
% Creates new video
vid_tj = VideoWriter(path_output, 'Motion JPEG AVI');
vid_tj.FrameRate = fr;
vid_tj.Quality = 100;
open(vid_tj);
% Generates video
for f = 1:15000 % f = frame
s(f).cdata = readFrame(vid);
%imshow(s(f).cdata);
%hold on
% Plots extra information
% Gets final frame and records video
%frame_print = getframe(gca);
frame_print = s(f).cdata;
writeVideo(vid_tj, frame_print);
end
close(vid_tj);
This would work but I need to plot some stuff on the image before a save into the new video. I think this cant be done unless I open the frame, am I right? In my script s(f).cdata does not really store the new information, just the original frame, or how can I store the new plots there?
By the way, I've tried resizing as commented and that seems to work quite good.
I'll accept this answer since resizing definitely works and solves my problem. However, I did find out that the function readFrame() has an additional parameter which is readFrame(vid, 'native'),which also solves the issue as it respects the properties of the original video. But thanks for the replies.

Sign in to comment.

More Answers (1)

If possible, do not use getframe for this purpose. Instead, use Computer Vision Toolbox functions insertShape and insertText to draw on top of the cdata of the frame. The result will have exactly the same resolution as the cdata and there is no risk that the exact location of the axes or text might wobble a pixel or three as you proceed, which is a problem with the getframe approach.
If you need draw a patch with transparency then it might not be practical to use InsertShape, but you can use it to insert curves and bubbles and text labels.

1 Comment

I tried those functions, but I found them a bit trickier to do the drawings I want. But could be a good solution.

Sign in to comment.

Products

Release

R2020b

Community Treasure Hunt

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

Start Hunting!