[LAB 09 · 检测几何:框、匹配、NMS 与 AP](/course/notebooks/90d213b4e1e04c7e889ee6fc042b2358.html) # 2 · 训练分配和评价匹配解决两个问题 · 实现代码 [独立阅读](/course/notebook-blocks/ef7e83a286ba4b14912267d87243dc13.html) 并入相关学习路径 固定框匹配、PR/AP、NMS误删相邻对象反例 展开完整实现代码 ``` def assign_training_anchors(anchors, gt_boxes, positive_iou=0.50): """D2L-style target assignment: threshold positives + forced GT coverage. One anchor has at most one GT, but several anchors may target the same GT. Returns GT index per anchor (-1 means background in this simplified lab). Scores and predicted classes are intentionally absent from the inputs. """ if not 0 <= positive_iou <= 1: raise ValueError("positive_iou must be in [0,1]") ious = box_iou(anchors, gt_boxes) n_anchor, n_gt = ious.shape assigned = np.full(n_anchor, -1, dtype=int) forced = np.zeros(n_anchor, dtype=bool) if n_gt == 0: return assigned, forced if n_anchor < n_gt: raise ValueError("Forced GT coverage requires anchors >= GTs") best_gt = ious.argmax(axis=1) best_iou = ious[np.arange(n_anchor), best_gt] positive = best_iou >= positive_iou assigned[positive] = best_gt[positive] remaining = ious.copy() for _ in range(n_gt): anchor_i, gt_i = np.unravel_index(np.argmax(remaining), remaining.shape) assigned[anchor_i] = gt_i forced[anchor_i] = True remaining[anchor_i, :] = -1.0 remaining[:, gt_i] = -1.0 return assigned, forced print("0-based GT targets (-1=background):", assign_training_anchors(PRED, GT)[0]) ```