Exploring the UCF 101 Action Dataset
Generate image frames from video
From the UCF 101 dataset website: UCF101 is an action recognition data set of realistic action videos, collected from YouTube, having 101 action categories. We downloaded a zipped file containing 13320 trimmed videos, each including one action, and a text file containing the list of action classes and their numerical index.
Unzip the .avi files into a VIDEO_DIR folder.
import glob
video_files = glob.glob(os.path.join(os.environ["VIDEO_DIR"], "*.avi"))
video_files[0:2]
There is better support for .mp4 files, so we will convert the .avi files to .mp4 using ffmpeg. The code below requires that your machine have ffmpeg installed.
import subprocess
def convert_from_avi_to_mp4(file_name):
outputfile = file_name.lower().replace(".avi", ".mp4")
subprocess.call(['ffmpeg', '-i', file_name, outputfile])
The code below takes quite a while and could be sped up by using multi-processing:
for file_name in video_files:
convert_from_avi_to_mp4(file_name)
Once all the files are converted we can list all the .mp4 files
mp4_video_files = glob.glob(os.path.join(os.environ["VIDEO_DIR"], "*.mp4"))
mp4_video_files[0:2]
Select one of the videos at random for illustration:
from IPython.display import Video
from random import choice, seed
seed(457)
video_path = choice(mp4_video_files)
video_path
Display the selected video:
Video(video_path, embed=True)
A video is a sequence of image frames. In this section we want to create a function that generates image frames at a given rate of frames per second and then select a specific number of equally spaced image frames to be kept for further processing.
import numpy as np
def sample_images(images, number_to_sample):
"""
Sample equally spaced frames from a list of image frames
:param images: a list of image frames.
:param number_to_sample: int representing the number os frames to sample.
:return: a numpy array containing the sample of frames.
"""
if number_to_sample < len(images):
idx = np.round(np.linspace(0, len(images) - 1, number_to_sample)).astype(int)
return np.array(images)[idx]
else:
return np.array(images)
import imageio
def extract_images(video_path, number_frames):
"""
Extract equally spaced frames from a video.
:param video_path: Full .mp4 video path.
:param number_frames: Number of frames to sample.
:return: a numpy array containing the sample of frames.
"""
reader = imageio.get_reader(
video_path,
fps=1
)
frames = []
for i, im in enumerate(reader):
frames.append(im)
return sample_images(frames, number_frames)
Generate 4 equally spaced frames from the video displayed above.
images = extract_images(video_path, 4)
Plot the extracted frames:
import matplotlib.pyplot as plt
def plot_images(images):
fig = plt.figure(figsize=(10, 10))
for idx, image in enumerate(images):
sub = fig.add_subplot(2,2,idx+1)
imgplot = plt.imshow(image)
plt.tight_layout()
plot_images(images)