0

我想编写一个程序,它将视频作为输入,创建一个输出视频文件,并将(在一定数量的帧之后开始)开始逐帧将修改后的帧写入输出文件。修改将需要处理单个像素列,一次一个。

将此视为要在 Matlab 中解决的问题,将每一帧视为一个矩阵......我想不出一种方法来使这个计算易于处理。我希望有人能够就我如何开始解决这个问题提供建议。


以下是一些细节,以防有帮助:

我有兴趣通过以下方式转换视频:

将视频视为 (MxN) 矩阵的序列,其中每个矩阵称为 a frame

  • 获取输入视频并为输出视频创建新文件
  • 对于输出视频的第 (i) 帧中的每一列 V,将这一列替换frame(i + V - N)为输入视频的 V in 列。

例如:frame(i) 的最右边的新列(第 N 列)将包含第 N 列,frame(i + N - N) = frame(i)...因此没有替换。frame(i) 的新的第 2 列到最右边的列(第 N-1 列)将包含 的第 N-1 列[frame(i+N-1-N) = frame(i-1)]

为了完成这项工作(即为了不耗尽之前的帧),此列替换将从视频的第 N 帧开始。

4

1 回答 1

2

所以...这基本上是从左到右运行的可变延迟?

正如您所说,您确实有两种方法可以解决此问题:

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 倍,其中所用时间为文件读取次数.

希望这有帮助,祝你好运!

于 2013-06-16T13:17:32.480 回答