Main Content

读取视频文件

此示例说明如何从特定时间或帧索引开始读取视频帧,读取指定区间内的帧,或读取视频中的所有帧。

从指定时间或帧索引开始读取帧

从距离视频文件开头 0.5 秒处开始读取文件的一部分。然后,从帧索引 100 开始读取到视频文件结束。

为示例视频文件 xylophone_video.mp4 创建一个 VideoReader 对象。

vidObj = VideoReader("xylophone_video.mp4");

通过设置 CurrentTime 属性,指定应从距离文件开头 0.5 秒处开始读取。

vidObj.CurrentTime = 0.5;

使用 readFrame 方法读取视频帧,直至文件结束。

while hasFrame(vidObj)
    vidFrame = readFrame(vidObj);
    imshow(vidFrame)
    pause(1/vidObj.FrameRate)
end

Figure contains an axes object. The axes object contains an object of type image.

您也可以使用 read 方法从指定的帧索引开始读取视频帧,直到视频结束。将要读取的索引指定为 [100 Inf]read 方法返回从索引 100 开始到视频文件结束的所有帧。

vidframes = read(vidObj,[100 Inf]);

清除 VideoReader 对象。

clear vidObj

读取指定区间内的帧

通过指定时间或帧区间来读取视频文件的一部分。

读取 0.6 到 0.9 秒之间的视频帧。首先,创建一个 VideoReader 对象和一个用来保存帧的结构体数组。

vidObj = VideoReader("xylophone_video.mp4");
s = struct("cdata",zeros(vidObj.Height,vidObj.Width,3,"uint8"),colormap=[]);

然后,通过设置 CurrentTime 属性,指定应从距离文件开头 0.6 秒处开始读取。

vidObj.CurrentTime = 0.6;

一次读取一帧,直至 CurrentTime 到达 0.9 秒处。将每个视频帧中的数据追加到结构体数组。查看结构体数组中的帧数。s 是 1×10 结构体数组,表示读取了 10 个帧。有关将结构体数组 s 中的帧显示为影片的信息,请参阅 movie 函数参考页。

k = 1;
while vidObj.CurrentTime <= 0.9
    s(k).cdata = readFrame(vidObj);
    k = k+1;
end
whos s
  Name      Size              Bytes  Class     Attributes

  s         1x10            2305344  struct              

您也可以通过使用帧索引来读取指定区间内的所有帧。例如,将要读取的帧的范围指定为 [18 27]read 方法返回一个 m×n×p×10 数组(其中每个帧的大小为 m×n×p),表示读取 10 个帧。

frames = read(vidObj,[18 27]);
whos frames
  Name          Size                    Bytes  Class    Attributes

  frames      240x320x3x10            2304000  uint8              

清除 VideoReader 对象。

clear vidObj

读取所有帧

从视频中读取所有帧,一次读取一帧或一次读取所有帧。

创建一个 VideoReader 对象,并显示视频中的总帧数。

vidObj = VideoReader("xylophone_video.mp4");
vidObj.NumFrames
ans = 141

使用 readFrame 方法读取所有帧,一次读取一帧,并显示这些帧。

while hasFrame(vidObj)
   frame = readFrame(vidObj);
   imshow(frame)
   pause(1/vidObj.FrameRate)
end

Figure contains an axes object. The axes object contains an object of type image.

您也可以一次读取所有视频帧。read 方法返回一个视频帧的 m×n×p×141 数组(其中每个帧的大小为 m×n×p)。

allFrames = read(vidObj);
whos allFrames
  Name             Size                      Bytes  Class    Attributes

  allFrames      240x320x3x141            32486400  uint8              

清除 VideoReader 对象。

clear vidObj

视频读取的故障排除和提示

  • 在 Windows® 平台上,您无法修改或删除由工作区中的 VideoReader 对象引用的 AVI 文件。要从工作区中删除 VideoReader 对象,请使用 clear 函数。

  • 对于某些 MP4 文件,NumFrames 属性在 Windows、Mac 和 Linux® 平台上可能返回不同值。这种差异是由底层平台特定 API 的差异造成的。

  • CurrentTime 属性的值等于 Duration 属性的值时,hasFrame 方法可能会返回逻辑值 1 (true)。此行为是所使用的底层平台特定 API 的限制所致。

  • 不推荐通过将 CurrentTime 属性设置为接近于 Duration 值的值来查找视频文件中的最后一帧。对于某些文件,即使 CurrentTime 值小于 Duration 值,该操作也会返回错误,即指示已到达文件结尾。如果文件持续时间长于视频流的持续时间,并且在靠近文件结尾时没有可读取的视频,通常会发生此问题。

  • 不推荐使用 Duration 属性限制从视频文件中读取数据。请使用 hasFrame 方法检查是否存在可读取的帧。最好是连续读取数据,直至文件报告不再存在可读取的帧。

  • Windows 系统上的视频读取性能:为了在 Windows 上达到更好的 MP4MOV 视频文件读取性能,MATLAB® 使用系统的图形硬件进行解码。但是,在某些情况下,使用图形卡进行解码可能会降低系统性能,具体取决于系统上的特定图形硬件。如果您注意到系统上的视频读取性能降低,可以通过键入以下命令来禁用硬件加速:matlab.video.read.UseHardwareAcceleration('off')。您可以通过键入以下命令重新启用硬件加速:matlab.video.read.UseHardwareAcceleration('on')

另请参阅

| | | |

相关主题