:param filepath: str :return: list of PIL Images
(filepath,predictor)
| 47 | |
| 48 | |
| 49 | def align_face(filepath,predictor): |
| 50 | """ |
| 51 | :param filepath: str |
| 52 | :return: list of PIL Images |
| 53 | """ |
| 54 | |
| 55 | lms = get_landmark(filepath,predictor) |
| 56 | imgs = [] |
| 57 | for lm in lms: |
| 58 | lm_chin = lm[0: 17] # left-right |
| 59 | lm_eyebrow_left = lm[17: 22] # left-right |
| 60 | lm_eyebrow_right = lm[22: 27] # left-right |
| 61 | lm_nose = lm[27: 31] # top-down |
| 62 | lm_nostrils = lm[31: 36] # top-down |
| 63 | lm_eye_left = lm[36: 42] # left-clockwise |
| 64 | lm_eye_right = lm[42: 48] # left-clockwise |
| 65 | lm_mouth_outer = lm[48: 60] # left-clockwise |
| 66 | lm_mouth_inner = lm[60: 68] # left-clockwise |
| 67 | |
| 68 | # Calculate auxiliary vectors. |
| 69 | eye_left = np.mean(lm_eye_left, axis=0) |
| 70 | eye_right = np.mean(lm_eye_right, axis=0) |
| 71 | eye_avg = (eye_left + eye_right) * 0.5 |
| 72 | eye_to_eye = eye_right - eye_left |
| 73 | mouth_left = lm_mouth_outer[0] |
| 74 | mouth_right = lm_mouth_outer[6] |
| 75 | mouth_avg = (mouth_left + mouth_right) * 0.5 |
| 76 | eye_to_mouth = mouth_avg - eye_avg |
| 77 | |
| 78 | # Choose oriented crop rectangle. |
| 79 | x = eye_to_eye - np.flipud(eye_to_mouth) * [-1, 1] |
| 80 | x /= np.hypot(*x) |
| 81 | x *= max(np.hypot(*eye_to_eye) * 2.0, np.hypot(*eye_to_mouth) * 1.8) |
| 82 | y = np.flipud(x) * [-1, 1] |
| 83 | c = eye_avg + eye_to_mouth * 0.1 |
| 84 | quad = np.stack([c - x - y, c - x + y, c + x + y, c + x - y]) |
| 85 | qsize = np.hypot(*x) * 2 |
| 86 | |
| 87 | # read image |
| 88 | img = PIL.Image.open(filepath) |
| 89 | |
| 90 | output_size = 1024 |
| 91 | transform_size = 4096 |
| 92 | enable_padding = True |
| 93 | |
| 94 | # Shrink. |
| 95 | shrink = int(np.floor(qsize / output_size * 0.5)) |
| 96 | if shrink > 1: |
| 97 | rsize = (int(np.rint(float(img.size[0]) / shrink)), int(np.rint(float(img.size[1]) / shrink))) |
| 98 | img = img.resize(rsize, PIL.Image.ANTIALIAS) |
| 99 | quad /= shrink |
| 100 | qsize /= shrink |
| 101 | |
| 102 | # Crop. |
| 103 | border = max(int(np.rint(qsize * 0.1)), 3) |
| 104 | crop = (int(np.floor(min(quad[:, 0]))), int(np.floor(min(quad[:, 1]))), int(np.ceil(max(quad[:, 0]))), |
| 105 | int(np.ceil(max(quad[:, 1])))) |
| 106 | crop = (max(crop[0] - border, 0), max(crop[1] - border, 0), min(crop[2] + border, img.size[0]), |
no test coverage detected