Args: video_path (str): path to video frame_inds (List[int]): indices of frames to extract points (List[float]): values within [0, 1); multiply #frames to get frame indices Return: List[PIL.Image]
(
video_path,
frame_inds=None,
points=None,
backend="opencv",
return_length=False,
num_frames=None,
)
| 14 | |
| 15 | |
| 16 | def extract_frames( |
| 17 | video_path, |
| 18 | frame_inds=None, |
| 19 | points=None, |
| 20 | backend="opencv", |
| 21 | return_length=False, |
| 22 | num_frames=None, |
| 23 | ): |
| 24 | """ |
| 25 | Args: |
| 26 | video_path (str): path to video |
| 27 | frame_inds (List[int]): indices of frames to extract |
| 28 | points (List[float]): values within [0, 1); multiply #frames to get frame indices |
| 29 | Return: |
| 30 | List[PIL.Image] |
| 31 | """ |
| 32 | assert backend in ["av", "opencv", "decord"] |
| 33 | assert (frame_inds is None) or (points is None) |
| 34 | |
| 35 | if backend == "av": |
| 36 | import av |
| 37 | |
| 38 | container = av.open(video_path) |
| 39 | if num_frames is not None: |
| 40 | total_frames = num_frames |
| 41 | else: |
| 42 | total_frames = container.streams.video[0].frames |
| 43 | |
| 44 | if points is not None: |
| 45 | frame_inds = [int(p * total_frames) for p in points] |
| 46 | |
| 47 | frames = [] |
| 48 | for idx in frame_inds: |
| 49 | if idx >= total_frames: |
| 50 | idx = total_frames - 1 |
| 51 | target_timestamp = int(idx * av.time_base / container.streams.video[0].average_rate) |
| 52 | container.seek(target_timestamp) # return the nearest key frame, not the precise timestamp!!! |
| 53 | frame = next(container.decode(video=0)).to_image() |
| 54 | frames.append(frame) |
| 55 | |
| 56 | if return_length: |
| 57 | return frames, total_frames |
| 58 | return frames |
| 59 | |
| 60 | elif backend == "decord": |
| 61 | import decord |
| 62 | |
| 63 | container = decord.VideoReader(video_path, num_threads=1) |
| 64 | if num_frames is not None: |
| 65 | total_frames = num_frames |
| 66 | else: |
| 67 | total_frames = len(container) |
| 68 | |
| 69 | if points is not None: |
| 70 | frame_inds = [int(p * total_frames) for p in points] |
| 71 | |
| 72 | frame_inds = np.array(frame_inds).astype(np.int32) |
| 73 | frame_inds[frame_inds >= total_frames] = total_frames - 1 |
no test coverage detected