1
+ # Copyright (c) OpenMMLab. All rights reserved.
2
+ #####################
3
+ # Based on https://github.com/hongzhenwang/RRPN-revise
4
+ # Licensed under The MIT License
5
+ # Author: yanyan, scrin@foxmail.com
6
+ #####################
7
+ import math
8
+ import numpy as np
9
+
10
+
11
+ def div_up (m , n ):
12
+ return m // n + (m % n > 0 )
13
+
14
+ def trangle_area (a , b , c ):
15
+ return ((a [0 ] - c [0 ]) * (b [1 ] - c [1 ]) - (a [1 ] - c [1 ]) *
16
+ (b [0 ] - c [0 ])) / 2.0
17
+
18
+
19
+ def area (int_pts , num_of_inter ):
20
+ area_val = 0.0
21
+ for i in range (num_of_inter - 2 ):
22
+ area_val += abs (
23
+ trangle_area (int_pts [:2 ], int_pts [2 * i + 2 :2 * i + 4 ],
24
+ int_pts [2 * i + 4 :2 * i + 6 ]))
25
+ return area_val
26
+
27
+
28
+ def sort_vertex_in_convex_polygon (int_pts , num_of_inter ):
29
+ if num_of_inter > 0 :
30
+ center = np .zeros ((2 , ), dtype = np .float32 )
31
+ center [:] = 0.0
32
+ for i in range (num_of_inter ):
33
+ center [0 ] += int_pts [2 * i ]
34
+ center [1 ] += int_pts [2 * i + 1 ]
35
+ center [0 ] /= num_of_inter
36
+ center [1 ] /= num_of_inter
37
+ v = np .zeros ((2 , ), dtype = np .float32 )
38
+ vs = np .zeros ((16 , ), dtype = np .float32 )
39
+ for i in range (num_of_inter ):
40
+ v [0 ] = int_pts [2 * i ] - center [0 ]
41
+ v [1 ] = int_pts [2 * i + 1 ] - center [1 ]
42
+ d = math .sqrt (v [0 ] * v [0 ] + v [1 ] * v [1 ])
43
+ v [0 ] = v [0 ] / d
44
+ v [1 ] = v [1 ] / d
45
+ if v [1 ] < 0 :
46
+ v [0 ] = - 2 - v [0 ]
47
+ vs [i ] = v [0 ]
48
+ j = 0
49
+ temp = 0
50
+ for i in range (1 , num_of_inter ):
51
+ if vs [i - 1 ] > vs [i ]:
52
+ temp = vs [i ]
53
+ tx = int_pts [2 * i ]
54
+ ty = int_pts [2 * i + 1 ]
55
+ j = i
56
+ while j > 0 and vs [j - 1 ] > temp :
57
+ vs [j ] = vs [j - 1 ]
58
+ int_pts [j * 2 ] = int_pts [j * 2 - 2 ]
59
+ int_pts [j * 2 + 1 ] = int_pts [j * 2 - 1 ]
60
+ j -= 1
61
+
62
+ vs [j ] = temp
63
+ int_pts [j * 2 ] = tx
64
+ int_pts [j * 2 + 1 ] = ty
65
+
66
+
67
+ def line_segment_intersection (pts1 , pts2 , i , j , temp_pts ):
68
+ A = np .zeros ((2 , ), dtype = np .float32 )
69
+ B = np .zeros ((2 , ), dtype = np .float32 )
70
+ C = np .zeros ((2 , ), dtype = np .float32 )
71
+ D = np .zeros ((2 , ), dtype = np .float32 )
72
+
73
+ A [0 ] = pts1 [2 * i ]
74
+ A [1 ] = pts1 [2 * i + 1 ]
75
+
76
+ B [0 ] = pts1 [2 * ((i + 1 ) % 4 )]
77
+ B [1 ] = pts1 [2 * ((i + 1 ) % 4 ) + 1 ]
78
+
79
+ C [0 ] = pts2 [2 * j ]
80
+ C [1 ] = pts2 [2 * j + 1 ]
81
+
82
+ D [0 ] = pts2 [2 * ((j + 1 ) % 4 )]
83
+ D [1 ] = pts2 [2 * ((j + 1 ) % 4 ) + 1 ]
84
+ BA0 = B [0 ] - A [0 ]
85
+ BA1 = B [1 ] - A [1 ]
86
+ DA0 = D [0 ] - A [0 ]
87
+ CA0 = C [0 ] - A [0 ]
88
+ DA1 = D [1 ] - A [1 ]
89
+ CA1 = C [1 ] - A [1 ]
90
+ acd = DA1 * CA0 > CA1 * DA0
91
+ bcd = (D [1 ] - B [1 ]) * (C [0 ] - B [0 ]) > (C [1 ] - B [1 ]) * (D [0 ] - B [0 ])
92
+ if acd != bcd :
93
+ abc = CA1 * BA0 > BA1 * CA0
94
+ abd = DA1 * BA0 > BA1 * DA0
95
+ if abc != abd :
96
+ DC0 = D [0 ] - C [0 ]
97
+ DC1 = D [1 ] - C [1 ]
98
+ ABBA = A [0 ] * B [1 ] - B [0 ] * A [1 ]
99
+ CDDC = C [0 ] * D [1 ] - D [0 ] * C [1 ]
100
+ DH = BA1 * DC0 - BA0 * DC1
101
+ Dx = ABBA * DC0 - BA0 * CDDC
102
+ Dy = ABBA * DC1 - BA1 * CDDC
103
+ temp_pts [0 ] = Dx / DH
104
+ temp_pts [1 ] = Dy / DH
105
+ return True
106
+ return False
107
+
108
+
109
+ def line_segment_intersection_v1 (pts1 , pts2 , i , j , temp_pts ):
110
+ a = np .zeros ((2 , ), dtype = np .float32 )
111
+ b = np .zeros ((2 , ), dtype = np .float32 )
112
+ c = np .zeros ((2 , ), dtype = np .float32 )
113
+ d = np .zeros ((2 , ), dtype = np .float32 )
114
+
115
+ a [0 ] = pts1 [2 * i ]
116
+ a [1 ] = pts1 [2 * i + 1 ]
117
+
118
+ b [0 ] = pts1 [2 * ((i + 1 ) % 4 )]
119
+ b [1 ] = pts1 [2 * ((i + 1 ) % 4 ) + 1 ]
120
+
121
+ c [0 ] = pts2 [2 * j ]
122
+ c [1 ] = pts2 [2 * j + 1 ]
123
+
124
+ d [0 ] = pts2 [2 * ((j + 1 ) % 4 )]
125
+ d [1 ] = pts2 [2 * ((j + 1 ) % 4 ) + 1 ]
126
+
127
+ area_abc = trangle_area (a , b , c )
128
+ area_abd = trangle_area (a , b , d )
129
+
130
+ if area_abc * area_abd >= 0 :
131
+ return False
132
+
133
+ area_cda = trangle_area (c , d , a )
134
+ area_cdb = area_cda + area_abc - area_abd
135
+
136
+ if area_cda * area_cdb >= 0 :
137
+ return False
138
+ t = area_cda / (area_abd - area_abc )
139
+
140
+ dx = t * (b [0 ] - a [0 ])
141
+ dy = t * (b [1 ] - a [1 ])
142
+ temp_pts [0 ] = a [0 ] + dx
143
+ temp_pts [1 ] = a [1 ] + dy
144
+ return True
145
+
146
+
147
+ def point_in_quadrilateral (pt_x , pt_y , corners ):
148
+ ab0 = corners [2 ] - corners [0 ]
149
+ ab1 = corners [3 ] - corners [1 ]
150
+
151
+ ad0 = corners [6 ] - corners [0 ]
152
+ ad1 = corners [7 ] - corners [1 ]
153
+
154
+ ap0 = pt_x - corners [0 ]
155
+ ap1 = pt_y - corners [1 ]
156
+
157
+ abab = ab0 * ab0 + ab1 * ab1
158
+ abap = ab0 * ap0 + ab1 * ap1
159
+ adad = ad0 * ad0 + ad1 * ad1
160
+ adap = ad0 * ap0 + ad1 * ap1
161
+
162
+ return abab >= abap and abap >= 0 and adad >= adap and adap >= 0
163
+
164
+
165
+ def quadrilateral_intersection (pts1 , pts2 , int_pts ):
166
+ num_of_inter = 0
167
+ for i in range (4 ):
168
+ if point_in_quadrilateral (pts1 [2 * i ], pts1 [2 * i + 1 ], pts2 ):
169
+ int_pts [num_of_inter * 2 ] = pts1 [2 * i ]
170
+ int_pts [num_of_inter * 2 + 1 ] = pts1 [2 * i + 1 ]
171
+ num_of_inter += 1
172
+ if point_in_quadrilateral (pts2 [2 * i ], pts2 [2 * i + 1 ], pts1 ):
173
+ int_pts [num_of_inter * 2 ] = pts2 [2 * i ]
174
+ int_pts [num_of_inter * 2 + 1 ] = pts2 [2 * i + 1 ]
175
+ num_of_inter += 1
176
+ temp_pts = np .zeros ((2 , ), dtype = np .float32 )
177
+ for i in range (4 ):
178
+ for j in range (4 ):
179
+ has_pts = line_segment_intersection (pts1 , pts2 , i , j , temp_pts )
180
+ if has_pts :
181
+ int_pts [num_of_inter * 2 ] = temp_pts [0 ]
182
+ int_pts [num_of_inter * 2 + 1 ] = temp_pts [1 ]
183
+ num_of_inter += 1
184
+
185
+ return num_of_inter
186
+
187
+
188
+ def rbbox_to_corners (corners , rbbox ):
189
+ # generate clockwise corners and rotate it clockwise
190
+ angle = rbbox [4 ]
191
+ a_cos = math .cos (angle )
192
+ a_sin = math .sin (angle )
193
+ center_x = rbbox [0 ]
194
+ center_y = rbbox [1 ]
195
+ x_d = rbbox [2 ]
196
+ y_d = rbbox [3 ]
197
+ corners_x = np .zeros ((4 , ), dtype = np .float32 )
198
+ corners_y = np .zeros ((4 , ), dtype = np .float32 )
199
+ corners_x [0 ] = - x_d / 2
200
+ corners_x [1 ] = - x_d / 2
201
+ corners_x [2 ] = x_d / 2
202
+ corners_x [3 ] = x_d / 2
203
+ corners_y [0 ] = - y_d / 2
204
+ corners_y [1 ] = y_d / 2
205
+ corners_y [2 ] = y_d / 2
206
+ corners_y [3 ] = - y_d / 2
207
+ for i in range (4 ):
208
+ corners [2 *
209
+ i ] = a_cos * corners_x [i ] + a_sin * corners_y [i ] + center_x
210
+ corners [2 * i
211
+ + 1 ] = - a_sin * corners_x [i ] + a_cos * corners_y [i ] + center_y
212
+
213
+
214
+ def inter (rbbox1 , rbbox2 ):
215
+ corners1 = np .zeros ((8 , ), dtype = np .float32 )
216
+ corners2 = np .zeros ((8 , ), dtype = np .float32 )
217
+ intersection_corners = np .zeros ((16 , ), dtype = np .float32 )
218
+
219
+ rbbox_to_corners (corners1 , rbbox1 )
220
+ rbbox_to_corners (corners2 , rbbox2 )
221
+
222
+ num_intersection = quadrilateral_intersection (corners1 , corners2 ,
223
+ intersection_corners )
224
+ sort_vertex_in_convex_polygon (intersection_corners , num_intersection )
225
+ # print(intersection_corners.reshape([-1, 2])[:num_intersection])
226
+
227
+ return area (intersection_corners , num_intersection )
228
+
229
+
230
+ def devRotateIoUEval (rbox1 , rbox2 , criterion = - 1 ):
231
+ area1 = rbox1 [2 ] * rbox1 [3 ]
232
+ area2 = rbox2 [2 ] * rbox2 [3 ]
233
+ area_inter = inter (rbox1 , rbox2 )
234
+ if criterion == - 1 :
235
+ return area_inter / (area1 + area2 - area_inter )
236
+ elif criterion == 0 :
237
+ return area_inter / area1
238
+ elif criterion == 1 :
239
+ return area_inter / area2
240
+ else :
241
+ return area_inter
242
+
243
+
244
+ def rotate_iou_cpu_eval (dev_boxes , dev_query_boxes , criterion = - 1 ):
245
+ num_boxes = dev_boxes .shape [0 ]
246
+ num_qboxes = dev_query_boxes .shape [0 ]
247
+ dev_iou = np .zeros ((num_boxes , num_qboxes ))
248
+ for box_i in range (num_boxes ):
249
+ for qbox_i in range (num_qboxes ):
250
+ dev_iou [box_i , qbox_i ] = devRotateIoUEval (dev_query_boxes [qbox_i ], dev_boxes [box_i ], criterion )
251
+
252
+ return dev_iou
0 commit comments