Spaces:
Runtime error
Runtime error
File size: 3,704 Bytes
e90b704 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
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
|