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 |