将视频转换为图像序列 MATLAB

4
我将尝试将视频转换为图像序列,我在MathWorks上看到的代码如下:
读取并播放xylophone.mp4电影文件。
xyloObj = VideoReader('xylophone.mp4');

nFrames = xyloObj.NumberOfFrames;
vidHeight = xyloObj.Height;
vidWidth = xyloObj.Width;

预分配电影结构。

mov(1:nFrames) = ...
    struct('cdata',zeros(vidHeight,vidWidth, 3,'uint8'),...
           'colormap',[]);

一次只读取一个帧。

for k = 1 : nFrames
    mov(k).cdata = read(xyloObj,k);
end

当我尝试运行这段代码时,编译需要很长时间。有没有一种不用循环就可以读取所有帧的方法,以使其更快?

1个回答

2
无论你做什么,都需要很长时间。你正在解压每一帧并将原始RGB帧放入内存中。因此,时间花费在I/O和将帧解码为RGB上。然而,从长远来看,对你来说可能更快的方法是首先使用单个read调用批量读取一堆帧,然后它们可供以后使用。 read方法允许您指定一个二元向量作为第二个输入,告诉MATLAB要读取的帧范围。例如,如果您想读取前10帧,请执行以下操作:
video = read(xyloObj, [1 10]);

video是一个4维数组,其中第一维是帧的高度,第二维是宽度,第三维是颜色通道的数量(通常为3),第四维是帧数。因此,如果你想要访问第i帧,你需要这样做:

frame = video(:,:,:,i);

另外,如果您调用read而未提供第二个参数,则会从开头读取所有帧。因此,您也可以这样做:

video = read(xyloObj);

在我的电脑上的xylophone.mp4文件中,有141帧,对于上述操作大约需要13秒。我的配置是Mac OS Yosemite 10.10.3,运行MATLAB R2013a,拥有16 GB的RAM和Intel Core i7 2.3 GHz处理器。这与我们之前讨论的内容一致,现在这些帧可以作为一个4D矩阵使用。
因此,也许有一件事情可以做,那就是使用read函数读取所有帧而不是循环读取。如果速度慢,那么也许你可以一次读取每10或20帧左右,处理帧,然后继续下一批... 就像这样:
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

然而,如果你只是使用read命令而没有任何第二个输入,如果你可以等待大约13秒左右,那就完全没问题。此外,如果你真的想要稍后利用这些帧,你可以随时使用save来将帧存储在MAT文件中,以便于以后加载和使用。


那么,如果我在读取帧后直接处理视频呢?如果我先将视频转换为图像序列,会有什么区别吗? - Brilian Aringga
@BrilianAringga - 不太行!无论你做什么都需要很长时间。它需要很长时间的原因是由于I/O和解压缩帧。将其转换为图像序列的原因是你只需要进行一次读取调用。一旦你这样做了,那么只需要切片到图像序列矩阵中获取所需的帧。然而,这将占用大量内存,因此你必须决定什么对你来说更好、更容易... 要么逐帧读取一个帧,要么一次性完成。 - rayryeng
哦,我明白了!所以我可以减少处理时间,因为我不需要再次读取帧,对吗? - Brilian Aringga
@BrilianAringga - 没错!只需调用一次read,从那时起,帧将可供您使用。 :) 我已编辑我的帖子以反映这一点。 - rayryeng
1
我现在明白了,非常感谢大师@rayryeng的解释xD。 - Brilian Aringga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接