Spaces:
Build error
Build error
| import cv2 | |
| import numpy as np | |
| def umeyama(src, dst, estimate_scale): | |
| num = src.shape[0] | |
| dim = src.shape[1] | |
| src_mean = src.mean(axis=0) | |
| dst_mean = dst.mean(axis=0) | |
| src_demean = src - src_mean | |
| dst_demean = dst - dst_mean | |
| A = np.dot(dst_demean.T, src_demean) / num | |
| d = np.ones((dim,), dtype=np.double) | |
| if np.linalg.det(A) < 0: | |
| d[dim - 1] = -1 | |
| T = np.eye(dim + 1, dtype=np.double) | |
| U, S, V = np.linalg.svd(A) | |
| rank = np.linalg.matrix_rank(A) | |
| if rank == 0: | |
| return np.nan * T | |
| elif rank == dim - 1: | |
| if np.linalg.det(U) * np.linalg.det(V) > 0: | |
| T[:dim, :dim] = np.dot(U, V) | |
| else: | |
| s = d[dim - 1] | |
| d[dim - 1] = -1 | |
| T[:dim, :dim] = np.dot(U, np.dot(np.diag(d), V)) | |
| d[dim - 1] = s | |
| else: | |
| T[:dim, :dim] = np.dot(U, np.dot(np.diag(d), V.T)) | |
| if estimate_scale: | |
| scale = 1.0 / src_demean.var(axis=0).sum() * np.dot(S, d) | |
| else: | |
| scale = 1.0 | |
| T[:dim, dim] = dst_mean - scale * np.dot(T[:dim, :dim], src_mean.T) | |
| T[:dim, :dim] *= scale | |
| return T | |
| arcface_dst = np.array( | |
| [[38.2946, 51.6963], [73.5318, 51.5014], [56.0252, 71.7366], | |
| [41.5493, 92.3655], [70.7299, 92.2041]], | |
| dtype=np.float32) | |
| def estimate_norm(lmk, image_size=112, mode='arcface'): | |
| assert lmk.shape == (5, 2) | |
| assert image_size % 112 == 0 or image_size % 128 == 0 | |
| if image_size % 112 == 0: | |
| ratio = float(image_size) / 112.0 | |
| diff_x = 0 | |
| else: | |
| ratio = float(image_size) / 128.0 | |
| diff_x = 8.0 * ratio | |
| dst = arcface_dst * ratio | |
| dst[:, 0] += diff_x | |
| M = umeyama(lmk, dst, True)[0:2, :] | |
| return M | |
| def norm_crop2(img, landmark, image_size=112, mode='arcface'): | |
| M = estimate_norm(landmark, image_size, mode) | |
| warped = cv2.warpAffine(img, M, (image_size, image_size), borderValue=0.0, borderMode=cv2.BORDER_REPLICATE) | |
| return warped, M | |
| def get_cropped_head(img, landmark, scale=1.4): | |
| # it is ugly but works :D | |
| center = np.mean(landmark, axis=0) | |
| landmark = center + (landmark - center) * scale | |
| M = estimate_norm(landmark, 128, mode='arcface') | |
| warped = cv2.warpAffine(img, M/0.25, (512, 512), borderValue=0.0) | |
| return warped |