【问题标题】:Modifying Every Column of Every Frame of a Video修改视频每一帧的每一列
【发布时间】:2013-06-15 04:01:55
【问题描述】:

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

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


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

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

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

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

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

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

【问题讨论】:

  • 这是作业还是您之前问过(但后来删除)这个问题?
  • Schorsch,我大约一周前发布了这个问题,但我实际上在问什么非常不清楚。由于这个原因,最后一个问题被关闭了......似乎我在问“什么语言最适合这个问题?”我的预期问题是:“我可以使用 Matlab 来解决这个问题吗……总的来说,我怎么可能开始解决这个问题?”这不是一项任务,而是我想应用于视频的转换。我一直在 Adob​​e Premiere 中手动编辑视频以近似这种效果......但这将为我节省大量时间
  • 如果对我的要求仍有任何疑问:我不是要求一种算法来完成我在帖子后半部分中描述的特定任务。相反,我要问的是如何才能开始以这种“细粒度”级别处理视频,而不会耗尽内存或不必等待几年才能看到程序完成。
  • 谢谢,感谢您提供额外且有用的背景信息。

标签: matlab video video-processing


【解决方案1】:

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

正如您所说,您确实有两种解决方法:

a) 使用大量内存 b) 使用大量文件访问权限

您的内存需求随着视频大小的三次方而增加 - 每帧的大小增加,并且您需要打开或参考的先前帧的数量增加。 IE。将帧大小加倍将需要每帧 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 倍,其中所用时间为文件读取次数.

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

【讨论】:

  • +1 表示细节和努力,特别是概述了两种可能的方法
  • 谢谢!这是一个有趣的问题,我之前在matlab中做过一些视频处理,现在想再做一次,很好地思考了一些问题:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-12
  • 2018-05-24
  • 2013-08-08
  • 2021-06-28
  • 2012-11-09
  • 1970-01-01
  • 2013-10-01
相关资源
最近更新 更多