Hi我制作了一个视频帧加载程序数据集,将其输入到pytorch模型中。我想从视频中采样帧,但帧应该从每个视频中均匀采样。这是我想出的课。我想知道是否有更好的方法来加快采样过程
你有什么建议吗,尤其是在read_video
方法部分
感谢
import torch
import torchvision as tv
import cv2
import numpy as np
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
from pathlib import Path
class VideoLoader(torch.utils.data.Dataset):
def __init__(self, data_path, classes, transforms=None, max_frames=None, frames_ratio=None):
super(VideoLoader, self).__init__()
self.data_path = data_path
self.classes = classes
self.frames_ratio = frames_ratio
self.transforms = transforms
self.max_frames = max_frames
def read_video(self, path):
frames = []
vc = cv2.VideoCapture(path)
total_frames = int(vc.get(cv2.CAP_PROP_FRAME_COUNT))
if self.frames_ratio:
if type(self.frames_ratio) is float:
frames_to_pick = int(total_frames * self.frames_ratio)
else:
frames_to_pick = self.frames_ratio
else:
frames_to_pick = total_frames
idxs = np.linspace(0, total_frames, frames_to_pick, endpoint=False)
for i in idxs:
ok, f = vc.read()
if ok:
f = tv.transforms.ToTensor()(f)
f = self.transforms(f) if self.transforms else f
frames.append(f)
vc.set(cv2.CAP_PROP_POS_FRAMES, i)
if self.max_frames and len(frames) == self.max_frames: break
else: break
vc.release()
return torch.stack(frames)
def __getitem__(self, index):
v_path, label = self.data_path[index]
return self.read_video(v_path), self.classes[label]
def __len__(self): return len(self.data_path)
因为你不能真正并行地搜索视频,所以没有任何更快的采样过程可以在本地运行。我个人在这个问题上遇到了麻烦,这就是为什么我开始为这个问题构建一个简单的API,称为Sieve。你可以直接将数据上传到Sieve(从云存储桶或本地存储(,它会快速为你剪切所有帧,甚至用运动、人、物体等标记它们。它在云中使用无服务器功能进行并行化,这使得它非常快速,甚至可以拍摄数小时或数天的镜头。
然后,您可以使用仪表板从Sieve快速导出,该仪表板为您提供了一个快速curl
命令,您可以运行该命令下载所需的确切样本。
这里有一个有用的回购:https://github.com/Sieve-Data/automatic-video-processing
如果您对预先将每个视频的帧提取到磁盘感到满意,那么这个库正是您想要的:视频数据集在Github上加载PyTorchhttps://github.com/RaivoKoot/Video-Dataset-Loading-Pytorch