evaluation/tiny_benchmark/maskrcnn_benchmark/modeling/rpn/locnet/locnet.py (149 lines of code) (raw):

import torch import torch.nn.functional as F from torch import nn from .inference import make_location_postprocessor from .loss import make_location_loss_evaluator from .head import build_location_head class LocationGenerator(object): def __init__(self, fpn_strides): self.fpn_strides = fpn_strides def __call__(self, features): locations = [] for level, feature in enumerate(features): h, w = feature.size()[-2:] locations_per_level = self.compute_locations_per_level( h, w, self.fpn_strides[level], feature.device ) locations.append(locations_per_level) return locations def compute_locations_per_level(self, h, w, stride, device): shifts_x = torch.arange( 0, w * stride, step=stride, dtype=torch.float32, device=device ) shifts_y = torch.arange( 0, h * stride, step=stride, dtype=torch.float32, device=device ) shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x) shift_x = shift_x.reshape(-1) shift_y = shift_y.reshape(-1) locations = torch.stack((shift_x, shift_y), dim=1) + stride // 2 return locations class LOCModule(nn.Module): """ Module for FCOS computation. Takes feature maps from the backbone and FCOS outputs and losses. Only Test on FPN now. """ def __init__(self, cfg, in_channels): super(LOCModule, self).__init__() self.head = build_location_head(cfg, in_channels) self.anchor_generator = LocationGenerator(cfg.MODEL.LOC.FPN_STRIDES) # anchor or locations self.loss_evaluator = make_location_loss_evaluator(cfg) self.infer = make_location_postprocessor(cfg) self.debug_vis_labels = cfg.MODEL.LOC.DEBUG.VIS_LABELS def forward(self, images, features, targets=None): # preds: (box_cls, box_regression, centerness) for FCOS preds = self.head(features) # anchors for anchor-base, locations for anchor free anchors = self.anchor_generator(features) if self.debug_vis_labels: losses = self.loss_evaluator(anchors, *preds, targets) boxes = self.infer(anchors, *preds, images.image_sizes) show_image(images, targets, boxes) return boxes, {} else: if self.training: losses = self.loss_evaluator(anchors, *preds, targets) return None, losses else: boxes = self.infer(anchors, *preds, images.image_sizes) return boxes, {} def build_location_net(cfg, in_channels): return LOCModule(cfg, in_channels) import numpy as np class ResultShower(object): """ 1. plot image 2. plot list of bboxes, bboxes can be ground-truth or detection results 3. show score text for detection result 4. show detection location as red point, score as point size """ def __init__(self, image_mean=np.array([102.9801, 115.9465, 122.7717]), show_iter=1): self.score_th = None self.show_score_topk = 4 self.image_mean = image_mean self.point_size = 100 self.plot = self.plot2 self.show_iter = show_iter self.counter = 0 def __call__(self, images, *targets_list): import matplotlib.pyplot as plt import seaborn as sbn if (self.counter + 1) % self.show_iter != 0: self.counter += 1 return self.counter += 1 colors = sbn.color_palette(n_colors=len(targets_list)) img = images.tensors[0].permute((1, 2, 0)).cpu().numpy() + self.image_mean img = img[:, :, [2, 1, 0]] plt.imshow(img/255) title = "boxes:" for ci, targets in enumerate(targets_list): if targets is not None: bboxes = targets[0].bbox.detach().cpu().numpy().tolist() scores = targets[0].extra_fields['scores'].detach().cpu() if 'scores' in targets[0].extra_fields else None locations = targets[0].extra_fields['det_locations'].detach().cpu() if 'det_locations' in targets[0].extra_fields else None labels = targets[0].extra_fields['labels'].cpu() if scores is None or len(scores) == 0: self.plot1(bboxes, scores, locations, labels, None, (1, 0, 0)) # ground-truth else: score_th = -torch.kthvalue(-scores, self.show_score_topk)[0]\ if self.score_th is None else self.score_th self.plot(bboxes, scores, locations, labels, score_th, colors[ci]) count = len(targets[0].bbox) if scores is None else (scores > score_th).sum() title += "{}({}) ".format(count, len(targets[0].bbox)) plt.title(title) plt.show() input() def plot2(self, bboxes, scores, locations, labels, score_th, color=None): """ no dash line link box and location, use color link different color for different box, same color for same box and location """ import matplotlib.pyplot as plt import seaborn as sbn assert len(locations) == len(scores) if True: # sorted scores, idx = (-scores).sort() scores = -scores labels = labels[idx] locations = locations[idx] bboxes = np.array(bboxes)[idx.numpy()] colors = sbn.color_palette(n_colors=len(bboxes)) for i, (x1, y1, x2, y2) in enumerate(bboxes): w = x2 - x1 + 1 h = y2 - y1 + 1 color = colors[i] if scores is not None: if scores[i] >= score_th: plt.text(x1, y1, '{}:{:.2f}'.format(labels[i], scores[i]), color=(1, 0, 0)) rect = plt.Rectangle((x1, y1), w, h, fill=False, color=color, linewidth=1.5) plt.axes().add_patch(rect) if locations is not None: lx, ly = locations[i] plt.scatter(lx, ly, color=color, s=self.point_size*scores[i]) else: plt.text(x2, y2, '{}'.format(labels[i]), color=(1, 0, 0)) rect = plt.Rectangle((x1, y1), w, h, fill=False, color=color, linewidth=1.5) plt.axes().add_patch(rect) print(scores) print(labels) print(locations) print(bboxes) def plot1(self, bboxes, scores, locations, labels, score_th, color): """ , use dash line link bbox and location """ import matplotlib.pyplot as plt for i, (x1, y1, x2, y2) in enumerate(bboxes): w = x2 - x1 + 1 h = y2 - y1 + 1 if scores is not None: if scores[i] >= score_th: plt.text(x1, y1, '{:.2f}'.format(scores[i]), color=(1, 0, 0)) rect = plt.Rectangle((x1, y1), w, h, fill=False, color=color, linewidth=1.5) plt.axes().add_patch(rect) if locations is not None: lx, ly = locations[i] plt.plot([lx, lx, lx], [y2, ly, y1], '--', color=color) plt.plot([x2, lx, x1], [ly, ly, ly], '--', color=color) if locations is not None: lx, ly = locations[i] plt.scatter(lx, ly, color='r', s=self.point_size * scores[i]) else: rect = plt.Rectangle((x1, y1), w, h, fill=False, color=color, linewidth=1.5) plt.axes().add_patch(rect) show_image = ResultShower()