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