test_datasets_video_utils.py 4.02 KB
Newer Older
1
2
3
import contextlib
import os

4
5
6
import pytest
import torch
from common_utils import get_list_of_videos, assert_equal
7
from torchvision import io
8
from torchvision.datasets.video_utils import VideoClips, unfold
9
10


11
class TestVideo:
12
13
14
15
    def test_unfold(self):
        a = torch.arange(7)

        r = unfold(a, 3, 3, 1)
16
17
18
19
20
21
        expected = torch.tensor(
            [
                [0, 1, 2],
                [3, 4, 5],
            ]
        )
22
        assert_equal(r, expected)
23
24

        r = unfold(a, 3, 2, 1)
25
        expected = torch.tensor([[0, 1, 2], [2, 3, 4], [4, 5, 6]])
26
        assert_equal(r, expected)
27
28

        r = unfold(a, 3, 2, 2)
29
30
31
32
33
34
        expected = torch.tensor(
            [
                [0, 2, 4],
                [2, 4, 6],
            ]
        )
35
        assert_equal(r, expected)
36

37
    @pytest.mark.skipif(not io.video._av_available(), reason="this test requires av")
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    def test_video_clips(self, tmpdir):
        video_list = get_list_of_videos(tmpdir, num_videos=3)
        video_clips = VideoClips(video_list, 5, 5, num_workers=2)
        assert video_clips.num_clips() == 1 + 2 + 3
        for i, (v_idx, c_idx) in enumerate([(0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2)]):
            video_idx, clip_idx = video_clips.get_clip_location(i)
            assert video_idx == v_idx
            assert clip_idx == c_idx

        video_clips = VideoClips(video_list, 6, 6)
        assert video_clips.num_clips() == 0 + 1 + 2
        for i, (v_idx, c_idx) in enumerate([(1, 0), (2, 0), (2, 1)]):
            video_idx, clip_idx = video_clips.get_clip_location(i)
            assert video_idx == v_idx
            assert clip_idx == c_idx

        video_clips = VideoClips(video_list, 6, 1)
        assert video_clips.num_clips() == 0 + (10 - 6 + 1) + (15 - 6 + 1)
        for i, v_idx, c_idx in [(0, 1, 0), (4, 1, 4), (5, 2, 0), (6, 2, 1)]:
            video_idx, clip_idx = video_clips.get_clip_location(i)
            assert video_idx == v_idx
            assert clip_idx == c_idx
60

61
    @pytest.mark.skipif(not io.video._av_available(), reason="this test requires av")
62
63
64
65
66
67
68
69
70
71
    def test_video_clips_custom_fps(self, tmpdir):
        video_list = get_list_of_videos(tmpdir, num_videos=3, sizes=[12, 12, 12], fps=[3, 4, 6])
        num_frames = 4
        for fps in [1, 3, 4, 10]:
            video_clips = VideoClips(video_list, num_frames, num_frames, fps, num_workers=2)
            for i in range(video_clips.num_clips()):
                video, audio, info, video_idx = video_clips.get_clip(i)
                assert video.shape[0] == num_frames
                assert info["video_fps"] == fps
                # TODO add tests checking that the content is right
72
73
74
75
76
77
78
79

    def test_compute_clips_for_video(self):
        video_pts = torch.arange(30)
        # case 1: single clip
        num_frames = 13
        orig_fps = 30
        duration = float(len(video_pts)) / orig_fps
        new_fps = 13
80
        clips, idxs = VideoClips.compute_clips_for_video(video_pts, num_frames, num_frames, orig_fps, new_fps)
81
        resampled_idxs = VideoClips._resample_video_idx(int(duration * new_fps), orig_fps, new_fps)
82
83
84
        assert len(clips) == 1
        assert_equal(clips, idxs)
        assert_equal(idxs[0], resampled_idxs)
85
86
87
88
89
90

        # case 2: all frames appear only once
        num_frames = 4
        orig_fps = 30
        duration = float(len(video_pts)) / orig_fps
        new_fps = 12
91
        clips, idxs = VideoClips.compute_clips_for_video(video_pts, num_frames, num_frames, orig_fps, new_fps)
92
        resampled_idxs = VideoClips._resample_video_idx(int(duration * new_fps), orig_fps, new_fps)
93
94
95
        assert len(clips) == 3
        assert_equal(clips, idxs)
        assert_equal(idxs.flatten(), resampled_idxs)
96

97
98
99
100
        # case 3: frames aren't enough for a clip
        num_frames = 32
        orig_fps = 30
        new_fps = 13
101
        with pytest.warns(UserWarning):
102
            clips, idxs = VideoClips.compute_clips_for_video(video_pts, num_frames, num_frames, orig_fps, new_fps)
103
104
        assert len(clips) == 0
        assert len(idxs) == 0
105

106

107
if __name__ == "__main__":
108
    pytest.main([__file__])