| | import os |
| | import cv2 |
| | import numpy as np |
| | from PIL import Image |
| | from batch_face import RetinaFace |
| |
|
| |
|
| | def _get_square_face(coord, image, padding_scale = 1.5): |
| | x1, y1, x2, y2 = coord |
| | |
| | length = ((x2 - x1) + (y2 - y1)) // 2 |
| | x1 = x1 - length * (padding_scale - 1.0) |
| | x2 = x2 + length * (padding_scale - 1.0) |
| | y1 = y1 - length * (padding_scale - 1.0) |
| | y2 = y2 + length * (padding_scale - 1.0) |
| |
|
| | |
| | y1 -= length * (padding_scale - 1.0) * 0.2 |
| | y2 -= length * (padding_scale - 1.0) * 0.2 |
| |
|
| | |
| | center = (x1 + x2) // 2, (y1 + y2) // 2 |
| | length = max(x2 - x1, y2 - y1) // 2 |
| | x1 = max(int(round(center[0] - length)), 0) |
| | x2 = min(int(round(center[0] + length)), image.shape[1]) |
| | y1 = max(int(round(center[1] - length)), 0) |
| | y2 = min(int(round(center[1] + length)), image.shape[0]) |
| | return image[y1:y2, x1:x2] |
| |
|
| |
|
| | def _get_face_coord(face_detector, frame_cv2): |
| | faces = face_detector(frame_cv2, cv=True) |
| | if len(faces) == 0: |
| | raise ValueError("Face is not detected") |
| | else: |
| | coord = faces[0][0] |
| | return coord |
| |
|
| |
|
| |
|
| | def _smooth_coord(last_coord, current_coord, smooth_factor=0.1): |
| | change = np.array(current_coord) - np.array(last_coord) |
| | |
| | change = change * smooth_factor |
| | return (np.array(last_coord) + np.array(change)).astype(int).tolist() |
| |
|
| |
|
| | def get_face_img(face_detector, input_frame_path): |
| | print("Detecting face in the image...") |
| | frame_cv2 = cv2.imread(input_frame_path) |
| | coord = _get_face_coord(face_detector, frame_cv2) |
| | face = _get_square_face(coord, frame_cv2) |
| | face = cv2.cvtColor(face, cv2.COLOR_BGR2RGB) |
| | return Image.fromarray(face), coord |
| |
|
| |
|
| | def get_faces_video(face_detector, input_video_path): |
| | output_frames = [] |
| | output_coords = [] |
| | last_coord = None |
| |
|
| | print("Detecting faces in the video...") |
| | cap = cv2.VideoCapture(input_video_path) |
| | while cap.isOpened(): |
| | ret, frame = cap.read() |
| | if not ret: |
| | break |
| | face_coord = _get_face_coord(face_detector, frame) |
| | if last_coord is not None: |
| | face_coord = _smooth_coord(last_coord, face_coord) |
| | last_coord = face_coord |
| | face = _get_square_face(face_coord, frame) |
| | face = cv2.cvtColor(face, cv2.COLOR_BGR2RGB) |
| | face_pil = Image.fromarray(face) |
| | output_frames.append(face_pil) |
| | output_coords.append(face_coord) |
| | cap.release() |
| | return output_frames, output_coords |
| |
|
| |
|
| | if __name__ == '__main__': |
| | import torch |
| | face_detector = RetinaFace(gpu_id=0) if torch.cuda.is_available() else RetinaFace(gpu_id=-1) |
| | |
| | input_frame_path = './test_imgs/makeup/1.jpg' |
| | face, _ = get_face_img(face_detector, input_frame_path) |
| | face.save('face.png') |
| | print("Image saved to face.png") |
| |
|
| | |
| | import imageio |
| | from tqdm import tqdm |
| | frames, _ = get_faces_video(face_detector, './test_imgs/input_video.mp4') |
| | print("Number of frames: ", len(frames)) |
| | writer = imageio.get_writer('face.mp4', fps=30, macro_block_size=1, quality=8, codec="libx264") |
| | for frame in tqdm(frames): |
| | writer.append_data(np.array(frame.resize((512, 512)))) |
| | writer.close() |
| | print("Video saved to face.mp4") |
| |
|