Path: blob/master/Face-Recognition-with-ArcFace/align/matlab_cp2tform.py
3142 views
import numpy as np1from numpy.linalg import inv, norm, lstsq2from numpy.linalg import matrix_rank as rank345class MatlabCp2tormException(Exception):6def __str__(self):7return "In File {}:{}".format(8__file__, super.__str__(self))910def tformfwd(trans, uv):11"""12Function:13----------14apply affine transform 'trans' to uv1516Parameters:17----------18@trans: 3x3 np.array19transform matrix20@uv: Kx2 np.array21each row is a pair of coordinates (x, y)2223Returns:24----------25@xy: Kx2 np.array26each row is a pair of transformed coordinates (x, y)27"""28uv = np.hstack((29uv, np.ones((uv.shape[0], 1))30))31xy = np.dot(uv, trans)32xy = xy[:, 0:-1]33return xy343536def tforminv(trans, uv):37"""38Function:39----------40apply the inverse of affine transform 'trans' to uv4142Parameters:43----------44@trans: 3x3 np.array45transform matrix46@uv: Kx2 np.array47each row is a pair of coordinates (x, y)4849Returns:50----------51@xy: Kx2 np.array52each row is a pair of inverse-transformed coordinates (x, y)53"""54Tinv = inv(trans)55xy = tformfwd(Tinv, uv)56return xy575859def findNonreflectiveSimilarity(uv, xy, options=None):6061options = {'K': 2}6263K = options['K']64M = xy.shape[0]65x = xy[:, 0].reshape((-1, 1)) # use reshape to keep a column vector66y = xy[:, 1].reshape((-1, 1)) # use reshape to keep a column vector67# print('--->x, y:\n', x, y6869tmp1 = np.hstack((x, y, np.ones((M, 1)), np.zeros((M, 1))))70tmp2 = np.hstack((y, -x, np.zeros((M, 1)), np.ones((M, 1))))71X = np.vstack((tmp1, tmp2))72# print('--->X.shape: ', X.shape73# print('X:\n', X7475u = uv[:, 0].reshape((-1, 1)) # use reshape to keep a column vector76v = uv[:, 1].reshape((-1, 1)) # use reshape to keep a column vector77U = np.vstack((u, v))78# print('--->U.shape: ', U.shape79# print('U:\n', U8081# We know that X * r = U82if rank(X) >= 2 * K:83r, _, _, _ = lstsq(X, U)84r = np.squeeze(r)85else:86raise Exception("cp2tform: two Unique Points Req")8788# print('--->r:\n', r8990sc = r[0]91ss = r[1]92tx = r[2]93ty = r[3]9495Tinv = np.array([96[sc, -ss, 0],97[ss, sc, 0],98[tx, ty, 1]99])100101# print('--->Tinv:\n', Tinv102103T = inv(Tinv)104# print('--->T:\n', T105106T[:, 2] = np.array([0, 0, 1])107108return T, Tinv109110111def findSimilarity(uv, xy, options=None):112113options = {'K': 2}114115# uv = np.array(uv)116# xy = np.array(xy)117118# Solve for trans1119trans1, trans1_inv = findNonreflectiveSimilarity(uv, xy, options)120121# Solve for trans2122123# manually reflect the xy data across the Y-axis124xyR = xy125xyR[:, 0] = -1 * xyR[:, 0]126127trans2r, trans2r_inv = findNonreflectiveSimilarity(uv, xyR, options)128129# manually reflect the tform to undo the reflection done on xyR130TreflectY = np.array([131[-1, 0, 0],132[0, 1, 0],133[0, 0, 1]134])135136trans2 = np.dot(trans2r, TreflectY)137138# Figure out if trans1 or trans2 is better139xy1 = tformfwd(trans1, uv)140norm1 = norm(xy1 - xy)141142xy2 = tformfwd(trans2, uv)143norm2 = norm(xy2 - xy)144145if norm1 <= norm2:146return trans1, trans1_inv147else:148trans2_inv = inv(trans2)149return trans2, trans2_inv150151152def get_similarity_transform(src_pts, dst_pts, reflective = True):153"""154Function:155----------156Find Similarity Transform Matrix 'trans':157u = src_pts[:, 0]158v = src_pts[:, 1]159x = dst_pts[:, 0]160y = dst_pts[:, 1]161[x, y, 1] = [u, v, 1] * trans162163Parameters:164----------165@src_pts: Kx2 np.array166source points, each row is a pair of coordinates (x, y)167@dst_pts: Kx2 np.array168destination points, each row is a pair of transformed169coordinates (x, y)170@reflective: True or False171if True:172use reflective similarity transform173else:174use non-reflective similarity transform175176Returns:177----------178@trans: 3x3 np.array179transform matrix from uv to xy180trans_inv: 3x3 np.array181inverse of trans, transform matrix from xy to uv182"""183184if reflective:185trans, trans_inv = findSimilarity(src_pts, dst_pts)186else:187trans, trans_inv = findNonreflectiveSimilarity(src_pts, dst_pts)188189return trans, trans_inv190191192def cvt_tform_mat_for_cv2(trans):193"""194Function:195----------196Convert Transform Matrix 'trans' into 'cv2_trans' which could be197directly used by cv2.warpAffine():198u = src_pts[:, 0]199v = src_pts[:, 1]200x = dst_pts[:, 0]201y = dst_pts[:, 1]202[x, y].T = cv_trans * [u, v, 1].T203204Parameters:205----------206@trans: 3x3 np.array207transform matrix from uv to xy208209Returns:210----------211@cv2_trans: 2x3 np.array212transform matrix from src_pts to dst_pts, could be directly used213for cv2.warpAffine()214"""215cv2_trans = trans[:, 0:2].T216217return cv2_trans218219220def get_similarity_transform_for_cv2(src_pts, dst_pts, reflective = True):221"""222Function:223----------224Find Similarity Transform Matrix 'cv2_trans' which could be225directly used by cv2.warpAffine():226u = src_pts[:, 0]227v = src_pts[:, 1]228x = dst_pts[:, 0]229y = dst_pts[:, 1]230[x, y].T = cv_trans * [u, v, 1].T231232Parameters:233----------234@src_pts: Kx2 np.array235source points, each row is a pair of coordinates (x, y)236@dst_pts: Kx2 np.array237destination points, each row is a pair of transformed238coordinates (x, y)239reflective: True or False240if True:241use reflective similarity transform242else:243use non-reflective similarity transform244245Returns:246----------247@cv2_trans: 2x3 np.array248transform matrix from src_pts to dst_pts, could be directly used249for cv2.warpAffine()250"""251trans, trans_inv = get_similarity_transform(src_pts, dst_pts, reflective)252cv2_trans = cvt_tform_mat_for_cv2(trans)253254return cv2_trans255256257if __name__ == '__main__':258"""259u = [0, 6, -2]260v = [0, 3, 5]261x = [-1, 0, 4]262y = [-1, -10, 4]263264# In Matlab, run:265#266# uv = [u'; v'];267# xy = [x'; y'];268# tform_sim=cp2tform(uv,xy,'similarity');269#270# trans = tform_sim.tdata.T271# ans =272# -0.0764 -1.6190 0273# 1.6190 -0.0764 0274# -3.2156 0.0290 1.0000275# trans_inv = tform_sim.tdata.Tinv276# ans =277#278# -0.0291 0.6163 0279# -0.6163 -0.0291 0280# -0.0756 1.9826 1.0000281# xy_m=tformfwd(tform_sim, u,v)282#283# xy_m =284#285# -3.2156 0.0290286# 1.1833 -9.9143287# 5.0323 2.8853288# uv_m=tforminv(tform_sim, x,y)289#290# uv_m =291#292# 0.5698 1.3953293# 6.0872 2.2733294# -2.6570 4.3314295"""296u = [0, 6, -2]297v = [0, 3, 5]298x = [-1, 0, 4]299y = [-1, -10, 4]300301uv = np.array((u, v)).T302xy = np.array((x, y)).T303304print("\n--->uv:")305print(uv)306print("\n--->xy:")307print(xy)308309trans, trans_inv = get_similarity_transform(uv, xy)310311print("\n--->trans matrix:")312print(trans)313314print("\n--->trans_inv matrix:")315print(trans_inv)316317print("\n---> apply transform to uv")318print("\nxy_m = uv_augmented * trans")319uv_aug = np.hstack((320uv, np.ones((uv.shape[0], 1))321))322xy_m = np.dot(uv_aug, trans)323print(xy_m)324325print("\nxy_m = tformfwd(trans, uv)")326xy_m = tformfwd(trans, uv)327print(xy_m)328329print("\n---> apply inverse transform to xy")330print("\nuv_m = xy_augmented * trans_inv")331xy_aug = np.hstack((332xy, np.ones((xy.shape[0], 1))333))334uv_m = np.dot(xy_aug, trans_inv)335print(uv_m)336337print("\nuv_m = tformfwd(trans_inv, xy)")338uv_m = tformfwd(trans_inv, xy)339print(uv_m)340341uv_m = tforminv(trans, xy)342print("\nuv_m = tforminv(trans, xy)")343print(uv_m)344345