Skip to content

Instantly share code, notes, and snippets.

@brunomsantiago
Created March 24, 2021 23:30
Show Gist options
  • Save brunomsantiago/620520808005bcbc42b6a9551d4978b9 to your computer and use it in GitHub Desktop.
Save brunomsantiago/620520808005bcbc42b6a9551d4978b9 to your computer and use it in GitHub Desktop.
Making thumbnail mosaic from videos using Python and OpenCV
from pathlib import Path
import cv2
import numpy as np
def make_mosaic(cap, n_rows=4, n_cols=5):
n_frames = n_rows * n_cols
cap_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
floor = int(cap_frames*0.05)
ceil = int(cap_frames*0.95)
frames_indexes = np.linspace(floor, ceil, n_frames).astype(int)
frames = []
for frame_index in frames_indexes:
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
success, frame = cap.read()
if success:
frames.append(frame)
if n_frames != len(frames):
raise Exception(f'Frame extraction error. Got {len(frames)}. Expected {n_frames}')
rows_list = [frames[x:x+n_cols]
for x
in range(0, len(frames), n_cols)]
rows = [np.hstack(row) for row in rows_list]
mosaic = np.vstack(rows)
return mosaic
def downscale(image, max_height=3500, max_width=3000):
height, width = image.shape[:2]
h_ratio, w_ratio = height/max_height, width/max_width
ratio = max(h_ratio, w_ratio)
if ratio <= 1.0:
return image
new_dim = int(width/ratio), int(height/ratio)
return cv2.resize(image, new_dim, interpolation = cv2.INTER_CUBIC)
def save_mosaic(video_filepath, overwrite=True, **kwargs):
video_filepath = Path(video_filepath)
name = video_filepath.name
base_name = '.'.join(name.split('.')[:-1])
mosaic_name = f'{base_name}.jpg'
mosaic_filepath = video_filepath.parent / mosaic_name
if overwrite or not(mosaic_filepath.exists()):
cap = cv2.VideoCapture(video_filepath.as_posix())
mosaic = make_mosaic(cap, **kwargs)
mosaic2 = downscale(mosaic, **kwargs)
cv2.imwrite(mosaic_filepath.as_posix(), mosaic2)
def batch_mosaic(folder,
video_suffixes=['.mp4', '.wmv', '.avi'],
**kwargs):
folder = Path(folder)
files = sorted(folder.glob('*'))
video_files = [f for f in files
if f.suffix in video_suffixes]
# video_files = video_files[0:2]
for n, file in enumerate(video_files):
print(f'Making mosaic {n+1}\n {file.name}')
try:
save_mosaic(file, **kwargs)
except Exception as e:
print(f' {e}\n\n\n')
folder = Path().cwd()
batch_mosaic(folder, overwrite=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment