Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/Face-Recognition-with-ArcFace/align/matlab_cp2tform.py
3142 views
1
import numpy as np
2
from numpy.linalg import inv, norm, lstsq
3
from numpy.linalg import matrix_rank as rank
4
5
6
class MatlabCp2tormException(Exception):
7
def __str__(self):
8
return "In File {}:{}".format(
9
__file__, super.__str__(self))
10
11
def tformfwd(trans, uv):
12
"""
13
Function:
14
----------
15
apply affine transform 'trans' to uv
16
17
Parameters:
18
----------
19
@trans: 3x3 np.array
20
transform matrix
21
@uv: Kx2 np.array
22
each row is a pair of coordinates (x, y)
23
24
Returns:
25
----------
26
@xy: Kx2 np.array
27
each row is a pair of transformed coordinates (x, y)
28
"""
29
uv = np.hstack((
30
uv, np.ones((uv.shape[0], 1))
31
))
32
xy = np.dot(uv, trans)
33
xy = xy[:, 0:-1]
34
return xy
35
36
37
def tforminv(trans, uv):
38
"""
39
Function:
40
----------
41
apply the inverse of affine transform 'trans' to uv
42
43
Parameters:
44
----------
45
@trans: 3x3 np.array
46
transform matrix
47
@uv: Kx2 np.array
48
each row is a pair of coordinates (x, y)
49
50
Returns:
51
----------
52
@xy: Kx2 np.array
53
each row is a pair of inverse-transformed coordinates (x, y)
54
"""
55
Tinv = inv(trans)
56
xy = tformfwd(Tinv, uv)
57
return xy
58
59
60
def findNonreflectiveSimilarity(uv, xy, options=None):
61
62
options = {'K': 2}
63
64
K = options['K']
65
M = xy.shape[0]
66
x = xy[:, 0].reshape((-1, 1)) # use reshape to keep a column vector
67
y = xy[:, 1].reshape((-1, 1)) # use reshape to keep a column vector
68
# print('--->x, y:\n', x, y
69
70
tmp1 = np.hstack((x, y, np.ones((M, 1)), np.zeros((M, 1))))
71
tmp2 = np.hstack((y, -x, np.zeros((M, 1)), np.ones((M, 1))))
72
X = np.vstack((tmp1, tmp2))
73
# print('--->X.shape: ', X.shape
74
# print('X:\n', X
75
76
u = uv[:, 0].reshape((-1, 1)) # use reshape to keep a column vector
77
v = uv[:, 1].reshape((-1, 1)) # use reshape to keep a column vector
78
U = np.vstack((u, v))
79
# print('--->U.shape: ', U.shape
80
# print('U:\n', U
81
82
# We know that X * r = U
83
if rank(X) >= 2 * K:
84
r, _, _, _ = lstsq(X, U)
85
r = np.squeeze(r)
86
else:
87
raise Exception("cp2tform: two Unique Points Req")
88
89
# print('--->r:\n', r
90
91
sc = r[0]
92
ss = r[1]
93
tx = r[2]
94
ty = r[3]
95
96
Tinv = np.array([
97
[sc, -ss, 0],
98
[ss, sc, 0],
99
[tx, ty, 1]
100
])
101
102
# print('--->Tinv:\n', Tinv
103
104
T = inv(Tinv)
105
# print('--->T:\n', T
106
107
T[:, 2] = np.array([0, 0, 1])
108
109
return T, Tinv
110
111
112
def findSimilarity(uv, xy, options=None):
113
114
options = {'K': 2}
115
116
# uv = np.array(uv)
117
# xy = np.array(xy)
118
119
# Solve for trans1
120
trans1, trans1_inv = findNonreflectiveSimilarity(uv, xy, options)
121
122
# Solve for trans2
123
124
# manually reflect the xy data across the Y-axis
125
xyR = xy
126
xyR[:, 0] = -1 * xyR[:, 0]
127
128
trans2r, trans2r_inv = findNonreflectiveSimilarity(uv, xyR, options)
129
130
# manually reflect the tform to undo the reflection done on xyR
131
TreflectY = np.array([
132
[-1, 0, 0],
133
[0, 1, 0],
134
[0, 0, 1]
135
])
136
137
trans2 = np.dot(trans2r, TreflectY)
138
139
# Figure out if trans1 or trans2 is better
140
xy1 = tformfwd(trans1, uv)
141
norm1 = norm(xy1 - xy)
142
143
xy2 = tformfwd(trans2, uv)
144
norm2 = norm(xy2 - xy)
145
146
if norm1 <= norm2:
147
return trans1, trans1_inv
148
else:
149
trans2_inv = inv(trans2)
150
return trans2, trans2_inv
151
152
153
def get_similarity_transform(src_pts, dst_pts, reflective = True):
154
"""
155
Function:
156
----------
157
Find Similarity Transform Matrix 'trans':
158
u = src_pts[:, 0]
159
v = src_pts[:, 1]
160
x = dst_pts[:, 0]
161
y = dst_pts[:, 1]
162
[x, y, 1] = [u, v, 1] * trans
163
164
Parameters:
165
----------
166
@src_pts: Kx2 np.array
167
source points, each row is a pair of coordinates (x, y)
168
@dst_pts: Kx2 np.array
169
destination points, each row is a pair of transformed
170
coordinates (x, y)
171
@reflective: True or False
172
if True:
173
use reflective similarity transform
174
else:
175
use non-reflective similarity transform
176
177
Returns:
178
----------
179
@trans: 3x3 np.array
180
transform matrix from uv to xy
181
trans_inv: 3x3 np.array
182
inverse of trans, transform matrix from xy to uv
183
"""
184
185
if reflective:
186
trans, trans_inv = findSimilarity(src_pts, dst_pts)
187
else:
188
trans, trans_inv = findNonreflectiveSimilarity(src_pts, dst_pts)
189
190
return trans, trans_inv
191
192
193
def cvt_tform_mat_for_cv2(trans):
194
"""
195
Function:
196
----------
197
Convert Transform Matrix 'trans' into 'cv2_trans' which could be
198
directly used by cv2.warpAffine():
199
u = src_pts[:, 0]
200
v = src_pts[:, 1]
201
x = dst_pts[:, 0]
202
y = dst_pts[:, 1]
203
[x, y].T = cv_trans * [u, v, 1].T
204
205
Parameters:
206
----------
207
@trans: 3x3 np.array
208
transform matrix from uv to xy
209
210
Returns:
211
----------
212
@cv2_trans: 2x3 np.array
213
transform matrix from src_pts to dst_pts, could be directly used
214
for cv2.warpAffine()
215
"""
216
cv2_trans = trans[:, 0:2].T
217
218
return cv2_trans
219
220
221
def get_similarity_transform_for_cv2(src_pts, dst_pts, reflective = True):
222
"""
223
Function:
224
----------
225
Find Similarity Transform Matrix 'cv2_trans' which could be
226
directly used by cv2.warpAffine():
227
u = src_pts[:, 0]
228
v = src_pts[:, 1]
229
x = dst_pts[:, 0]
230
y = dst_pts[:, 1]
231
[x, y].T = cv_trans * [u, v, 1].T
232
233
Parameters:
234
----------
235
@src_pts: Kx2 np.array
236
source points, each row is a pair of coordinates (x, y)
237
@dst_pts: Kx2 np.array
238
destination points, each row is a pair of transformed
239
coordinates (x, y)
240
reflective: True or False
241
if True:
242
use reflective similarity transform
243
else:
244
use non-reflective similarity transform
245
246
Returns:
247
----------
248
@cv2_trans: 2x3 np.array
249
transform matrix from src_pts to dst_pts, could be directly used
250
for cv2.warpAffine()
251
"""
252
trans, trans_inv = get_similarity_transform(src_pts, dst_pts, reflective)
253
cv2_trans = cvt_tform_mat_for_cv2(trans)
254
255
return cv2_trans
256
257
258
if __name__ == '__main__':
259
"""
260
u = [0, 6, -2]
261
v = [0, 3, 5]
262
x = [-1, 0, 4]
263
y = [-1, -10, 4]
264
265
# In Matlab, run:
266
#
267
# uv = [u'; v'];
268
# xy = [x'; y'];
269
# tform_sim=cp2tform(uv,xy,'similarity');
270
#
271
# trans = tform_sim.tdata.T
272
# ans =
273
# -0.0764 -1.6190 0
274
# 1.6190 -0.0764 0
275
# -3.2156 0.0290 1.0000
276
# trans_inv = tform_sim.tdata.Tinv
277
# ans =
278
#
279
# -0.0291 0.6163 0
280
# -0.6163 -0.0291 0
281
# -0.0756 1.9826 1.0000
282
# xy_m=tformfwd(tform_sim, u,v)
283
#
284
# xy_m =
285
#
286
# -3.2156 0.0290
287
# 1.1833 -9.9143
288
# 5.0323 2.8853
289
# uv_m=tforminv(tform_sim, x,y)
290
#
291
# uv_m =
292
#
293
# 0.5698 1.3953
294
# 6.0872 2.2733
295
# -2.6570 4.3314
296
"""
297
u = [0, 6, -2]
298
v = [0, 3, 5]
299
x = [-1, 0, 4]
300
y = [-1, -10, 4]
301
302
uv = np.array((u, v)).T
303
xy = np.array((x, y)).T
304
305
print("\n--->uv:")
306
print(uv)
307
print("\n--->xy:")
308
print(xy)
309
310
trans, trans_inv = get_similarity_transform(uv, xy)
311
312
print("\n--->trans matrix:")
313
print(trans)
314
315
print("\n--->trans_inv matrix:")
316
print(trans_inv)
317
318
print("\n---> apply transform to uv")
319
print("\nxy_m = uv_augmented * trans")
320
uv_aug = np.hstack((
321
uv, np.ones((uv.shape[0], 1))
322
))
323
xy_m = np.dot(uv_aug, trans)
324
print(xy_m)
325
326
print("\nxy_m = tformfwd(trans, uv)")
327
xy_m = tformfwd(trans, uv)
328
print(xy_m)
329
330
print("\n---> apply inverse transform to xy")
331
print("\nuv_m = xy_augmented * trans_inv")
332
xy_aug = np.hstack((
333
xy, np.ones((xy.shape[0], 1))
334
))
335
uv_m = np.dot(xy_aug, trans_inv)
336
print(uv_m)
337
338
print("\nuv_m = tformfwd(trans_inv, xy)")
339
uv_m = tformfwd(trans_inv, xy)
340
print(uv_m)
341
342
uv_m = tforminv(trans, xy)
343
print("\nuv_m = tforminv(trans, xy)")
344
print(uv_m)
345