import shutil
import sys
from pathlib import Path
import cv2 as cv
suffix_set = set(".avi,.mp4,.MOV".split(","))
[docs]def video_info(fpath):
cap = cv.VideoCapture(fpath)
fps = int(cap.get(cv.CAP_PROP_FPS))
count = int(cap.get(cv.CAP_PROP_FRAME_COUNT))
width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))
cap.release()
return fps, count, width, height
[docs]def find_videos(input_dir, end_tag="_tof"):
video_paths = []
for fpath in sorted(Path(input_dir).glob("**/*")):
if fpath.suffix not in suffix_set:
continue
video_paths.append(fpath)
links = {}
main_files = []
len_tag = len(end_tag)
for fpath in video_paths:
fstem = fpath.stem
if fstem.endswith(end_tag):
links[fstem[:-len_tag]] = fpath.as_posix()
else:
main_files.append((fstem, fpath.as_posix()))
video_pairs = []
for fstem, fpath in main_files:
video_pairs.append((fpath, links.get(fstem)))
return video_pairs
[docs]def align_pairs(infile1, infile2, outdir):
info_1 = video_info(infile1)
info_2 = info_1
if infile2 is not None:
info_2 = video_info(infile2)
s1 = info_1[1] // info_1[0]
s2 = info_2[1] // info_2[0]
s = min(s1, s2)
if s < 1:
return None
clip_video_opencv(outdir, infile1, 0, s)
if infile2 is not None:
clip_video_opencv(outdir, infile2, 0, s)
[docs]def clip_video_opencv(outdir, infile, t_start, t_end):
outfile = Path(outdir) / f"data/{Path(infile).stem}.mp4"
print(f"\n[CLIP]\n in: {infile}\nout: {outfile}")
fourcc = cv.VideoWriter_fourcc(*"mp4v")
cap = cv.VideoCapture(infile)
fps = int(cap.get(cv.CAP_PROP_FPS))
count = int(cap.get(cv.CAP_PROP_FRAME_COUNT))
width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))
out = cv.VideoWriter(str(outfile), fourcc, fps, (width, height))
a, b = t_start * fps, t_end * fps
curr_pos = 0
while curr_pos < count:
ret, frame = cap.read()
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
if a <= curr_pos < b:
out.write(frame)
curr_pos += 1
cap.release()
out.release()
[docs]def func(input_dir, output_dir, end_tag):
output_dir = Path(output_dir)
shutil.rmtree(output_dir, ignore_errors=True)
(output_dir / "data").mkdir(parents=True, exist_ok=False)
video_pairs = find_videos(input_dir, end_tag=end_tag)
for file1, file2 in video_pairs:
align_pairs(file1, file2, output_dir)
return f"\n[OUTDIR]\n{output_dir}"
[docs]def parse_args(args=None):
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument("input_dir", type=str,
help="videos dir")
parser.add_argument("-o", "--output_dir", type=str,
help="output dir")
parser.add_argument("-e", "--end-tag", type=str, default="_tof",
help="the pair video file")
args = parser.parse_args(args=args)
return vars(args)
[docs]def main(args=None):
kwargs = parse_args(args)
print(f"{__file__}: {kwargs}")
print(func(**kwargs))
return 0
if __name__ == "__main__":
sys.exit(main())