|
from pathlib import Path |
|
from urllib.parse import urlparse |
|
|
|
import numpy as np |
|
from PIL import Image |
|
|
|
|
|
def get_video_frames(video_pth, frames_video=15): |
|
import cv2 |
|
|
|
assert Path(video_pth).exists(), f"Video {video_pth} does not exist" |
|
|
|
video_pth = str(video_pth) |
|
|
|
|
|
cap = cv2.VideoCapture(video_pth) |
|
|
|
|
|
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) |
|
|
|
frame_idxs = sample_frames(total_frames, n_frames=frames_video) |
|
|
|
frames = [] |
|
f_idxs = [] |
|
for frame_idx in frame_idxs: |
|
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx) |
|
ret, frame = cap.read() |
|
|
|
if not ret or frame is None: |
|
print(f"Video {video_pth} is corrupted") |
|
frames = [ |
|
Image.fromarray(np.zeros((384, 384, 3)).astype(np.uint8)) |
|
] * frames_video |
|
f_idxs = [-1] * frames_video |
|
return frames, f_idxs |
|
|
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
|
frames.append(Image.fromarray(frame)) |
|
f_idxs.append(frame_idx) |
|
|
|
|
|
n_frames = len(frames) |
|
if n_frames < frames_video: |
|
frames += [Image.fromarray(np.zeros((384, 384, 3)).astype(np.uint8))] * ( |
|
frames_video - n_frames |
|
) |
|
|
|
|
|
f_idxs += [-1] * (frames_video - len(f_idxs)) |
|
|
|
return frames, f_idxs |
|
|
|
|
|
def sample_frames(vlen, n_frames=15): |
|
acc_samples = min(vlen, n_frames) |
|
intervals = np.linspace(start=0, stop=vlen, num=acc_samples + 1).astype(int) |
|
ranges = [] |
|
for idx, interv in enumerate(intervals[:-1]): |
|
ranges.append((interv, intervals[idx + 1] - 1)) |
|
|
|
frame_idxs = [(x[0] + x[1]) // 2 for x in ranges] |
|
|
|
return frame_idxs |
|
|
|
|
|
def concat_h_imgs(im_list, resample=Image.Resampling.BICUBIC): |
|
min_height = min(im.height for im in im_list) |
|
im_list_resize = [ |
|
im.resize( |
|
(int(im.width * min_height / im.height), min_height), resample=resample |
|
) |
|
for im in im_list |
|
] |
|
total_width = sum(im.width for im in im_list_resize) |
|
dst = Image.new("RGB", (total_width, min_height)) |
|
pos_x = 0 |
|
for im in im_list_resize: |
|
dst.paste(im, (pos_x, 0)) |
|
pos_x += im.width |
|
return dst |
|
|
|
|
|
def extract_frames(url, n_frames=10): |
|
import urllib.request |
|
|
|
import cv2 |
|
import numpy as np |
|
from PIL import Image |
|
|
|
|
|
resp = urllib.request.urlopen(url) |
|
video = resp.read() |
|
|
|
|
|
video = cv2.VideoCapture(url) |
|
|
|
|
|
total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) |
|
|
|
|
|
frames_idxs = sample_frames(total_frames, n_frames=n_frames) |
|
|
|
frames = [] |
|
for frame_number in frames_idxs: |
|
video.set(cv2.CAP_PROP_POS_FRAMES, frame_number) |
|
ret, frame = video.read() |
|
if ret: |
|
|
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
|
|
|
pil_image = Image.fromarray(np.uint8(frame)) |
|
frames.append(pil_image) |
|
return frames |
|
|
|
|
|
def visualize_url_video(url, n_frames=10): |
|
frames = extract_frames(url, n_frames=n_frames) |
|
if n_frames == 1: |
|
return frames[0] |
|
return concat_h_imgs(frames) |
|
|
|
|
|
def visualize_pth_video(video_pth, n_frames=10): |
|
frames, _ = get_video_frames(video_pth, frames_video=n_frames) |
|
if n_frames == 1: |
|
return frames[0] |
|
return concat_h_imgs(frames) |
|
|
|
|
|
def visualize_video(video, n_frames=10): |
|
if is_url(video): |
|
return visualize_url_video(video, n_frames=n_frames) |
|
return visualize_pth_video(video, n_frames=n_frames) |
|
|
|
|
|
def is_url(url_or_filename): |
|
parsed = urlparse(str(url_or_filename)) |
|
return parsed.scheme in ("http", "https") |
|
|