forked from louis-she/sfd.pytorch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanchor.py
95 lines (71 loc) · 3.3 KB
/
anchor.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
import numpy as np
from utils import change_coordinate_inv
def anchors_of_feature_map(stride, size, feature_map_shape):
anchors = []
height, width = feature_map_shape
for row in range(height):
center_y = row * stride + size // 2
for col in range(width):
center_x = col * stride + size // 2
anchors.append( (center_x, center_y, size, size) )
return anchors
def generate_anchors(anchor_stride, anchor_size, image_size):
all_anchors = []
for i in range(len(anchor_stride)):
anchors = []
stride = anchor_stride[i]
size = anchor_size[i]
for row in range(image_size[0] // stride):
center_y = row * stride + stride // 2
for col in range(image_size[1] // stride):
center_x = col * stride + stride // 2
width = size
height = size
anchors.append(( center_x, center_y, width, height))
all_anchors.append(anchors)
return all_anchors
def mark_anchors(anchors, gt_boxes, positive_threshold=0.3,
negative_threshold=0.1, least_pos_num=50):
"""IoU larger than positive_threshold is positive anchors,
less than negative_threshold is negative anchors. (Obviousely, this
comment is trash talk...)
"""
iou = compute_iou(anchors, gt_boxes)
max_iou = iou.max(axis=1)
positive_anchor_indices = np.where(max_iou > positive_threshold)[0]
negative_anchor_indices = np.where(max_iou < negative_threshold)[0]
# positive anchors should get coorsponding gt_boxes for computing deltas
positive_iou = iou[positive_anchor_indices]
matched_gt_box_indices = positive_iou.argmax(axis=1)
# if matched anchors is not enough(less than least_pos_num),
# do the sort and pick top least_pos_num trick.
if len(matched_gt_box_indices) < least_pos_num:
# anyway, 0.2 is the bottom line
allowed_positive_anchor_indices = np.where(max_iou > 0.2)[0]
top_n_sorted_indices = np.argsort(max_iou)[::-1][:least_pos_num]
# get the intersect of the 2 array
positive_anchor_indices = np.intersect1d(
allowed_positive_anchor_indices,
top_n_sorted_indices
)
positive_iou = iou[positive_anchor_indices]
matched_gt_box_indices = positive_iou.argmax(axis=1)
return positive_anchor_indices, matched_gt_box_indices, negative_anchor_indices
def compute_iou(anchors, gt_boxes):
"""compute IoU for 2 bounding boxes arrays, return size is:
[anchors.shape[0], gt_boxes[0]]
"""
len_anchors = anchors.shape[0]
len_gt_boxes = gt_boxes.shape[0]
anchors = np.repeat(anchors, len_gt_boxes, axis=0)
gt_boxes = np.vstack([gt_boxes] * len_anchors)
y1 = np.maximum(anchors[:, 0], gt_boxes[:, 0])
x1 = np.maximum(anchors[:, 1], gt_boxes[:, 1])
y2 = np.minimum(anchors[:, 2], gt_boxes[:, 2])
x2 = np.minimum(anchors[:, 3], gt_boxes[:, 3])
y_zeros = np.zeros_like(y2.shape)
x_zeros = np.zeros_like(x2.shape)
intersect = np.maximum((y2 - y1), y_zeros) * np.maximum((x2 - x1), x_zeros)
unit = (anchors[:, 2] - anchors[:, 0]) * (anchors[:, 3] - anchors[:, 1]) + \
(gt_boxes[:, 2] - gt_boxes[:, 0]) * (gt_boxes[:, 3] - gt_boxes[:, 1]) - intersect
return (intersect / unit).reshape(len_anchors, len_gt_boxes)