CoolFace
Apppublic

abdul168/Free-View_Expressive_Talking_Head_Video_Editing

sourceHugging Facecc-by-nc-4.0updated 4mo agoView on Hugging Face
0likes
preprocess_videos.py124 linesDownload Raw Back to root
1import face_detection2import numpy as np3import cv24from tqdm import tqdm5import torch6import glob7import os8from natsort import natsorted9 10device = "cuda" if torch.cuda.is_available() else "cpu"11 12 13def get_squre_coords(coords, image, size=None, last_size=None):14    y1, y2, x1, x2 = coords15    w, h = x2 - x1, y2 - y116    center = (x1 + w // 2, y1 + h // 2)17    if size is None:18        size = (w + h) // 219    if last_size is not None:20        size = (w + h) // 221        size = (size - last_size) // 5 + last_size22    x1, y1 = center[0] - size // 2, center[1] - size // 223    x2, y2 = x1 + size, y1 + size24    return size, [y1, y2, x1, x2]25 26 27def get_smoothened_boxes(boxes, T):28    for i in range(len(boxes)):29        if i + T > len(boxes):30            window = boxes[len(boxes) - T :]31        else:32            window = boxes[i : i + T]33        boxes[i] = np.mean(window, axis=0)34    return boxes35 36 37def face_detect(images, pads):38    detector = face_detection.FaceAlignment(face_detection.LandmarksType._2D, flip_input=False, device=device)39 40    batch_size = 32 if device == "cuda" else 441    print("face detect batch size:", batch_size)42    while 1:43        predictions = []44        try:45            for i in tqdm(range(0, len(images), batch_size)):46                predictions.extend(detector.get_detections_for_batch(np.array(images[i : i + batch_size])))47        except RuntimeError:48            if batch_size == 1:49                raise RuntimeError("Image too big to run face detection on GPU. Please use the --resize_factor argument")50            batch_size //= 251            print("Recovering from OOM error; New batch size: {}".format(batch_size))52            continue53        break54 55    results = []56    pady1, pady2, padx1, padx2 = pads57    for rect, image in zip(predictions, images):58        if rect is None:59            cv2.imwrite(".temp/faulty_frame.jpg", image)  # check this frame where the face was not detected.60            raise ValueError("Face not detected! Ensure the video contains a face in all the frames.")61 62        y1 = max(0, rect[1] - pady1)63        y2 = min(image.shape[0], rect[3] + pady2)64        x1 = max(0, rect[0] - padx1)65        x2 = min(image.shape[1], rect[2] + padx2)66        # y_gap, x_gap = ((y2 - y1) * 2) // 3, ((x2 - x1) * 2) // 367        y_gap, x_gap = (y2 - y1) // 2, (x2 - x1) // 268        coords_ = [y1 - y_gap, y2 + y_gap, x1 - x_gap, x2 + x_gap]69 70        _, coords = get_squre_coords(coords_, image)71 72        y1, y2, x1, x2 = coords73        y1 = max(0, y1)74        y2 = min(image.shape[0], y2)75        x1 = max(0, x1)76        x2 = min(image.shape[1], x2)77 78        results.append([x1, y1, x2, y2])79 80    print("Number of frames cropped: {}".format(len(results)))81    print("First coords: {}".format(results[0]))82    boxes = np.array(results)83    boxes = get_smoothened_boxes(boxes, T=25)84    # results = [[image[y1:y2, x1:x2], (y1, y2, x1, x2)] for image, (x1, y1, x2, y2) in zip(images, boxes)]85 86    del detector87    return boxes88 89 90def add_black(imgs):91    for i in range(len(imgs)):92        imgs[i] = cv2.vconcat([np.zeros((100, imgs[i].shape[1], 3), dtype=np.uint8), imgs[i], np.zeros((20, imgs[i].shape[1], 3), dtype=np.uint8)])93 94    return imgs95 96 97def preprocess(video_dir="./assets/videos", save_dir="./assets/coords"):98    all_videos = natsorted(glob.glob(os.path.join(video_dir, "*.mp4")))99    for video_path in all_videos:100        video_stream = cv2.VideoCapture(video_path)101 102        # print('Reading video frames...')103        full_frames = []104        while 1:105            still_reading, frame = video_stream.read()106            if not still_reading:107                video_stream.release()108                break109            full_frames.append(frame)110        print("Number of frames available for inference: " + str(len(full_frames)))111        full_frames = add_black(full_frames)112        # print('Face detection running...')113        coords = face_detect(full_frames, pads=(0, 0, 0, 0))114        np.savez_compressed(os.path.join(save_dir, os.path.basename(video_path).split(".")[0]), coords=coords)115 116 117def load_from_npz(video_name, save_dir="./assets/coords"):118    npz = np.load(os.path.join(save_dir, video_name + ".npz"))119    return npz["coords"]120 121 122if __name__ == "__main__":123    preprocess()124