Batch process AVI files into PNG/JPG

Hi all,
I am working with a large dataset of .avi files which I need to split into .png for further analysis. From previous questions on here, I've derived some code which is doing this quite nicely for one avi file:
clc;
clear;
%Set current directory to folder containing this m file
cd('C:\Users\...');
%Open file to be converted
movieFullFileName = fullfile(cd, '26032019.AVI');
%Read in avi file
videoObject = VideoReader(movieFullFileName)
%Get some info from avi file
[folder, baseFileName, extentions] = fileparts(movieFullFileName);
%Create output folder:
folder=pwd;
outputFolder = sprintf('%s/Frames', folder);
%Determine how many frames there are
numberOfFrames = videoObject.NumberOfFrames;
vidHeight = videoObject.Height;
vidWidth = videoObject.Width;
for x=1 : numberOfFrames
frame = read(videoObject,x)
outputBaseFileName = sprintf('-%4.4d.png', x); %output filename, each frame numbered from 0001
outputFullFileName = fullfile(outputFolder, strcat(baseFileName, outputBaseFileName)); %output filename
imwrite(frame, outputFullFileName, 'png'); %write output file
end
At the moment, I'm only converting one video file and it takes just over a minute to process which seems quite long. Once I am finished collecting my data I'll have over 1500 videos so I am wondering if, at this early stage, there is anything I can do to refine or speed up my code?
Secondly, I would like to introduce another for loop which lets me apply this code to a series of avi files within a folder. Can anyone point me in the right direction with this?
Thanks!!

6 Comments

Hi everyone, I have managed to modify the code to include a for loop:
%%08 July 2019, Louise Wilson
%Code to split .avi file into many .jpg files.
%Same code but attempting for loop to analyse multiple files in a folder...
clc;
clear;
%Set current directory to folder containing this m file
paths=cd('C:\Users\lwil634\Documents\Cameras\Test');
for i=1:length(paths)
d=dir(fullfile(paths, '*.avi'));
for j=1:length(d)
vidfile=d(j).name
videoObject=VideoReader(vidfile)
[folder, baseFileName, extentions] = fileparts(vidfile);
folder=pwd;
outputFolder = sprintf('%s/Frames', folder);
numberOfFrames = videoObject.NumberOfFrames;
vidHeight = videoObject.Height;
vidWidth = videoObject.Width;
for x=1 : numberOfFrames
frame = read(videoObject,x)
outputBaseFileName = sprintf('-%4.4d.png', x); %output filename, each frame numbered from 0001
outputFullFileName = fullfile(outputFolder, strcat(baseFileName, outputBaseFileName)); %output filename
imwrite(frame, outputFullFileName, 'png'); %write output file
end
end
end
This code works-I get all of the frames for each AVI file in the folder I specify. However, I think it is erroneous? When I run the code, it runs forever, and doesn't stop until I ctrl+c. I only did this once I checked the output folder and saw that all of the files I expected were there. What can do to stop the code running on and on even though I believe it to be finished...?
Ultimately I am trying to write something so that I can put multiple paths in the paths section, so I could use the script to run through many folders of avi files at one execution of code.
Thanks!!
it runs forever, and doesn't stop until I ctrl+c.
Please check on
  • length(paths)
  • length(d)
  • numberOfFrames
Do confirm?
I think what's going wrong here is the outer-most loop. This code:
paths = cd('...');
returns in paths a char-vector of the old working directory, which will be something like 'c:\my\old\working\directory'. Because paths is a vector of type char, the outermost loop is simply repeating the processing multiple times doing exactly the same thing each time - once per character in paths. This is not what you want! To fix, simply omit the outermost loop.
I'm not familiar with video processing - but I am familiar with parallel computing - so one thought might be (if you have Parallel Computing Toolbox available) to convert the loop over the video files to be a parfor loop. Therefore, your code might look like this:
videoDir = 'C:\Users\lwil634\Documents\Cameras\Test';
videoFiles = dir(fullfile(videoDir, '*.avi'));
parfor fIdx = 1:numel(videoFiles)
thisVideoFile = fullfile(videoDir, videoFiles(fIdx).name);
% process thisVideoFile...
end
Thank you Edric! I did what you said and removed the outer loop, and now it works without problems, and is much faster!!
However, now I am only looping through multiple files within one folder. If possible, I was hoping to loop through many folders/paths? So, for example, I would list a series of C:/ destinations within paths. And then the loop would loop through these paths... does it make sense?
Hi Edric, I'm also curious about the code as it plays back the video to get each frame, am I correct? Is it possible to do similar but without this... so to speed up the code? I am looking at readframe but not understanding it:https://au.mathworks.com/help/matlab/ref/videoreader.readframe.html
To loop over multiple folders, the simplest way is to use an outer loop like this:
videoFolders = {'c:\path\to\folder\one', 'c:\path\to\folder\two'};
for folderIdx = 1:numel(videoFolders)
thisFolder = videoFolders{folderIdx};
theseFiles = dir(fullfile(thisFolder, '*.avi'));
for fileIdx = 1:numel(theseFiles)
... % process each file in the folder
end
end
Another option if there's a common root folder, and you're using a recent version of MATLAB, is to use the '**' syntax in the dir command, like this:
commonVideoFolder = 'c:\root\path\to\videos';
allFiles = dir(fullfile(commonVideoFolder, '**', '*.avi'));
for fileIdx = 1:numel(allFiles) % could be 'parfor'
thisEntry = allFiles(fileIdx);
thisFileName = fullfile(thisEntry.folder, thisEntry.name);
% ... process the file.
end

Sign in to comment.

Answers (1)

Put your existing code inside the for loop of the FAQ.

1 Comment

Hi! Thank you! I have my code working for lots of *.avi files... but I want to run through many folders of avi files. Should I adapt the code in the link you mention to include a series of folders?
% Specify the folder where the files live.
myFolder = 'C:\Users\yourUserName\Documents\My Pictures'; %other folders here???
% Check to make sure that folder actually exists. Warn user if it doesn't.
if ~isdir(myFolder)
errorMessage = sprintf('Error: The following folder does not exist:\n%s', myFolder);
uiwait(warndlg(errorMessage));
return;
end
% Get a list of all files in the folder with the desired file name pattern.
filePattern = fullfile(myFolder, '*.jpg'); % Change to whatever pattern you need.
theFiles = dir(filePattern);
for k = 1 : length(theFiles)
baseFileName = theFiles(k).name;
fullFileName = fullfile(myFolder, baseFileName);
fprintf(1, 'Now reading %s\n', fullFileName);
% Now do whatever you want with this file name,
% such as reading it in as an image array with imread()
imageArray = imread(fullFileName);
imshow(imageArray); % Display image.
drawnow; % Force display to update immediately.
end
My code right now:
%%08 July 2019, Louise Wilson
%Code to split several .avi files within a folder into many .jpg files.
%Adapting code to use vision.VideoFileReader might be faster?
clc;
clear;
%Set current directory to folder containing this .m file and raw .avi files:
paths=cd('C:\Users\lwil634\...');
mkdir Frames %create Frames output folder
d=dir(fullfile(paths, '*.AVI')); %filename of each file to be processed
fileCount=length(d); %number of files to be processed
for j=1:fileCount
vidfile=d(j).name; %get name of jth video file
videoObject=VideoReader(vidfile); %read in avi file
[folder, baseFileName, extentions] = fileparts(vidfile); %get info from avi file
folder=pwd; %print working directory
outputFolder = sprintf('%s/Frames', folder); %put outfiles files in 'Frames' folder
%Determine how many frames there are
numberOfFrames = videoObject.NumberOfFrames;
vidHeight = videoObject.Height;
vidWidth = videoObject.Width;
for x=1 : numberOfFrames
frame = read(videoObject,x);
outputBaseFileName = sprintf('-%4.4d.png', x); %output filename, each frame numbered from 0001
outputFullFileName = fullfile(outputFolder, strcat(baseFileName, outputBaseFileName)); %full output filename with .avi file number
imwrite(frame, outputFullFileName, 'png'); %write output png file
end
end

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products

Release

R2018b

Asked:

on 8 Jul 2019

Commented:

on 9 Jul 2019

Community Treasure Hunt

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

Start Hunting!