[LAB 10 · 从 RGB 图像训练小型检测器](/course/notebooks/a14237bfa9dd413d959ab4e458e11f42.html) # 哪些锚框受哪一种监督 · 实现代码 [独立阅读](/course/notebook-blocks/b6e5552805db40308895eb423c00fff1.html) 主线阅读与优先实验 RGB图像、单特征层锚框检测器、分类/位置损失、NMS、独立检测评价 展开完整实现代码 ``` %%writefile -a lab10_detector.py def anchors_grid(grid=12,sizes=(.23,.37)): boxes=[] for y in range(grid): for x in range(grid): for s in sizes:boxes.append([(x+.5)/grid-s/2,(y+.5)/grid-s/2,(x+.5)/grid+s/2,(y+.5)/grid+s/2]) return torch.tensor(boxes) def encode(anchors,boxes): ac=(anchors[:,:2]+anchors[:,2:])/2;aw=anchors[:,2:]-anchors[:,:2] bc=(boxes[:,:2]+boxes[:,2:])/2;bw=boxes[:,2:]-boxes[:,:2] return torch.cat([(bc-ac)/aw,torch.log((bw/aw).clamp(min=1e-6))],1) def decode(anchors,offset): ac=(anchors[:,:2]+anchors[:,2:])/2;aw=anchors[:,2:]-anchors[:,:2] bc=ac+offset[:,:2]*aw;bw=aw*torch.exp(offset[:,2:].clamp(-3,3)) return torch.cat([bc-bw/2,bc+bw/2],1).clamp(0,1) def match_targets(anchors,target): """-1 ignore, 0 background, 1/2 object. Each GT gets a distinct forced anchor.""" classes=torch.zeros(len(anchors),dtype=torch.long);offsets=torch.zeros_like(anchors) if not len(target['boxes']): return classes,offsets overlap=iou_matrix(anchors,target['boxes']);best,best_gt=overlap.max(1) classes[(best>=.25)&(best<.45)]=-1 positive=best>=.45 # Greedy global maximum, invalidate its anchor and GT; guarantees all GT assigned. work=overlap.clone() for _ in range(len(target['boxes'])): flat=int(work.argmax()); a=flat//work.shape[1];g=flat%work.shape[1] positive[a]=True;best_gt[a]=g;work[a,:]=-1;work[:,g]=-1 classes[positive]=target['labels'][best_gt[positive]] offsets[positive]=encode(anchors[positive],target['boxes'][best_gt[positive]]) return classes,offsets ```