13.4.1生成多个锚框
参考: 13.4.1生成多个锚框.
代码实现
import torch
import matplotlib.pyplot as plt
torch.set_printoptions(precision=2)
def multibox_prior(feature_map, sizes, ratios):
"""生成以每个像素为中心具有不同形状的锚框。"""
in_height, in_width = feature_map.shape[-2:]
device = feature_map.device
size_tensor = torch.tensor(sizes, device=device)
ratio_tensor = torch.tensor(ratios, device=device)
offset_h, offset_w = 0.5, 0.5
steps_h = 1.0 / in_height
steps_w = 1.0 / in_width
center_h = (torch.arange(in_height, device=device) + offset_h) * steps_h
center_w = (torch.arange(in_width, device=device) + offset_w) * steps_w
shift_y, shift_x = torch.meshgrid(center_h, center_w)
shift_y, shift_x = shift_y.reshape(-1), shift_x.reshape(-1)
anc_w = torch.cat((size_tensor * torch.sqrt(ratio_tensor[0]),
sizes[0] * torch.sqrt(ratio_tensor[1:])))
anc_h = torch.cat((size_tensor / torch.sqrt(ratio_tensor[0]),
sizes[0] / torch.sqrt(ratio_tensor[1:])))
anchor_manipulations = torch.stack([-anc_w, -anc_h, anc_w, anc_h], axis=1) / 2
out_grid = torch.stack([shift_x, shift_y, shift_x, shift_y],dim=1)
anchors = out_grid.reshape((-1, 1, 4)) + anchor_manipulations.reshape((1, -1, 4))
return anchors.reshape(1,-1,4)
img = plt.imread('../img/catdog.jpg')
h, w = img.shape[:2]
X = torch.rand(size=(1, 3, h, w))
Y = multibox_prior(X, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5])
print("Y.shape",Y.shape)
boxes = Y.reshape(h, w, 5, 4)
print(boxes.shape)
res = boxes[250, 250, 0, :]
print("第一个锚框坐标",res)
res_w = res[3] - res[1]
res_h = res[2] - res[0]
print(res_w == res_h)
13.4.2交并比
def box_iou(boxes1, boxes2):
"""计算两个锚框或边界框列表中成对的交并比。"""
box_area = lambda boxes: ((boxes[:, 2] - boxes[:, 0]) *
(boxes[:, 3] - boxes[:, 1]))
areas1 = box_area(boxes1)
areas2 = box_area(boxes2)
inter_upperlefts = torch.max(boxes1[:, None, :2], boxes2[:, :2])
inter_lowerrights = torch.min(boxes1[:, None, 2:], boxes2[:, 2:])
inters = (inter_lowerrights - inter_upperlefts).clamp(min=0)
inter_areas = inters[:, :, 0] * inters[:, :, 1]
union_areas = areas1[:, None] + areas2 - inter_areas
return inter_areas / union_areas
- 测试
box1 = torch.tensor([100,100,200,200]).unsqueeze(0)
box2 = torch.tensor([120,120,220,220]).unsqueeze(0)
iou = box_iou(box1,box2)
print("交并比为:",iou)
- 计算结果
13.4.3标注训练数据的锚框
- 算法原理
- 代码实现
def assign_anchor_to_bbox(ground_truth, anchors, device, iou_threshold=0.5):
"""将最接近的真实边界框分配给锚框。"""
num_anchors, num_gt_boxes = anchors.shape[0], ground_truth.shape[0]
jaccard = box_iou(anchors, ground_truth)
"""
tensor([[0.0536, 0.0000],
[0.1417, 0.0000],
[0.0000, 0.5657],
[0.0000, 0.2059],
[0.0000, 0.7459]])
"""
anchors_bbox_map = torch.full((num_anchors,), -1, dtype=torch.long,device=device)
jaccard_cp = jaccard.clone()
col_discard = torch.full((num_anchors,), -1)
row_discard = torch.full((num_gt_boxes,), -1)
for _ in range(num_gt_boxes):
max_idx = torch.argmax(jaccard_cp)
box_idx = (max_idx % num_gt_boxes).long()
anc_idx = (max_idx / num_gt_boxes).long()
anchors_bbox_map[anc_idx] = box_idx
jaccard_cp[:, box_idx] = col_discard
jaccard_cp[anc_idx, :] = row_discard
for i in range(num_anchors):
if anchors_bbox_map[i] == -1:
j = torch.argmax(jaccard[i, :])
if jaccard[i, j] >= iou_threshold:
anchors_bbox_map[i] = j
return anchors_bbox_map
- 算法理解
- 代码测试
ground_truth = torch.tensor([[0, 0.1, 0.08, 0.52, 0.92],
[1, 0.55, 0.2, 0.9, 0.88]])
anchors = torch.tensor([[0, 0.1, 0.2, 0.3], [0.15, 0.2, 0.4, 0.4],
[0.63, 0.05, 0.88, 0.98], [0.66, 0.45, 0.8, 0.8],
[0.57, 0.3, 0.92, 0.9]])
device = torch.device("cuda")
res = assign_anchor_to_bbox(ground_truth[:,1:], anchors, device=device)
print("res:",res)
res: tensor([-1, 0, 1, -1, 1], device='cuda:0')
|