|
import cv2 |
|
import numpy as np |
|
from skimage import transform as trans |
|
|
|
def affine_align(img, landmark=None, **kwargs): |
|
M = None |
|
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 ) |
|
|
|
|
|
dst = landmark.astype(np.float32) |
|
tform = trans.SimilarityTransform() |
|
tform.estimate(dst, src) |
|
M = tform.params[0:2,:] |
|
warped = cv2.warpAffine(img, M, (112, 112), borderValue = 0.0) |
|
return warped |
|
|
|
|
|
def kestrel_get_similar_matrix(src_points, dst_points): |
|
if src_points.size != dst_points.size: |
|
print("error: the size of src_points and dst_points must be same", |
|
"which is {0} vs. {1}".format(src_points.size, dst_points.size)) |
|
exit(-1) |
|
|
|
dst_points = dst_points.T.reshape(-1) |
|
|
|
point_num = src_points.shape[0] |
|
new_src_points = np.zeros((point_num * 2, 4)) |
|
new_src_points[:point_num, :2] = src_points |
|
new_src_points[:point_num, 2] = 1 |
|
new_src_points[:point_num, 3] = 0 |
|
|
|
new_src_points[point_num:, 0] = src_points[:, 1] |
|
new_src_points[point_num:, 1] = -src_points[:, 0] |
|
new_src_points[point_num:, 2] = 0 |
|
new_src_points[point_num:, 3] = 1 |
|
|
|
min_square_solution = np.linalg.lstsq(new_src_points, dst_points, |
|
rcond=-1)[0] |
|
|
|
trans_matrix = np.array([ |
|
[ min_square_solution[0], -min_square_solution[1], 0 ], |
|
[ min_square_solution[1], min_square_solution[0], 0 ], |
|
[ min_square_solution[2], min_square_solution[3], 1 ], |
|
]) |
|
|
|
return trans_matrix.T[:2] |
|
|
|
def transform(pts, M): |
|
dst = np.matmul(pts, M[:, :2].T) |
|
dst[:, 0] += M[0, 2] |
|
dst[:, 1] += M[1, 2] |
|
return dst |
|
|
|
|
|
def affine_alignSDK(img, landmark=None, borderMode=cv2.BORDER_REPLICATE, flags=cv2.INTER_LINEAR): |
|
M = None |
|
dst_points = np.array([[70.745156, 111.9996875], [108.23625, 111.9996875], [89.700875, 153.514375]], dtype=np.float32) |
|
default_shape = (178,218) |
|
lmk = landmark.astype(np.float32) |
|
src_points = np.array([ |
|
lmk[0], lmk[1], |
|
(lmk[3] + lmk[4]) / 2 |
|
], dtype=np.float32) |
|
|
|
trans_matrix = kestrel_get_similar_matrix(src_points, dst_points) |
|
trans_matrix = np.concatenate((trans_matrix, [[0, 0, 1]]), axis=0) |
|
|
|
return cv2.warpPerspective(img, trans_matrix, default_shape, borderMode, flags=flags), trans_matrix |
|
|