test_datasets_video_utils.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import pytest
  2. import torch
  3. from common_utils import assert_equal, get_list_of_videos
  4. from torchvision import io
  5. from torchvision.datasets.video_utils import unfold, VideoClips
  6. class TestVideo:
  7. def test_unfold(self):
  8. a = torch.arange(7)
  9. r = unfold(a, 3, 3, 1)
  10. expected = torch.tensor(
  11. [
  12. [0, 1, 2],
  13. [3, 4, 5],
  14. ]
  15. )
  16. assert_equal(r, expected)
  17. r = unfold(a, 3, 2, 1)
  18. expected = torch.tensor([[0, 1, 2], [2, 3, 4], [4, 5, 6]])
  19. assert_equal(r, expected)
  20. r = unfold(a, 3, 2, 2)
  21. expected = torch.tensor(
  22. [
  23. [0, 2, 4],
  24. [2, 4, 6],
  25. ]
  26. )
  27. assert_equal(r, expected)
  28. @pytest.mark.skipif(not io.video._av_available(), reason="this test requires av")
  29. def test_video_clips(self, tmpdir):
  30. video_list = get_list_of_videos(tmpdir, num_videos=3)
  31. video_clips = VideoClips(video_list, 5, 5, num_workers=2)
  32. assert video_clips.num_clips() == 1 + 2 + 3
  33. for i, (v_idx, c_idx) in enumerate([(0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2)]):
  34. video_idx, clip_idx = video_clips.get_clip_location(i)
  35. assert video_idx == v_idx
  36. assert clip_idx == c_idx
  37. video_clips = VideoClips(video_list, 6, 6)
  38. assert video_clips.num_clips() == 0 + 1 + 2
  39. for i, (v_idx, c_idx) in enumerate([(1, 0), (2, 0), (2, 1)]):
  40. video_idx, clip_idx = video_clips.get_clip_location(i)
  41. assert video_idx == v_idx
  42. assert clip_idx == c_idx
  43. video_clips = VideoClips(video_list, 6, 1)
  44. assert video_clips.num_clips() == 0 + (10 - 6 + 1) + (15 - 6 + 1)
  45. for i, v_idx, c_idx in [(0, 1, 0), (4, 1, 4), (5, 2, 0), (6, 2, 1)]:
  46. video_idx, clip_idx = video_clips.get_clip_location(i)
  47. assert video_idx == v_idx
  48. assert clip_idx == c_idx
  49. @pytest.mark.skipif(not io.video._av_available(), reason="this test requires av")
  50. def test_video_clips_custom_fps(self, tmpdir):
  51. video_list = get_list_of_videos(tmpdir, num_videos=3, sizes=[12, 12, 12], fps=[3, 4, 6])
  52. num_frames = 4
  53. for fps in [1, 3, 4, 10]:
  54. video_clips = VideoClips(video_list, num_frames, num_frames, fps, num_workers=2)
  55. for i in range(video_clips.num_clips()):
  56. video, audio, info, video_idx = video_clips.get_clip(i)
  57. assert video.shape[0] == num_frames
  58. assert info["video_fps"] == fps
  59. # TODO add tests checking that the content is right
  60. def test_compute_clips_for_video(self):
  61. video_pts = torch.arange(30)
  62. # case 1: single clip
  63. num_frames = 13
  64. orig_fps = 30
  65. duration = float(len(video_pts)) / orig_fps
  66. new_fps = 13
  67. clips, idxs = VideoClips.compute_clips_for_video(video_pts, num_frames, num_frames, orig_fps, new_fps)
  68. resampled_idxs = VideoClips._resample_video_idx(int(duration * new_fps), orig_fps, new_fps)
  69. assert len(clips) == 1
  70. assert_equal(clips, idxs)
  71. assert_equal(idxs[0], resampled_idxs)
  72. # case 2: all frames appear only once
  73. num_frames = 4
  74. orig_fps = 30
  75. duration = float(len(video_pts)) / orig_fps
  76. new_fps = 12
  77. clips, idxs = VideoClips.compute_clips_for_video(video_pts, num_frames, num_frames, orig_fps, new_fps)
  78. resampled_idxs = VideoClips._resample_video_idx(int(duration * new_fps), orig_fps, new_fps)
  79. assert len(clips) == 3
  80. assert_equal(clips, idxs)
  81. assert_equal(idxs.flatten(), resampled_idxs)
  82. # case 3: frames aren't enough for a clip
  83. num_frames = 32
  84. orig_fps = 30
  85. new_fps = 13
  86. with pytest.warns(UserWarning):
  87. clips, idxs = VideoClips.compute_clips_for_video(video_pts, num_frames, num_frames, orig_fps, new_fps)
  88. assert len(clips) == 0
  89. assert len(idxs) == 0
  90. if __name__ == "__main__":
  91. pytest.main([__file__])