This function computes the panoptic prediction from the model's predictions. Parameters: outputs: This is a dict coming directly from the model. See the model doc for the content. processed_sizes: This is a list of tuples (or torch tensors) of sizes of the images
(self, outputs, processed_sizes, target_sizes=None)
| 252 | self.is_thing_map = is_thing_map |
| 253 | |
| 254 | def forward(self, outputs, processed_sizes, target_sizes=None): |
| 255 | """ This function computes the panoptic prediction from the model's predictions. |
| 256 | Parameters: |
| 257 | outputs: This is a dict coming directly from the model. See the model doc for the content. |
| 258 | processed_sizes: This is a list of tuples (or torch tensors) of sizes of the images that were passed to the |
| 259 | model, ie the size after data augmentation but before batching. |
| 260 | target_sizes: This is a list of tuples (or torch tensors) corresponding to the requested final size |
| 261 | of each prediction. If left to None, it will default to the processed_sizes |
| 262 | """ |
| 263 | if target_sizes is None: |
| 264 | target_sizes = processed_sizes |
| 265 | assert len(processed_sizes) == len(target_sizes) |
| 266 | out_logits, raw_masks, raw_boxes = outputs["pred_logits"], outputs["pred_masks"], outputs["pred_boxes"] |
| 267 | assert len(out_logits) == len(raw_masks) == len(target_sizes) |
| 268 | preds = [] |
| 269 | |
| 270 | def to_tuple(tup): |
| 271 | if isinstance(tup, tuple): |
| 272 | return tup |
| 273 | return tuple(tup.cpu().tolist()) |
| 274 | |
| 275 | for cur_logits, cur_masks, cur_boxes, size, target_size in zip( |
| 276 | out_logits, raw_masks, raw_boxes, processed_sizes, target_sizes |
| 277 | ): |
| 278 | # we filter empty queries and detection below threshold |
| 279 | scores, labels = cur_logits.softmax(-1).max(-1) |
| 280 | keep = labels.ne(outputs["pred_logits"].shape[-1] - 1) & (scores > self.threshold) |
| 281 | cur_scores, cur_classes = cur_logits.softmax(-1).max(-1) |
| 282 | cur_scores = cur_scores[keep] |
| 283 | cur_classes = cur_classes[keep] |
| 284 | cur_masks = cur_masks[keep] |
| 285 | cur_masks = interpolate(cur_masks[None], to_tuple(size), mode="bilinear").squeeze(0) |
| 286 | cur_boxes = box_ops.box_cxcywh_to_xyxy(cur_boxes[keep]) |
| 287 | |
| 288 | h, w = cur_masks.shape[-2:] |
| 289 | assert len(cur_boxes) == len(cur_classes) |
| 290 | |
| 291 | # It may be that we have several predicted masks for the same stuff class. |
| 292 | # In the following, we track the list of masks ids for each stuff class (they are merged later on) |
| 293 | cur_masks = cur_masks.flatten(1) |
| 294 | stuff_equiv_classes = defaultdict(lambda: []) |
| 295 | for k, label in enumerate(cur_classes): |
| 296 | if not self.is_thing_map[label.item()]: |
| 297 | stuff_equiv_classes[label.item()].append(k) |
| 298 | |
| 299 | def get_ids_area(masks, scores, dedup=False): |
| 300 | # This helper function creates the final panoptic segmentation image |
| 301 | # It also returns the area of the masks that appears on the image |
| 302 | |
| 303 | m_id = masks.transpose(0, 1).softmax(-1) |
| 304 | |
| 305 | if m_id.shape[-1] == 0: |
| 306 | # We didn't detect any mask :( |
| 307 | m_id = torch.zeros((h, w), dtype=torch.long, device=m_id.device) |
| 308 | else: |
| 309 | m_id = m_id.argmax(-1).view(h, w) |
| 310 | |
| 311 | if dedup: |
nothing calls this directly
no test coverage detected