File size: 2,090 Bytes
7826761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from __future__ import annotations

from pathlib import Path

import cv2
import numpy as np
import torch
from tqdm import tqdm

from camera import Camera
from tracker.inference.preprocess import enlarge_bbox

from .visualizer import Visualizer


def save_tracking_video(
    output_path: str | Path,
    video_input,
    inference,
    camera: Camera,
    visualizer: Visualizer,
    vertices: torch.Tensor,
    fallback_fps: float,
) -> None:
    fps = float(fallback_fps) if video_input.fps is None else float(video_input.fps)
    video_input.reset()
    frame_size = (int(inference.image_width * 2), int(inference.image_height * 2))
    writer = cv2.VideoWriter(
        str(output_path), cv2.VideoWriter_fourcc(*"mp4v"), fps, frame_size
    )
    if not writer.isOpened():
        raise OSError(f"Failed to open video writer: {output_path}")

    try:
        num_frames = int(inference.vertex_coord.shape[0])
        for frame_id in tqdm(range(num_frames), desc="visualize video"):
            frame_rgb = video_input.read()
            if frame_rgb is None:
                raise ValueError(f"Unexpected end of input at frame {frame_id}.")

            alignment = visualizer.vis_align(frame_rgb, inference.vertex_coord[frame_id])
            alignment = visualizer.vis_contour(alignment, inference.vertex_coord[frame_id])
            bbox = np.round(enlarge_bbox(inference.face_bbox[frame_id], 1.3)).astype(np.int32)
            cv2.rectangle(alignment, bbox[:2], bbox[2:], (255, 0, 0), 2)
            overlay, shading = visualizer.vis_flame_shading_overlay(
                camera, frame_rgb, vertices[frame_id], alpha=0.5, return_shading=True
            )
            result = np.ascontiguousarray(
                np.concatenate(
                    [
                        np.concatenate([frame_rgb, alignment], axis=1),
                        np.concatenate([overlay, shading], axis=1),
                    ],
                    axis=0,
                )
            )
            writer.write(cv2.cvtColor(result, cv2.COLOR_RGB2BGR))
    finally:
        writer.release()