@@ -108,6 +108,8 @@ def poly2obb(polys, version='oc'):
108108 results = poly2obb_le135 (polys )
109109 elif version == 'le90' :
110110 results = poly2obb_le90 (polys )
111+ elif version == 'full360' :
112+ results = poly2obb_full360 (polys )
111113 else :
112114 raise NotImplementedError
113115 return results
@@ -129,6 +131,8 @@ def poly2obb_np(polys, version='oc'):
129131 results = poly2obb_np_le135 (polys )
130132 elif version == 'le90' :
131133 results = poly2obb_np_le90 (polys )
134+ elif version == 'full360' :
135+ results = poly2obb_np_full360 (polys )
132136 else :
133137 raise NotImplementedError
134138 return results
@@ -150,6 +154,9 @@ def obb2hbb(rbboxes, version='oc'):
150154 results = obb2hbb_le135 (rbboxes )
151155 elif version == 'le90' :
152156 results = obb2hbb_le90 (rbboxes )
157+ elif version == 'full360' :
158+ # NOTE: same as 90
159+ results = obb2hbb_le90 (rbboxes )
153160 else :
154161 raise NotImplementedError
155162 return results
@@ -171,6 +178,9 @@ def obb2poly(rbboxes, version='oc'):
171178 results = obb2poly_le135 (rbboxes )
172179 elif version == 'le90' :
173180 results = obb2poly_le90 (rbboxes )
181+ elif version == 'full360' :
182+ # NOTE: same as 90
183+ results = obb2poly_le90 (rbboxes )
174184 else :
175185 raise NotImplementedError
176186 return results
@@ -192,6 +202,8 @@ def obb2poly_np(rbboxes, version='oc'):
192202 results = obb2poly_np_le135 (rbboxes )
193203 elif version == 'le90' :
194204 results = obb2poly_np_le90 (rbboxes )
205+ elif version == 'full360' :
206+ results = obb2poly_np_full360 (rbboxes )
195207 else :
196208 raise NotImplementedError
197209 return results
@@ -213,6 +225,9 @@ def obb2xyxy(rbboxes, version='oc'):
213225 results = obb2xyxy_le135 (rbboxes )
214226 elif version == 'le90' :
215227 results = obb2xyxy_le90 (rbboxes )
228+ elif version == 'full360' :
229+ # NOTE: same as 90
230+ results = obb2xyxy_le90 (rbboxes )
216231 else :
217232 raise NotImplementedError
218233 return results
@@ -235,6 +250,7 @@ def hbb2obb(hbboxes, version='oc'):
235250 elif version == 'le90' :
236251 results = hbb2obb_le90 (hbboxes )
237252 else :
253+ # NOTE: not well defined for full360. Leave it unimplemented
238254 raise NotImplementedError
239255 return results
240256
@@ -298,6 +314,31 @@ def poly2obb_le135(polys):
298314 return torch .stack ([x_ctr , y_ctr , width , height , angles ], 1 )
299315
300316
317+ def poly2obb_full360 (polys ):
318+ """Convert polygons to oriented bounding boxes.
319+
320+ Args:
321+ polys (torch.Tensor): [x0,y0,x1,y1,x2,y2,x3,y3]
322+
323+ Returns:
324+ obbs (torch.Tensor): [x_ctr,y_ctr,w,h,angle]
325+ """
326+ polys = torch .reshape (polys , [- 1 , 8 ])
327+ pt1 , pt2 , pt3 , _ = polys [..., :8 ].chunk (4 , 1 )
328+ width = torch .sqrt (
329+ torch .pow (pt1 [..., 0 ] - pt2 [..., 0 ], 2 ) +
330+ torch .pow (pt1 [..., 1 ] - pt2 [..., 1 ], 2 ))
331+ height = torch .sqrt (
332+ torch .pow (pt2 [..., 0 ] - pt3 [..., 0 ], 2 ) +
333+ torch .pow (pt2 [..., 1 ] - pt3 [..., 1 ], 2 ))
334+ angles = torch .atan2 ((pt1 [..., 1 ] - pt2 [..., 1 ]),
335+ (pt1 [..., 0 ] - pt2 [..., 0 ]))
336+ angles = norm_angle (angles , 'full360' )
337+ x_ctr = (pt1 [..., 0 ] + pt3 [..., 0 ]) / 2.0
338+ y_ctr = (pt1 [..., 1 ] + pt3 [..., 1 ]) / 2.0
339+ return torch .stack ([x_ctr , y_ctr , width , height , angles ], 1 )
340+
341+
301342def poly2obb_le90 (polys ):
302343 """Convert polygons to oriented bounding boxes.
303344
@@ -418,6 +459,33 @@ def poly2obb_np_le90(poly):
418459 return x , y , w , h , a
419460
420461
462+ def poly2obb_np_full360 (poly ):
463+ """Convert polygons to oriented bounding boxes. Assumes head points then
464+ tail points.
465+
466+ Args:
467+ polys (ndarray): [x0,y0,x1,y1,x2,y2,x3,y3]
468+
469+ Returns:
470+ obbs (ndarray): [x_ctr,y_ctr,w,h,angle]
471+ """
472+ pt1 , pt2 , pt3 , pt4 = np .array (poly ).reshape ((4 , 2 ))
473+ x , y = (pt1 + pt2 + pt3 + pt4 ) / 4.0
474+ dx , dy = pt2 - pt1
475+ a = np .arctan2 (dy , dx )
476+ w = np .linalg .norm (pt2 - pt1 )
477+ h = np .linalg .norm (pt3 - pt2 )
478+ if w < 2 or h < 2 :
479+ return
480+ while not np .pi > a >= - np .pi :
481+ if a >= np .pi :
482+ a -= np .pi
483+ else :
484+ a += np .pi
485+ assert np .pi > a >= - np .pi
486+ return x , y , w , h , a
487+
488+
421489def obb2poly_oc (rboxes ):
422490 """Convert oriented bounding boxes to polygons.
423491
@@ -634,6 +702,26 @@ def hbb2obb_le90(hbboxes):
634702 return obboxes
635703
636704
705+ def hbb2obb_full360 (hbboxes ):
706+ """Convert horizontal bounding boxes to oriented bounding boxes.
707+
708+ Args:
709+ hbbs (torch.Tensor): [x_lt,y_lt,x_rb,y_rb]
710+
711+ Returns:
712+ obbs (torch.Tensor): [x_ctr,y_ctr,w,h,angle]
713+ """
714+ x = (hbboxes [..., 0 ] + hbboxes [..., 2 ]) * 0.5
715+ y = (hbboxes [..., 1 ] + hbboxes [..., 3 ]) * 0.5
716+ w = hbboxes [..., 2 ] - hbboxes [..., 0 ]
717+ h = hbboxes [..., 3 ] - hbboxes [..., 1 ]
718+ theta = x .new_zeros (* x .shape )
719+ obboxes1 = torch .stack ([x , y , w , h , theta ], dim = - 1 )
720+ obboxes2 = torch .stack ([x , y , h , w , theta - np .pi / 2 ], dim = - 1 )
721+ obboxes = torch .where ((w >= h )[..., None ], obboxes1 , obboxes2 )
722+ return obboxes
723+
724+
637725def obb2xyxy_oc (rbboxes ):
638726 """Convert oriented bounding boxes to horizontal bounding boxes.
639727
@@ -783,6 +871,31 @@ def obb2poly_np_le90(obboxes):
783871 return polys
784872
785873
874+ def obb2poly_np_full360 (obboxes ):
875+ """Convert oriented bounding boxes to polygons.
876+
877+ Args:
878+ obbs (ndarray): [x_ctr,y_ctr,w,h,angle,score]
879+
880+ Returns:
881+ polys (ndarray): [x0,y0,x1,y1,x2,y2,x3,y3,score]
882+ """
883+ try :
884+ center , w , h , theta , score = np .split (obboxes , (2 , 3 , 4 , 5 ), axis = - 1 )
885+ except : # noqa: E722
886+ results = np .stack ([0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], axis = - 1 )
887+ return results .reshape (1 , - 1 )
888+ Cos , Sin = np .cos (theta ), np .sin (theta )
889+ vector1 = np .concatenate ([w / 2 * Cos , w / 2 * Sin ], axis = - 1 )
890+ vector2 = np .concatenate ([- h / 2 * Sin , h / 2 * Cos ], axis = - 1 )
891+ point1 = center - vector1 - vector2
892+ point2 = center + vector1 - vector2
893+ point3 = center + vector1 + vector2
894+ point4 = center - vector1 + vector2
895+ polys = np .concatenate ([point1 , point2 , point3 , point4 , score ], axis = - 1 )
896+ return polys
897+
898+
786899def cal_line_length (point1 , point2 ):
787900 """Calculate the length of line.
788901
@@ -863,6 +976,8 @@ def norm_angle(angle, angle_range):
863976 return (angle + np .pi / 4 ) % np .pi - np .pi / 4
864977 elif angle_range == 'le90' :
865978 return (angle + np .pi / 2 ) % np .pi - np .pi / 2
979+ elif angle_range == 'full360' :
980+ return angle % (2 * np .pi ) - np .pi
866981 else :
867982 print ('Not yet implemented.' )
868983
0 commit comments