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 | |