Skip to content

Commit 373b25f

Browse files
authored
add angle_nms for post-process of rbbox
1 parent 29ea4dc commit 373b25f

File tree

4 files changed

+930
-0
lines changed

4 files changed

+930
-0
lines changed

angle_nms/angle_soft_nms.py

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
# --------------------------------------------------------
2+
# Fast R-CNN
3+
# Copyright (c) 2015 Microsoft
4+
# Licensed under The MIT License [see LICENSE for details]
5+
# Written by Ross Girshick
6+
# --------------------------------------------------------
7+
8+
# written by allenjbqin
9+
# 2019.05.15
10+
import os
11+
import numpy as np
12+
import ctypes
13+
from ctypes import *
14+
15+
so_file_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'librbox.so')
16+
so = ctypes.cdll.LoadLibrary
17+
librbox = so(so_file_path)
18+
19+
overlap = librbox.Overlap
20+
overlap.argtypes = (POINTER(c_double), POINTER(c_double))
21+
overlap.restype = c_double
22+
23+
24+
def py_cpu_nms(dets, thresh):
25+
"""Pure Python NMS baseline."""
26+
x1 = dets[:, 0]
27+
y1 = dets[:, 1]
28+
x2 = dets[:, 2]
29+
y2 = dets[:, 3]
30+
scores = dets[:, 4]
31+
32+
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
33+
order = scores.argsort()[::-1]
34+
35+
keep = []
36+
while order.size > 0:
37+
i = order[0]
38+
keep.append(i)
39+
xx1 = np.maximum(x1[i], x1[order[1:]])
40+
yy1 = np.maximum(y1[i], y1[order[1:]])
41+
xx2 = np.minimum(x2[i], x2[order[1:]])
42+
yy2 = np.minimum(y2[i], y2[order[1:]])
43+
44+
w = np.maximum(0.0, xx2 - xx1 + 1)
45+
h = np.maximum(0.0, yy2 - yy1 + 1)
46+
inter = w * h
47+
ovr = inter / (areas[i] + areas[order[1:]] - inter)
48+
49+
inds = np.where(ovr <= thresh)[0]
50+
order = order[inds + 1]
51+
52+
return keep
53+
54+
def angle_soft_nms(all_dets, sigma=0.5, Nt=0.1, threshold=0.001, method=0):
55+
"""Pure Python NMS baseline."""
56+
# dets = np.concatenate((all_dets[:, 0:4], all_dets[:, -1:]), axis=1)
57+
# scores = all_dets[:, 4]
58+
# cx,cy,w,h,angle,score
59+
# all_dets[:,4] = (all_dets[:,4]-0.5)*180.0
60+
all_dets[:,4] = all_dets[:,4] / np.pi *180.0
61+
boxes = all_dets
62+
# scores = all_dets[:, -1]
63+
N = all_dets.shape[0]
64+
if N >0 and len(boxes[0] == 7):
65+
is_scale = True
66+
else:
67+
is_scale = False
68+
69+
# # ## a simple example
70+
# a = np.array([10,10,10,20,0])
71+
# b = np.array([10,10,10,20,0.75])
72+
# cd_a = (c_double * 5)()
73+
# cd_b = (c_double * 5)()
74+
# cd_a[0] = c_double(a[0])
75+
# cd_a[1] = c_double(a[1])
76+
# cd_a[2] = c_double(a[2])
77+
# cd_a[3] = c_double(a[3])
78+
# cd_a[4] = c_double(a[4])
79+
# cd_b[0] = c_double(b[0])
80+
# cd_b[1] = c_double(b[1])
81+
# cd_b[2] = c_double(b[2])
82+
# cd_b[3] = c_double(b[3])
83+
# cd_b[4] = c_double(b[4])
84+
# ov = overlap(cd_a, cd_b)
85+
for i in range(N):
86+
maxscore = boxes[i, 5]
87+
maxpos = i
88+
# 将第i个bbox存在temp
89+
tcx = boxes[i, 0]
90+
tcy = boxes[i, 1]
91+
tw = boxes[i, 2]
92+
th = boxes[i, 3]
93+
tangle = boxes[i, 4]
94+
ts= boxes[i, 5]
95+
if is_scale:
96+
scale= boxes[i, 6]
97+
98+
pos = i + 1
99+
# get max box
100+
while pos < N:
101+
if maxscore < boxes[pos, 5]:
102+
maxscore = boxes[pos, 5]
103+
maxpos = pos
104+
pos = pos + 1
105+
106+
# add max box as a detection
107+
boxes[i, 0] = boxes[maxpos, 0]
108+
boxes[i, 1] = boxes[maxpos, 1]
109+
boxes[i, 2] = boxes[maxpos, 2]
110+
boxes[i, 3] = boxes[maxpos, 3]
111+
boxes[i, 4] = boxes[maxpos, 4]
112+
boxes[i, 5] = boxes[maxpos, 5]
113+
if is_scale:
114+
boxes[i, 6] = boxes[maxpos, 6]
115+
116+
# swap ith box with position of max box
117+
boxes[maxpos, 0] = tcx
118+
boxes[maxpos, 1] = tcy
119+
boxes[maxpos, 2] = tw
120+
boxes[maxpos, 3] = th
121+
boxes[maxpos, 4] = tangle
122+
boxes[maxpos, 5] = ts
123+
if is_scale:
124+
boxes[maxpos, 6] = scale
125+
126+
# 此时第i个位最大score的,重新将第i个bbox存在temp
127+
# tcx = boxes[i, 0]
128+
# tcy = boxes[i, 1]
129+
# tw = boxes[i, 2]
130+
# th = boxes[i, 3]
131+
# tangle = boxes[i, 4]
132+
# ts= boxes[i, 5]
133+
134+
box1 = (c_double * 5)()
135+
box2 = (c_double * 5)()
136+
box1[0] = c_double(boxes[i, 0])
137+
box1[1] = c_double(boxes[i, 1])
138+
box1[2] = c_double(boxes[i, 2])
139+
box1[3] = c_double(boxes[i, 3])
140+
box1[4] = c_double(boxes[i, 4])
141+
142+
pos = i + 1
143+
# NMS iterations, note that N changes if detection boxes fall below threshold
144+
while pos < N:
145+
box2[0] = c_double(boxes[pos, 0])
146+
box2[1] = c_double(boxes[pos, 1])
147+
box2[2] = c_double(boxes[pos, 2])
148+
box2[3] = c_double(boxes[pos, 3])
149+
box2[4] = c_double(boxes[pos, 4])
150+
151+
ov = overlap(box1, box2)
152+
if ov > 0:
153+
if method == 1: # linear
154+
if ov > Nt:
155+
weight = 1 - ov
156+
else:
157+
weight = 1
158+
elif method == 2: # gaussian
159+
weight = np.exp(-(ov * ov) / sigma)
160+
else: # original NMS
161+
if ov > Nt:
162+
weight = 0
163+
else:
164+
weight = 1
165+
166+
boxes[pos, 5] = weight * boxes[pos, 5]
167+
168+
# if box score falls below threshold, discard the box by swapping with last box
169+
# update N
170+
if boxes[pos, 5] < threshold:
171+
boxes[pos, 0] = boxes[N - 1, 0]
172+
boxes[pos, 1] = boxes[N - 1, 1]
173+
boxes[pos, 2] = boxes[N - 1, 2]
174+
boxes[pos, 3] = boxes[N - 1, 3]
175+
boxes[pos, 4] = boxes[N - 1, 4]
176+
boxes[pos, 5] = boxes[N - 1, 5]
177+
if is_scale:
178+
boxes[pos, 6] = boxes[N - 1, 6]
179+
N = N - 1
180+
pos = pos - 1
181+
pos = pos + 1
182+
keep = [i for i in range(N)]
183+
# boxes[:, 4] = (boxes[:, 4] / 180.0) + 0.5
184+
boxes[:, 4] = boxes[:, 4] / 180.0 * np.pi
185+
return boxes
186+
187+
def angle_soft_nms_new(all_dets, sigma=0.5, Nt=0.5, threshold=0.03, method=0, all_cls=False, cls_decay=1.5):
188+
"""Pure Python Soft-NMS baseline.
189+
author: Xingjia Pan
190+
date: 2019/11/4
191+
all_dets: cx,cy,w,h,angle,score for one row
192+
"""
193+
all_dets[:,4] = all_dets[:,4] / np.pi *180.0
194+
N = all_dets.shape[0]
195+
for i in range(N):
196+
order = np.argsort(-all_dets[:, 5])
197+
all_dets = all_dets[order, :]
198+
## calc distance of center point
199+
if i == N-1:
200+
continue
201+
dist_score = np.linalg.norm(all_dets[i,:2]-all_dets[i+1:, :2],axis=1)
202+
min_side = np.min(all_dets[i,2:4])+1e-8
203+
div_factor = 1./10 if min_side>96 else 1./7
204+
dist_score = dist_score/(div_factor * min_side)
205+
dist_score = np.clip(dist_score, 0.0, 1.0)
206+
dist_score = dist_score**2
207+
box1 = (c_double * 5)()
208+
box1[0] = c_double(all_dets[i, 0])
209+
box1[1] = c_double(all_dets[i, 1])
210+
box1[2] = c_double(all_dets[i, 2])
211+
box1[3] = c_double(all_dets[i, 3])
212+
box1[4] = c_double(all_dets[i, 4])
213+
j = i + 1
214+
# NMS iterations, note that N changes if detection boxes fall below threshold
215+
while j < N:
216+
box2 = (c_double * 5)()
217+
box2[0] = c_double(all_dets[j, 0])
218+
box2[1] = c_double(all_dets[j, 1])
219+
box2[2] = c_double(all_dets[j, 2])
220+
box2[3] = c_double(all_dets[j, 3])
221+
box2[4] = c_double(all_dets[j, 4])
222+
ov = overlap(box1, box2)
223+
weight = 1.0
224+
if ov > 0:
225+
if method == 1: # linear
226+
if ov > Nt:
227+
weight = 1 - ov
228+
else:
229+
weight = 1
230+
elif method == 2: # gaussian
231+
weight = np.exp(-(ov * ov) / sigma)
232+
else: # original NMS
233+
if ov > Nt:
234+
weight = 0
235+
else:
236+
weight = 1
237+
if all_cls:
238+
if all_dets[i,6] != all_dets[j, 6]:
239+
dist_score[j-i-1] *= cls_decay
240+
dist_score[j-i-1] = np.minimum(dist_score[j-i-1], 1.0)
241+
weight *= dist_score[j-i-1]
242+
all_dets[j, 5] = weight * all_dets[j, 5]
243+
j = j + 1
244+
keep = all_dets[:,5] > threshold
245+
all_dets[:, 4] = all_dets[:, 4] / 180.0 * np.pi
246+
return all_dets[keep,:]
247+
248+
249+
def py_yt_nms(dets, thresh):
250+
x1 = dets[:, 0]
251+
y1 = dets[:, 1]
252+
253+
x2 = dets[:, 2]
254+
y2 = dets[:, 3]
255+
scores = dets[:, 4]
256+
angle = 180.0 * (dets[:, 5] - 0.5)
257+
258+
# sort by confidence
259+
order = scores.argsort()[::-1]
260+
261+
# list of keep box
262+
keep = []
263+
while order.size > 0:
264+
i = order[0]
265+
keep.append(i)
266+
267+
cur_box = [x1[i], y1[i], x2[i], y2[i], angle[i]]
268+
other_boxes = []
269+
for each_box in range(1, len(order)):
270+
each_other_box = [x1[order[each_box]], y1[order[each_box]], x2[order[each_box]], y2[order[each_box]],angle[order[each_box]]]
271+
other_boxes.append(each_other_box)
272+
iou_result_list = []
273+
box1 = (c_double * 5)()
274+
box2 = (c_double * 5)()
275+
box1[0] = c_double(cur_box[0])
276+
box1[1] = c_double(cur_box[1])
277+
box1[2] = c_double(cur_box[2])
278+
box1[3] = c_double(cur_box[3])
279+
box1[4] = c_double(cur_box[4])
280+
# call for cpp nms function
281+
for each_gt_box in other_boxes:
282+
box2[0] = c_double(each_gt_box[0])
283+
box2[1] = c_double(each_gt_box[1])
284+
box2[2] = c_double(each_gt_box[2])
285+
box2[3] = c_double(each_gt_box[3])
286+
box2[4] = c_double(each_gt_box[4])
287+
288+
# get return iou result
289+
each_iou = overlap(box1, box2)
290+
iou_result_list.append(each_iou)
291+
292+
ovr = iou_result_list
293+
ovr = np.array(ovr)
294+
295+
inds = np.where(ovr <= thresh)[0]
296+
order = order[inds + 1]
297+
298+
return keep
299+
300+
301+
if __name__ == '__main__':
302+
a = np.array([(0, 0, 30 / 1000, 10 / 1000, .9, 0),
303+
(0, 0, 30 / 1000, 10 / 1000, .98, 0.25)]) # , (-5, -5, 5, 5, .98, 45), (-5, -5, 6, 6, .99, 30)])
304+
# print(py_cpu_nms(a, 0.45))
305+
# print(py_poly_nms(a, 0.45))
306+
# print(Polygon(a).area)

0 commit comments

Comments
 (0)