Trouble in making video from frames, can anyone help?

Hi,
I have around 1000 pictures which is like 30th frame from each second of 30 fps. I am trying to make a video with 1 fps hence I am using the code below but the problem is this code is not compiling the video in a sequence manner like frame30.jpg, frame60. jpg instead frames are messed up in video like starting from middle then finish then add the starting frames at the end. what i want is a it reads a frames from first to last hence made a video. I am not sure where I am making a mistake.
Code:
imgFile =dir('*.jpg');
N = length(imgFile);
% create the video writer with 1 FPS
writerObj = VideoWriter('compilingFrames.avi');
writeObj.FrameRate = 1;
%Open the video writer
open(writerObj);
%write the frame to the video
for i=1:N
img = imgFile(i).name;
I = imread(img);
writeVideo(writerObj,I);
end
% close the writer object
close(writerObj);

 Accepted Answer

Or if the frames are named strictly sequentially and have a predictable prefix, then generate the file names instead of reading them from the directory.
videofile = 'compilingFrames.avi';
writerObj = VideoWriter(videofile);
writeObj.FrameRate = 1;
%Open the video writer
open(writerObj);
N = 1;
while true
filename = sprintf('frame%d.jpg', N);
if ~exist(filename); break; end
try
I = imread(filename);
catch ME
fprintf('Failed to read file "%s", giving up', filename);
break;
end
writeVideo(writerObj, I);
N = N + 1;
end
%to get here we ran out of sequential files, or a file was not readable
% close the writer object
close(writerObj);
if N == 1
fprintf('No frames were written at all, deleting movie!\n');
delete(videofile);
elseif N == 2
fprintf('Only one frame was written to movie, but need at least two for valid movie, deleting movie\n');
delete(videofile);
else
fprintf('Wrote %d frames succesfully\n', N-1);
end

4 Comments

Hi, thanks for the help and see the error below. I am not understanding why it is not writting the frames as the images name are in sequence like frame30.jpg, frame60.jpg,frame90.jpg,frame120.jpg, and so on!
error:
Warning: No video frames were written to this file. The file may be invalid.
> In VideoWriter/close (line 282)
In compilingframes_2 (line 23)
No frames were written at all, deleting movie!
videofile = 'compilingFrames.avi';
writerObj = VideoWriter(videofile);
writeObj.FrameRate = 1;
%Open the video writer
open(writerObj);
N = 1;
while true
filename = sprintf('frame%d.jpg', 30*N);
if ~exist(filename); break; end
try
I = imread(filename);
catch ME
fprintf('Failed to read file "%s", giving up', filename);
break;
end
writeVideo(writerObj, I);
N = N + 1;
end
%to get here we ran out of sequential files, or a file was not readable
% close the writer object
close(writerObj);
if N == 1
fprintf('No frames were written at all, deleting movie!\n');
delete(videofile);
elseif N == 2
fprintf('Only one frame was written to movie, but need at least two for valid movie, deleting movie\n');
delete(videofile);
else
fprintf('Wrote %d frames succesfully\n', N-1);
end
Thanks, it worked with the frame sequence but still there is one problem which is the frame rate I wanted the frame rate to be 1 fps but it is going like 100 fps, video is too fast, even I mention in the code 1 fps but it did not implement it.
The line that is already in the code,
writeObj.FrameRate = 1;
should take care of that.
As an experiment, after the above code, try
v = VideoReader(videofile);
if isfield(v, 'FrameRate')
fprintf('Frame rate stored in file is: %g\n', v.FrameRate);
else
fprintf('Somehow file does not have any recorded FrameRate??\n');
end
clear v

Sign in to comment.

More Answers (1)

Chunru
Chunru on 31 Aug 2021
Edited: Chunru on 31 Aug 2021
If your image file names are well behaved, you can do a simple sorting of the file names:
imgFile =dir('*.jpg');
imgFile = sort({imgFile.name}'); % sort the file name
N = length(imgFile);
% create the video writer with 1 FPS
writerObj = VideoWriter('compilingFrames.avi');
writeObj.FrameRate = 1;
%Open the video writer
open(writerObj);
%write the frame to the video
for i=1:N
img = imgFile{i}; %.name;
I = imreadimg);
writeVideo(writerObj,I);
end
% close the writer object
close(writerObj);

4 Comments

Error coming as .name has been removed and it is looking character vector or string scaler. Error is below!
Error using imread>parse_inputs (line 501)
The file name or URL argument must be a character vector or string scalar.
Error in imread (line 339)
[source, fmt_s, extraArgs, was_cached_fmt_used] = parse_inputs(cached_fmt, varargin{:});
Error in compilingframes_1 (line 14)
I = imread(img);
Change to the following line
%img = imgFile(i);
img = imgFile{i};
it compiled the frames into video same as before, no difference. Is there anyway I can define int he code that start read the frame from frame30.jpg then go to frame60.jpg, then go to frame90.jpg until the last frame ?
Yes. You can define the frame sequence with the order you want:
imgFile ={'filename1.jpg', 'filename2.jp', ....}

Sign in to comment.

Categories

Find more on Convert Image Type 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!