Decord库快速视频抽帧

本文介绍了Decord库在视频读取、帧处理和抽帧任务中的优势,对比了与OpenCV的性能,并提供了使用教程和视频抽帧脚本示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Decord

Decord比Opencv块6倍!!
在这里插入图片描述

1. 使用教程

读取视频

# 1、读取使用
from decord import VideoReader
from decord import cpu, gpu

vr = VideoReader('tiny-Kinetics-400\\abseiling\\_4YTwq0-73Y_000044_000054.mp4', ctx=cpu(0))

print('video frames:', len(vr))
>>> video frames: 300

加载指定帧

# 加载指定帧
frames = vr.get_batch([1, 3, 5, 7, 200])
print(frames.shape)
>>> (5, 256, 454, 3)

保存帧为图片

# 2、保存帧为图片
frame1 = vr[5].asnumpy()
from matplotlib import pyplot as plt
plt.imshow(frame1)
plt.axis('off')
>>> (-0.5, 453.5, 255.5, -0.5)

在这里插入图片描述

2. 视频抽帧脚本

import cv2
import os
from decord import VideoReader
from decord import cpu
from tqdm import tqdm

video_bytes = "tiny-Kinetics-400\\abseiling\\_4YTwq0-73Y_000044_000054.mp4"  # 视频路径
pic_folder =  "frames"  # 抽帧保存文件夹
file_basename = "abseiling"  # 文件名前缀
archive_fps = 30  # 间隔帧数

# 压缩大图片的大小
def resize_image(image):
    height, width = image.shape[:2]
    n_width = int(256 * width / max(width, height))
    n_height = int(256 * height / max(width, height))
    img_new = cv2.resize(image, (n_width, n_height))
    return img_new

# 读取视频
vr = VideoReader(video_bytes, ctx=cpu(0))
fra_num = len(vr)  # 所有帧长度

# 获取指定帧并进行resize保存(使用tqdm显示进度)
frames = vr.get_batch(list(range(0, fra_num, archive_fps))).asnumpy()
for count, frame in tqdm(enumerate(frames), total=len(frames)):
    frame = resize_image(frame)
    image_name = f"{file_basename}_{count}.jpg"
    cv2.imwrite(os.path.join(pic_folder, image_name), cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

3、抽指定帧,然后存为MP4视频

用cv2的话太慢了,得把decord.ndarray.NDArray对象转为np.ndarray一帧一帧存。不如用imageio直接将整个NDArray转为np.ndarray后直接存储。

from decord import VideoReader, cpu
import imageio

# 例如只存原视频前16帧
video_path = '/mnt/petrelfs/yuezhengrong/Data/action.mp4'
output_path = 'test.mp4'
vr = VideoReader(video_path, ctx=cpu(0))
frame_indices = list(range(0, 16))  # 读取前16帧
frames = vr.get_batch(frame_indices)  # <class 'decord.ndarray.NDArray'> (16, 2160, 5070, 3)
imageio.mimsave(output_path, frames.asnumpy(), fps=30)

按照indeces或timestamps抽帧

decord库只提供了使用帧索引frame_idxs进行get_batch抽帧,如果你只有时间戳,可以选择:

  1. 使用decord库,获取fps,然后将时间戳转换为帧索引。
  2. 直接使用pytorchvideo库的get_clip获取帧,但速度不如decord。
import decord

def get_frames_by_indices(video_path, start_idx, end_idx):
    """
    根据帧索引获取视频帧。
    
    参数:
    video_path : str
        视频文件的路径。
    start_idx : int
        起始帧索引。
    end_idx : int
        结束帧索引。
        
    返回:
    frames : list
        根据索引获取的帧列表。
    """
    # 加载视频
    vr = decord.VideoReader(video_path)
    
    # 获取帧索引范围内的帧
    frames = vr.get_batch(frame_idxs=range(start_idx, end_idx + 1))
    
    return frames
def get_frames_by_timestamps(video_path, start_sec, end_sec):
    """
    根据时间戳获取视频帧。
    
    参数:
    video_path : str
        视频文件的路径。
    start_sec : float
        起始时间戳(秒)。
    end_sec : float
        结束时间戳(秒)。
        
    返回:
    frames : list
        根据时间戳获取的帧列表。
    """
    # 加载视频
    vr = decord.VideoReader(video_path)
    
    # 获取帧率
    fps = vr.get_avg_fps()
    
    # 将时间戳转换为帧索引
    start_idx = int(start_sec * fps)
    end_idx = int(end_sec * fps)
    
    # 获取时间戳范围内的帧
    frames = vr.get_batch(frame_idxs=range(start_idx, end_idx + 1))
    
    return frames
# 假设我们有一个视频文件路径
video_path = 'path_to_your_video.mp4'

# 根据帧索引获取帧
start_frame_idx = 150
end_frame_idx = 250
frames_by_indices = get_frames_by_indices(video_path, start_frame_idx, end_frame_idx)

# 根据时间戳获取帧
start_timestamp = 5.0  # 5秒
end_timestamp = 10.0   # 10秒
frames_by_timestamps = get_frames_by_timestamps(video_path, start_timestamp, end_timestamp)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yuezero_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值