SunderAli17 commited on
Commit
cd98a68
1 Parent(s): b230f3c

Create matlab_cp2tform.py

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