import cv2 import numpy as np def get_similarity_transform(src_pts, dst_pts): """Get similarity transform matrix from src_pts to dst_pts Args: src_pts: Kx2 np.array source points matrix, each row is a pair of coordinates (x, y) dst_pts: Kx2 np.array destination points matrix, each row is a pair of coordinates (x, y) Returns: xform_matrix: 3x3 np.array transform matrix from src_pts to dst_pts """ src_pts = np.asarray(src_pts) dst_pts = np.asarray(dst_pts) assert src_pts.shape == dst_pts.shape assert (src_pts.ndim == 2) and (src_pts.shape[-1] == 2) npts = src_pts.shape[0] src_x = src_pts[:, 0].reshape((-1, 1)) src_y = src_pts[:, 1].reshape((-1, 1)) tmp1 = np.hstack((src_x, -src_y, np.ones((npts, 1)), np.zeros((npts, 1)))) tmp2 = np.hstack((src_y, src_x, np.zeros((npts, 1)), np.ones((npts, 1)))) A = np.vstack((tmp1, tmp2)) dst_x = dst_pts[:, 0].reshape((-1, 1)) dst_y = dst_pts[:, 1].reshape((-1, 1)) b = np.vstack((dst_x, dst_y)) x = np.linalg.lstsq(A, b, rcond=-1)[0] x = np.squeeze(x) sc, ss, tx, ty = x[0], x[1], x[2], x[3] xform_matrix = np.array([ [sc, -ss, tx], [ss, sc, ty], [ 0, 0, 1] ]) return xform_matrix def align_and_crop(image, landmarks, std_landmarks, align_size, border_value=0, return_transform_matrix=False): landmarks = np.asarray(landmarks) std_landmarks = np.asarray(std_landmarks) xform_matrix = get_similarity_transform(landmarks, std_landmarks) landmarks_ex = np.pad(landmarks, ((0,0),(0,1)), mode='constant', constant_values=1) dst_landmarks = np.dot(landmarks_ex, xform_matrix[:2,:].T) dst_image = cv2.warpAffine(image, xform_matrix[:2,:], dsize=align_size, borderValue=border_value) if return_transform_matrix: return dst_image, dst_landmarks, xform_matrix else: return dst_image, dst_landmarks