Added video extractor arguments and documentation
This commit is contained in:
parent
f99467af6b
commit
891f53da04
|
@ -0,0 +1,27 @@
|
||||||
|
# Video frame extractor
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Place video files into the top level of a directory.
|
||||||
|
|
||||||
|
Execute `python scripts/extract_video_frames.py --vid_dir path/to/videos` to iterate over all files, extract frames at regular intervals, and save full resolution frame images to disk.
|
||||||
|
|
||||||
|
This tool supports a wide variety of input video containers and codecs (via OpenCV), and exports jpg or png files.
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
### --vid_dir
|
||||||
|
|
||||||
|
Required directory path for input video files.
|
||||||
|
|
||||||
|
### --out_dir
|
||||||
|
|
||||||
|
Optional directory path in which to store extracted frame images. Defaults to a directory named 'output' that will be created inside the specified videos directory.
|
||||||
|
|
||||||
|
### --format
|
||||||
|
|
||||||
|
The format for image files saved to disk. Defaults to `png`, or optionally `jpg`.
|
||||||
|
|
||||||
|
### --interval
|
||||||
|
|
||||||
|
The number of seconds between frame captures. Defaults to 10 seconds.
|
|
@ -1,42 +1,90 @@
|
||||||
# extract frames from videos every n seconds
|
import argparse
|
||||||
|
|
||||||
import cv2
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import cv2
|
||||||
|
|
||||||
video_base_path = Path('../movies')
|
def get_parser(**parser_kwargs):
|
||||||
frames_root_path = Path('../frames')
|
parser = argparse.ArgumentParser(**parser_kwargs)
|
||||||
|
parser.add_argument(
|
||||||
|
"--vid_dir",
|
||||||
|
required=True,
|
||||||
|
type=str,
|
||||||
|
nargs="?",
|
||||||
|
const=True,
|
||||||
|
help="directory with videos to extract frames",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--out_dir",
|
||||||
|
type=str,
|
||||||
|
nargs="?",
|
||||||
|
const=True,
|
||||||
|
help="directory to put extracted images",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--format",
|
||||||
|
type=str,
|
||||||
|
nargs="?",
|
||||||
|
const=True,
|
||||||
|
default="png",
|
||||||
|
choices=["png", "jpg"],
|
||||||
|
help="image file format of the extracted frames",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--interval",
|
||||||
|
type=int,
|
||||||
|
nargs="?",
|
||||||
|
const=True,
|
||||||
|
default=10,
|
||||||
|
help="number of seconds between frame captures",
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
interval = 30 #seconds
|
def get_videos(input_dir):
|
||||||
|
for f in input_dir.iterdir():
|
||||||
|
file_path = Path(f)
|
||||||
|
if file_path.suffix in [".mp4", ".avi", ".mov", ".mpeg", ".mpg", ".mkv"]:
|
||||||
|
yield file_path
|
||||||
|
|
||||||
if not video_base_path.exists():
|
def capture_frames(input_dir, output_dir):
|
||||||
print('Video base path does not exist')
|
print (f'Capturing video frames in {opt.interval} second intervals.\n')
|
||||||
exit(1)
|
|
||||||
|
|
||||||
if not frames_root_path.exists():
|
|
||||||
os.mkdir(frames_root_path)
|
|
||||||
|
|
||||||
# loop over all files in the base path
|
|
||||||
for video_path in video_base_path.iterdir():
|
|
||||||
frames_folder = frames_root_path / f'frames-{video_path.stem}'
|
|
||||||
if not frames_folder.exists():
|
|
||||||
os.mkdir(frames_folder)
|
|
||||||
|
|
||||||
print(f'Loading video {video_path}')
|
|
||||||
print(f'Saving frames to {frames_folder}')
|
|
||||||
|
|
||||||
|
for video_path in get_videos(input_dir):
|
||||||
|
print(f'Extracting {video_path}')
|
||||||
cap = cv2.VideoCapture(str(video_path))
|
cap = cv2.VideoCapture(str(video_path))
|
||||||
fps = cap.get(cv2.CAP_PROP_FPS)
|
if not cap.isOpened():
|
||||||
count = 0
|
print(f'Could not open video')
|
||||||
|
continue
|
||||||
|
|
||||||
while(cap.isOpened()):
|
output = output_dir / video_path.stem
|
||||||
|
output.mkdir(exist_ok=True, parents=True)
|
||||||
|
|
||||||
|
current_frame = 0
|
||||||
|
count = 0
|
||||||
|
fps = cap.get(cv2.CAP_PROP_FPS)
|
||||||
|
while cap.isOpened():
|
||||||
ret, frame = cap.read()
|
ret, frame = cap.read()
|
||||||
if ret:
|
if ret:
|
||||||
cv2.imwrite(str(frames_folder / f'frame{count}.jpg'), frame)
|
count_str = str(count).zfill(4)
|
||||||
count += fps * interval
|
cv2.imwrite(str(output / f'frame_{count_str}.{opt.format}'), frame)
|
||||||
cap.set(cv2.CAP_PROP_POS_FRAMES, count)
|
current_frame += fps * opt.interval
|
||||||
|
cap.set(cv2.CAP_PROP_POS_FRAMES, current_frame)
|
||||||
|
count += 1
|
||||||
else:
|
else:
|
||||||
cap.release()
|
cap.release()
|
||||||
break
|
break
|
||||||
|
|
||||||
print('done')
|
print(f'\nFinished extracting frames to {output_dir}\n')
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = get_parser()
|
||||||
|
opt = parser.parse_args()
|
||||||
|
|
||||||
|
if (not Path(opt.vid_dir).exists):
|
||||||
|
print("Video directory does not exist.")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if (opt.out_dir is None):
|
||||||
|
output = Path(opt.vid_dir) / "output"
|
||||||
|
print(f"No output directory specified, using default: {output}")
|
||||||
|
else:
|
||||||
|
output = Path(opt.out_dir)
|
||||||
|
capture_frames(Path(opt.vid_dir), output)
|
||||||
|
|
Loading…
Reference in New Issue