所以...这基本上是从左到右运行的可变延迟?
正如您所说,您确实有两种方法可以解决此问题:
a) 使用大量内存 b) 使用大量文件访问
您的内存需求随着视频大小的立方幂的增加而增加 - 每帧的大小增加,并且您需要打开或参考的先前帧的数量增加。即,帧大小加倍将需要每帧 4 倍的内存,以及 2 倍的打开帧数。
我认为 Matlab 的内存管理可能会让这对于例如 1080p 视频很难做到,除非你有一个相当高端的工作站。你?对 720p 视频的快速测试读取为每帧 1.2MB。1080p 大约是每帧 5MB,你需要打开 1920 帧:大约需要 10GB。
如果您没有足够的内存,单独加载帧会更有效 - 否则您将使用页面文件,这将比逐帧加载慢。
您单独读取每一帧的基本代码可能是这样的:
VR=VideoReader('My_Input_Video_Filename.avi');
VW=VideoWriter('My_Output_Video_Filename.avi','MPEG-4');
NumInFrames=get(VR,'NumberOfFrames');
InWidth=get(VR,'Width');
InHeight=get(VR,'Height');
OutFrame=zeros(InHeight,InWidth,3,'uint8');
for (frame=InWidth+1:NumInFrames)
for (subindex=1:InWidth)
CData=read(VR,frame-subindex);
OutFrame(:,subindex,:)=CData(:,subindex,:);
end
writeVideo(VW,OutFrame);
end
这可能会很慢,而且我还没有完全检查它是否有效,但它确实使用了最少的内存。
最小文件访问的最佳情况可能是使用环形缓冲区安排和最大内存量,看起来像这样:
VR=VideoReader('My_Input_Video_Filename.avi');
VW=VideoWriter('My_Output_Video_Filename.avi','MPEG-4');
NumInFrames=get(VR,'NumberOfFrames');
InWidth=get(VR,'Width');
InHeight=get(VR,'Height');
CDatas=read(VR,InWidth);
BufferIndex=1;
OutFrame=zeros(InHeight,InWidth,3,'uint8');
for (frame=InWidth+1:NumInFrames)
CDatas(:,:,:,BufferIndex)=read(VR,frame);
tempindices=circshift(1:InWidth,[1,-1*BufferIndex]);
for (subindex=1:InWidth)
OutFrame(:,subindex,:)=CDatas(:,subindex,:,tempindices(subindex));
end
writeVideo(VW,OutFrame);
BufferIndex=mod(BufferIndex+1,InWidth);
end
缓冲区索引代码可能需要在那里进行一些调整,但沿着这些路线的东西将是最小文件访问,最大内存使用解决方案。
对于具有或多或少内存的给定 PC,您可以在这两者之间的某处实现作为解决方案(即每次迭代读取 1 和所有帧之间的某处)作为最佳情况。
对于这种任务,Matlab 会很慢,但它会是让你的算法正确并解决索引错误之类的好方法。转换为编译语言会大大提高速度 - 我在几个小时内将 Matlab 脚本转换为 C# 程序,与优化脚本相比,速度提高了 10 倍,其中所用时间为文件读取次数.
希望这有帮助,祝你好运!