-
Notifications
You must be signed in to change notification settings - Fork 38
/
BoxProposing.py
executable file
·130 lines (120 loc) · 5.76 KB
/
BoxProposing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import numpy as np
import random
class BoxProposalModule(object):
def __init__(self, *args, **kwargs):
self.MinimapRatio = kwargs.get('MinimapRatio', 2) # we down-sample the normal boundary map to save computation cost
self.min_box_size = kwargs.get('min_box_size', 64) // self.MinimapRatio
self.min_aspect_ratio = kwargs.get('min_aspect_ratio', 0.3)
self.max_aspect_ratio = kwargs.get('max_aspect_ratio', 10.)
self.anchor_x_step = kwargs.get('anchor_x_step', 12) // self.MinimapRatio
self.anchor_y_step = kwargs.get('anchor_y_step', 12) // self.MinimapRatio
self.SafeGap = kwargs.get('SafeGap', 2) // self.MinimapRatio # shrink the proposals so that they wont get too close to the boundaries
self.overlap_threshold = kwargs.get('overlap_threshold', 1) # threshold for overlap with boundaries in normal maps
def BoxFitting(self, normal_boundary_map, box_x, box_y):
"""
Given the center point and normal boundary map
:param normal_boundary_map: ndarray, HxW, 0/1
:param box_x: int
:param box_y: int
:return: UL_x, UL_y, BR_x, BR_y
"""
h, w = normal_boundary_map.shape
x_left_min = 0
x_left_max = box_x - self.min_box_size // 2
x_right_min = box_x + self.min_box_size // 2
x_right_max = w
y_down_min = 0
y_down_max = box_y - self.min_box_size // 4
y_up_min = box_y + self.min_box_size // 4
y_up_max = h
# if already crossing boundary or outside
if (x_left_max < 0) or \
(x_right_min >= w) or \
(y_down_max < 0) or \
(y_up_min >= h) or \
(np.sum(normal_boundary_map[y_down_max:y_up_min, x_left_max:x_right_min]) > self.overlap_threshold):
return -1
enlargeable_flag = True
enlargement_count = 0
direction = [1, 2, 3, 4] # right, left, down, up
while enlargeable_flag:
random.shuffle(direction)
enlargeable_flag = False
for d in direction:
if d == 4: # up
if y_up_max-y_up_min < 2: continue
mid = (y_up_min+y_up_max) // 2
if np.sum(normal_boundary_map[y_down_max:mid,
x_left_max:x_right_min]) > self.overlap_threshold:
y_up_max = mid
else:
y_up_min = mid
enlargeable_flag = True
break
elif d == 3: # down
if y_down_max-y_down_min < 2: continue
mid = (y_down_max+y_down_min) // 2
if np.sum(normal_boundary_map[mid:y_up_min,
x_left_max:x_right_min]) > self.overlap_threshold:
y_down_min = mid
else:
y_down_max = mid
enlargeable_flag = True
break
elif d == 2: # left
if x_left_max-x_left_min < 2: continue
mid = (x_left_max+x_left_min) // 2
if np.sum(normal_boundary_map[y_down_max:y_up_min,
mid:x_right_min]) > self.overlap_threshold:
x_left_min = mid
else:
x_left_max = mid
enlargeable_flag = True
break
elif d == 1: # right
if x_right_max-x_right_min < 2: continue
mid = (x_right_max+x_right_min) // 2
if np.sum(normal_boundary_map[y_down_max:y_up_min,
x_left_max:mid]) > self.overlap_threshold:
x_right_max = mid
else:
x_right_min = mid
enlargeable_flag = True
break
if enlargeable_flag:
enlargement_count += 1
if enlargement_count >= 15:
if random.random() < 0.2: break
return x_left_max+self.SafeGap, y_down_max+self.SafeGap, x_right_min-self.SafeGap, y_up_min-self.SafeGap
def BoxProposing(self, normal_boundary_map, proposalnumber):
"""
normal_boundary_map: ndarray, HxW 0/1, binary maps
proposalnumber: how many proposals to return
"""
H, W = normal_boundary_map.shape
Proposals = []
hs = [h for h in range(random.randint(0, self.anchor_y_step // self.MinimapRatio), H, self.anchor_y_step // self.MinimapRatio)]
random.shuffle(hs)
ws = [w for w in range(random.randint(0, self.anchor_x_step // self.MinimapRatio), W, self.anchor_x_step // self.MinimapRatio)]
random.shuffle(ws)
# random visits
for h in hs[:]:
for w in ws[:]:
result = self.BoxFitting(normal_boundary_map, w, h)
# filter out failed proposals
if result == -1:
continue
UL_x, UL_y, BR_x, BR_y = result
normal_boundary_map[UL_y:BR_y, UL_x: BR_x] = 1
center_x = (UL_x + BR_x) / 2
center_y = (UL_y + BR_y) / 2
result = [center_x - self.min_box_size / 2,
center_y - self.min_box_size / 2,
center_x + self.min_box_size / 2,
center_y + self.min_box_size / 2]
Proposals.append(np.array(result, dtype=np.int)*self.MinimapRatio)
if len(Proposals) >= proposalnumber * 4:
random.shuffle(Proposals)
return Proposals[:proposalnumber]
random.shuffle(Proposals)
return Proposals[:proposalnumber]