Spaces:
Runtime error
Runtime error
import cv2 | |
import numpy as np | |
from skimage import transform as trans | |
arcface_src = 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) | |
arcface_src = np.expand_dims(arcface_src, axis=0) | |
def estimate_norm(lmk, face_size, dst_face_size, expand_size): | |
assert lmk.shape == (5, 2) | |
tform = trans.SimilarityTransform() | |
lmk_tran = np.insert(lmk, 2, values=np.ones(5), axis=1) | |
min_M = [] | |
min_index = [] | |
min_error = float('inf') | |
assert face_size == 112 | |
src = (arcface_src / face_size * dst_face_size) + (expand_size - dst_face_size) / 2 | |
for i in np.arange(src.shape[0]): | |
tform.estimate(lmk, src[i]) | |
M = tform.params[0:2, :] | |
results = np.dot(M, lmk_tran.T) | |
results = results.T | |
error = np.sum(np.sqrt(np.sum((results - src[i]) ** 2, axis=1))) | |
if error < min_error: | |
min_error = error | |
min_M = M | |
min_index = i | |
return min_M, min_index | |
def metrix_M(face_size, expand_size, keypoints=None): | |
id_size = 112 | |
detected_lmk = np.concatenate(keypoints).reshape(5, 2) | |
M, _ = estimate_norm(detected_lmk, id_size, face_size, expand_size) | |
Minv = np.identity(3, dtype=np.single) | |
Minv[0:2, :] = M | |
M = Minv[0:2, :] | |
return M | |
def decompose_tfm(tfm): | |
tfm = tfm.copy() | |
s_x = np.sqrt(tfm[0][0] ** 2 + tfm[0][1] ** 2) | |
s_y = np.sqrt(tfm[1][0] ** 2 + tfm[1][1] ** 2) | |
t_x = tfm[0][2] | |
t_y = tfm[1][2] | |
#平移旋转矩阵rt | |
rt = np.array([ | |
[tfm[0][0] / s_x, tfm[0][1] / s_x, t_x / s_x], | |
[tfm[1][0] / s_y, tfm[1][1] / s_y, t_y / s_y], | |
]) | |
#缩放矩阵s | |
s = np.array([ | |
[s_x, 0, 0], | |
[0, s_y, 0] | |
]) | |
# _rt = np.vstack([rt, [[0, 0, 1]]]) | |
# _s = np.vstack([s, [[0, 0, 1]]]) | |
# print(np.dot(_s, _rt)[:2] - tfm) | |
return rt, s | |
def img_warp(img, M, expand_size, adjust=0): | |
warped = cv2.warpAffine(img, M, (expand_size, expand_size)) | |
warped = warped - np.uint8(adjust) | |
warped = np.clip(warped, 0, 255) | |
return warped | |
def img_warp_back_inv_m(img, img_to, inv_m): | |
h_up, w_up, c = img_to.shape | |
mask = np.ones_like(img).astype(np.float32) | |
inv_mask = cv2.warpAffine(mask, inv_m, (w_up, h_up)) | |
inv_img = cv2.warpAffine(img, inv_m, (w_up, h_up)) | |
img_to[inv_mask == 1] = inv_img[inv_mask == 1] | |
return img_to | |
def get_video_fps(vfile): | |
cap = cv2.VideoCapture(vfile) | |
fps = cap.get(cv2.CAP_PROP_FPS) | |
cap.release() | |
return fps | |
class laplacianSmooth(object): | |
def __init__(self, smoothAlpha=0.3): | |
self.smoothAlpha = smoothAlpha | |
self.pts_last = None | |
def smooth(self, pts_cur): | |
if self.pts_last is None: | |
self.pts_last = pts_cur.copy() | |
return pts_cur.copy() | |
x1 = min(pts_cur[:, 0]) | |
x2 = max(pts_cur[:, 0]) | |
y1 = min(pts_cur[:, 1]) | |
y2 = max(pts_cur[:, 1]) | |
width = x2 - x1 | |
pts_update = [] | |
for i in range(len(pts_cur)): | |
x_new, y_new = pts_cur[i] | |
x_old, y_old = self.pts_last[i] | |
tmp = (x_new - x_old) ** 2 + (y_new - y_old) ** 2 | |
w = np.exp(-tmp / (width * self.smoothAlpha)) | |
x = x_old * w + x_new * (1 - w) | |
y = y_old * w + y_new * (1 - w) | |
pts_update.append([x, y]) | |
pts_update = np.array(pts_update) | |
self.pts_last = pts_update.copy() | |
return pts_update | |