Reputation: 57
i am trying to convert a video to image sequences, and at mathworks i saw the code like this
Read and play back the movie file xylophone.mp4.
xyloObj = VideoReader('xylophone.mp4');
nFrames = xyloObj.NumberOfFrames;
vidHeight = xyloObj.Height;
vidWidth = xyloObj.Width;
Preallocate the movie structure.
mov(1:nFrames) = ...
struct('cdata',zeros(vidHeight,vidWidth, 3,'uint8'),...
'colormap',[]);
Read one frame at a time.
for k = 1 : nFrames
mov(k).cdata = read(xyloObj,k);
end
while i am trying this code, it requires a very long time to compile it. Is there any way to read all frame without looping so i can make it faster?
Upvotes: 4
Views: 1659
Reputation: 104464
It's going to take a long time regardless of what you do. What you're doing is uncompressing each frame and placing the raw RGB frames into memory. As such, the time is being spent in I/O and performing a decoding of the frames into RGB. However, what may be faster for you in the long run is to batch read a bunch of frames with a single read
call first and then they're available for use later on.
The read
method allows you to specify a two element vector as the second input that tells MATLAB the range of frames you want to read. For example, if you wanted to read the first 10 frames, do this:
video = read(xyloObj, [1 10]);
video
is a 4-D array where the first dimension is the height of a frame, the second dimension is the width, the third dimension is the number of colour channels (usually 3) and the fourth dimension is the frame number. Therefore, if you wanted to access the i
th frame, you'd do:
frame = video(:,:,:,i);
Also, if you called read
without the second parameter, this reads in all of the frames from the beginning to end. As such, you can also just do this:
video = read(xyloObj);
In the xylophone.mp4
file (on my computer), there are 141 frames and doing the above on my computer took about 13 seconds. My configuration is Mac OS Yosemite 10.10.3 running MATLAB R2013a with 16 GB of RAM on an Intel Core i7 2.3 GHz. This makes sense from what we talked about before and now the frames are available as a 4D matrix.
So perhaps one thing that could work is to use read
and just read in all of the frames without looping. If that's slow, then perhaps you can read in every 10 or 20 frames or so at one time, process the frames, then proceed to the next batch.... so something like this:
for idx = 1 : 20 : nFrames
if idx + 20 > nFrames
endIndex = nFrames;
else
endIndex = idx + 20;
end
video = read(xyloObj, [idx endIndex-1]);
%// Continue processing
end
However, if you just use the read
command by itself without any second inputs, if you can wait about 13 seconds or so then that's totally fine. Besides which, if you really wanted to make use of the frames for later, you can always employ save
and store the frames in a MAT file for ease of loading and use for later.
Upvotes: 2