1+ import numpy as np
2+ from pathlib import Path
3+ from gdl .datasets .ImageDatasetHelpers import bbox2point , bbpoint_warp
4+ import skvideo
5+ import types
6+
7+
8+ def align_face (image , landmarks , landmark_type , scale_adjustment , target_size_height , target_size_width = None ,):
9+ """
10+ Returns an image with the face aligned to the center of the image.
11+ :param image: The full resolution image in which to align the face.
12+ :param landmarks: The landmarks of the face in the image (in the original image coordinates).
13+ :param landmark_type: The type of landmarks. Such as 'kpt68' or 'bbox' or 'mediapipe'.
14+ :param scale_adjustment: The scale adjustment to apply to the image.
15+ :param target_size_height: The height of the output image.
16+ :param target_size_width: The width of the output image. If not provided, it is assumed to be the same as target_size_height.
17+ :return: The aligned face image. The image will be in range [0,1].
18+ """
19+ # landmarks_for_alignment = "mediapipe"
20+ left = landmarks [:,0 ].min ()
21+ top = landmarks [:,1 ].min ()
22+ right = landmarks [:,0 ].max ()
23+ bottom = landmarks [:,1 ].max ()
24+
25+ old_size , center = bbox2point (left , right , top , bottom , type = landmark_type )
26+ size = (old_size * scale_adjustment ).astype (np .int32 )
27+
28+ img_warped , lmk_warped = bbpoint_warp (image , center , size , target_size_height , target_size_width , landmarks = landmarks )
29+
30+ return img_warped
31+
32+
33+ def align_video (video , centers , sizes , landmarks , target_size_height , target_size_width = None , ):
34+ """
35+ Returns a video with the face aligned to the center of the image.
36+ :param video: The full resolution video in which to align the face.
37+ :param landmarks: The landmarks of the face in the video (in the original video coordinates).
38+ :param target_size_height: The height of the output video.
39+ :param target_size_width: The width of the output video. If not provided, it is assumed to be the same as target_size_height.
40+ :return: The aligned face video. The video will be in range [0,1].
41+ """
42+ if isinstance (video , (str , Path )):
43+ video = skvideo .io .vread (video )
44+ elif isinstance (video , (np .ndarray , types .GeneratorType )):
45+ pass
46+ else :
47+ raise ValueError ("video must be a string, Path, or numpy array" )
48+
49+ aligned_video = []
50+ warped_landmarks = []
51+ if isinstance (video , np .ndarray ):
52+ for i in range (len (centers )):
53+ img_warped , lmk_warped = bbpoint_warp (video [i ], centers [i ], sizes [i ],
54+ target_size_height = target_size_height , target_size_width = target_size_width ,
55+ landmarks = landmarks [i ])
56+ aligned_video .append (img_warped )
57+ warped_landmarks += [lmk_warped ]
58+
59+ elif isinstance (video , types .GeneratorType ):
60+ for i , frame in enumerate (video ):
61+ img_warped , lmk_warped = bbpoint_warp (frame , centers [i ], sizes [i ],
62+ target_size_height = target_size_height , target_size_width = target_size_width ,
63+ landmarks = landmarks [i ])
64+ aligned_video .append (img_warped )
65+ warped_landmarks += [lmk_warped ]
66+
67+ aligned_video = np .stack (aligned_video , axis = 0 )
68+ return aligned_video , warped_landmarks
69+
70+
71+ def align_and_save_video (video , out_video_path , centers , sizes , landmarks , target_size_height , target_size_width = None , output_dict = None ):
72+ """
73+ Returns a video with the face aligned to the center of the image.
74+ :param video: The full resolution video in which to align the face.
75+ :param landmarks: The landmarks of the face in the video (in the original video coordinates).
76+ :param target_size_height: The height of the output video.
77+ :param target_size_width: The width of the output video. If not provided, it is assumed to be the same as target_size_height.
78+ :return: The aligned face video. The video will be in range [0,1].
79+ """
80+ if isinstance (video , (str , Path )):
81+ video = skvideo .io .vread (video )
82+ elif isinstance (video , (np .ndarray , types .GeneratorType )):
83+ pass
84+ else :
85+ raise ValueError ("video must be a string, Path, or numpy array" )
86+
87+ writer = skvideo .io .FFmpegWriter (str (out_video_path ), outputdict = output_dict )
88+ warped_landmarks = []
89+ if isinstance (video , np .ndarray ):
90+ for i in range (len (centers )):
91+ img_warped , lmk_warped = bbpoint_warp (video [i ], centers [i ], sizes [i ],
92+ target_size_height = target_size_height , target_size_width = target_size_width ,
93+ landmarks = landmarks [i ])
94+ img_warped = (img_warped * 255 ).astype (np .uint8 )
95+ writer .writeFrame (img_warped )
96+ warped_landmarks += [lmk_warped ]
97+
98+ elif isinstance (video , types .GeneratorType ):
99+ for i , frame in enumerate (video ):
100+ img_warped , lmk_warped = bbpoint_warp (frame , centers [i ], sizes [i ],
101+ target_size_height = target_size_height , target_size_width = target_size_width ,
102+ landmarks = landmarks [i ])
103+ img_warped = (img_warped * 255 ).astype (np .uint8 )
104+ writer .writeFrame (img_warped )
105+ warped_landmarks += [lmk_warped ]
106+ writer .close ()
107+
108+ return warped_landmarks
0 commit comments