| |
|
|
| |
|
|
| from typing import Any |
| import torch |
| from torch.nn import functional as F |
|
|
| from detectron2.structures import BitMasks, Boxes, BoxMode |
|
|
| from .base import IntTupleBox, make_int_box |
| from .to_mask import ImageSizeType |
|
|
|
|
| def resample_coarse_segm_tensor_to_bbox(coarse_segm: torch.Tensor, box_xywh_abs: IntTupleBox): |
| """ |
| Resample coarse segmentation tensor to the given |
| bounding box and derive labels for each pixel of the bounding box |
| |
| Args: |
| coarse_segm: float tensor of shape [1, K, Hout, Wout] |
| box_xywh_abs (tuple of 4 int): bounding box given by its upper-left |
| corner coordinates, width (W) and height (H) |
| Return: |
| Labels for each pixel of the bounding box, a long tensor of size [1, H, W] |
| """ |
| x, y, w, h = box_xywh_abs |
| w = max(int(w), 1) |
| h = max(int(h), 1) |
| labels = F.interpolate(coarse_segm, (h, w), mode="bilinear", align_corners=False).argmax(dim=1) |
| return labels |
|
|
|
|
| def resample_fine_and_coarse_segm_tensors_to_bbox( |
| fine_segm: torch.Tensor, coarse_segm: torch.Tensor, box_xywh_abs: IntTupleBox |
| ): |
| """ |
| Resample fine and coarse segmentation tensors to the given |
| bounding box and derive labels for each pixel of the bounding box |
| |
| Args: |
| fine_segm: float tensor of shape [1, C, Hout, Wout] |
| coarse_segm: float tensor of shape [1, K, Hout, Wout] |
| box_xywh_abs (tuple of 4 int): bounding box given by its upper-left |
| corner coordinates, width (W) and height (H) |
| Return: |
| Labels for each pixel of the bounding box, a long tensor of size [1, H, W] |
| """ |
| x, y, w, h = box_xywh_abs |
| w = max(int(w), 1) |
| h = max(int(h), 1) |
| |
| coarse_segm_bbox = F.interpolate( |
| coarse_segm, |
| (h, w), |
| mode="bilinear", |
| align_corners=False, |
| ).argmax(dim=1) |
| |
| labels = ( |
| F.interpolate(fine_segm, (h, w), mode="bilinear", align_corners=False).argmax(dim=1) |
| * (coarse_segm_bbox > 0).long() |
| ) |
| return labels |
|
|
|
|
| def resample_fine_and_coarse_segm_to_bbox(predictor_output: Any, box_xywh_abs: IntTupleBox): |
| """ |
| Resample fine and coarse segmentation outputs from a predictor to the given |
| bounding box and derive labels for each pixel of the bounding box |
| |
| Args: |
| predictor_output: DensePose predictor output that contains segmentation |
| results to be resampled |
| box_xywh_abs (tuple of 4 int): bounding box given by its upper-left |
| corner coordinates, width (W) and height (H) |
| Return: |
| Labels for each pixel of the bounding box, a long tensor of size [1, H, W] |
| """ |
| return resample_fine_and_coarse_segm_tensors_to_bbox( |
| predictor_output.fine_segm, |
| predictor_output.coarse_segm, |
| box_xywh_abs, |
| ) |
|
|
|
|
| def predictor_output_with_coarse_segm_to_mask( |
| predictor_output: Any, boxes: Boxes, image_size_hw: ImageSizeType |
| ) -> BitMasks: |
| """ |
| Convert predictor output with coarse and fine segmentation to a mask. |
| Assumes that predictor output has the following attributes: |
| - coarse_segm (tensor of size [N, D, H, W]): coarse segmentation |
| unnormalized scores for N instances; D is the number of coarse |
| segmentation labels, H and W is the resolution of the estimate |
| |
| Args: |
| predictor_output: DensePose predictor output to be converted to mask |
| boxes (Boxes): bounding boxes that correspond to the DensePose |
| predictor outputs |
| image_size_hw (tuple [int, int]): image height Himg and width Wimg |
| Return: |
| BitMasks that contain a bool tensor of size [N, Himg, Wimg] with |
| a mask of the size of the image for each instance |
| """ |
| H, W = image_size_hw |
| boxes_xyxy_abs = boxes.tensor.clone() |
| boxes_xywh_abs = BoxMode.convert(boxes_xyxy_abs, BoxMode.XYXY_ABS, BoxMode.XYWH_ABS) |
| N = len(boxes_xywh_abs) |
| masks = torch.zeros((N, H, W), dtype=torch.bool, device=boxes.tensor.device) |
| for i in range(len(boxes_xywh_abs)): |
| box_xywh = make_int_box(boxes_xywh_abs[i]) |
| box_mask = resample_coarse_segm_tensor_to_bbox(predictor_output[i].coarse_segm, box_xywh) |
| x, y, w, h = box_xywh |
| masks[i, y : y + h, x : x + w] = box_mask |
|
|
| return BitMasks(masks) |
|
|
|
|
| def predictor_output_with_fine_and_coarse_segm_to_mask( |
| predictor_output: Any, boxes: Boxes, image_size_hw: ImageSizeType |
| ) -> BitMasks: |
| """ |
| Convert predictor output with coarse and fine segmentation to a mask. |
| Assumes that predictor output has the following attributes: |
| - coarse_segm (tensor of size [N, D, H, W]): coarse segmentation |
| unnormalized scores for N instances; D is the number of coarse |
| segmentation labels, H and W is the resolution of the estimate |
| - fine_segm (tensor of size [N, C, H, W]): fine segmentation |
| unnormalized scores for N instances; C is the number of fine |
| segmentation labels, H and W is the resolution of the estimate |
| |
| Args: |
| predictor_output: DensePose predictor output to be converted to mask |
| boxes (Boxes): bounding boxes that correspond to the DensePose |
| predictor outputs |
| image_size_hw (tuple [int, int]): image height Himg and width Wimg |
| Return: |
| BitMasks that contain a bool tensor of size [N, Himg, Wimg] with |
| a mask of the size of the image for each instance |
| """ |
| H, W = image_size_hw |
| boxes_xyxy_abs = boxes.tensor.clone() |
| boxes_xywh_abs = BoxMode.convert(boxes_xyxy_abs, BoxMode.XYXY_ABS, BoxMode.XYWH_ABS) |
| N = len(boxes_xywh_abs) |
| masks = torch.zeros((N, H, W), dtype=torch.bool, device=boxes.tensor.device) |
| for i in range(len(boxes_xywh_abs)): |
| box_xywh = make_int_box(boxes_xywh_abs[i]) |
| labels_i = resample_fine_and_coarse_segm_to_bbox(predictor_output[i], box_xywh) |
| x, y, w, h = box_xywh |
| masks[i, y : y + h, x : x + w] = labels_i > 0 |
| return BitMasks(masks) |
|
|