| |
|
|
| from typing import Dict |
| import torch |
| from torch.nn import functional as F |
|
|
| from detectron2.structures.boxes import Boxes, BoxMode |
|
|
| from ..structures import ( |
| DensePoseChartPredictorOutput, |
| DensePoseChartResult, |
| DensePoseChartResultWithConfidences, |
| ) |
| from . import resample_fine_and_coarse_segm_to_bbox |
| from .base import IntTupleBox, make_int_box |
|
|
|
|
| def resample_uv_tensors_to_bbox( |
| u: torch.Tensor, |
| v: torch.Tensor, |
| labels: torch.Tensor, |
| box_xywh_abs: IntTupleBox, |
| ) -> torch.Tensor: |
| """ |
| Resamples U and V coordinate estimates for the given bounding box |
| |
| Args: |
| u (tensor [1, C, H, W] of float): U coordinates |
| v (tensor [1, C, H, W] of float): V coordinates |
| labels (tensor [H, W] of long): labels obtained by resampling segmentation |
| outputs for the given bounding box |
| box_xywh_abs (tuple of 4 int): bounding box that corresponds to predictor outputs |
| Return: |
| Resampled U and V coordinates - a tensor [2, H, W] of float |
| """ |
| x, y, w, h = box_xywh_abs |
| w = max(int(w), 1) |
| h = max(int(h), 1) |
| u_bbox = F.interpolate(u, (h, w), mode="bilinear", align_corners=False) |
| v_bbox = F.interpolate(v, (h, w), mode="bilinear", align_corners=False) |
| uv = torch.zeros([2, h, w], dtype=torch.float32, device=u.device) |
| for part_id in range(1, u_bbox.size(1)): |
| uv[0][labels == part_id] = u_bbox[0, part_id][labels == part_id] |
| uv[1][labels == part_id] = v_bbox[0, part_id][labels == part_id] |
| return uv |
|
|
|
|
| def resample_uv_to_bbox( |
| predictor_output: DensePoseChartPredictorOutput, |
| labels: torch.Tensor, |
| box_xywh_abs: IntTupleBox, |
| ) -> torch.Tensor: |
| """ |
| Resamples U and V coordinate estimates for the given bounding box |
| |
| Args: |
| predictor_output (DensePoseChartPredictorOutput): DensePose predictor |
| output to be resampled |
| labels (tensor [H, W] of long): labels obtained by resampling segmentation |
| outputs for the given bounding box |
| box_xywh_abs (tuple of 4 int): bounding box that corresponds to predictor outputs |
| Return: |
| Resampled U and V coordinates - a tensor [2, H, W] of float |
| """ |
| return resample_uv_tensors_to_bbox( |
| predictor_output.u, |
| predictor_output.v, |
| labels, |
| box_xywh_abs, |
| ) |
|
|
|
|
| def densepose_chart_predictor_output_to_result( |
| predictor_output: DensePoseChartPredictorOutput, boxes: Boxes |
| ) -> DensePoseChartResult: |
| """ |
| Convert densepose chart predictor outputs to results |
| |
| Args: |
| predictor_output (DensePoseChartPredictorOutput): DensePose predictor |
| output to be converted to results, must contain only 1 output |
| boxes (Boxes): bounding box that corresponds to the predictor output, |
| must contain only 1 bounding box |
| Return: |
| DensePose chart-based result (DensePoseChartResult) |
| """ |
| assert len(predictor_output) == 1 and len(boxes) == 1, ( |
| f"Predictor output to result conversion can operate only single outputs" |
| f", got {len(predictor_output)} predictor outputs and {len(boxes)} boxes" |
| ) |
|
|
| boxes_xyxy_abs = boxes.tensor.clone() |
| boxes_xywh_abs = BoxMode.convert(boxes_xyxy_abs, BoxMode.XYXY_ABS, BoxMode.XYWH_ABS) |
| box_xywh = make_int_box(boxes_xywh_abs[0]) |
|
|
| labels = resample_fine_and_coarse_segm_to_bbox(predictor_output, box_xywh).squeeze(0) |
| uv = resample_uv_to_bbox(predictor_output, labels, box_xywh) |
| return DensePoseChartResult(labels=labels, uv=uv) |
|
|
|
|
| def resample_confidences_to_bbox( |
| predictor_output: DensePoseChartPredictorOutput, |
| labels: torch.Tensor, |
| box_xywh_abs: IntTupleBox, |
| ) -> Dict[str, torch.Tensor]: |
| """ |
| Resamples confidences for the given bounding box |
| |
| Args: |
| predictor_output (DensePoseChartPredictorOutput): DensePose predictor |
| output to be resampled |
| labels (tensor [H, W] of long): labels obtained by resampling segmentation |
| outputs for the given bounding box |
| box_xywh_abs (tuple of 4 int): bounding box that corresponds to predictor outputs |
| Return: |
| Resampled confidences - a dict of [H, W] tensors of float |
| """ |
|
|
| x, y, w, h = box_xywh_abs |
| w = max(int(w), 1) |
| h = max(int(h), 1) |
|
|
| confidence_names = [ |
| "sigma_1", |
| "sigma_2", |
| "kappa_u", |
| "kappa_v", |
| "fine_segm_confidence", |
| "coarse_segm_confidence", |
| ] |
| confidence_results = {key: None for key in confidence_names} |
| confidence_names = [ |
| key for key in confidence_names if getattr(predictor_output, key) is not None |
| ] |
| confidence_base = torch.zeros([h, w], dtype=torch.float32, device=predictor_output.u.device) |
|
|
| |
| for key in confidence_names: |
| resampled_confidence = F.interpolate( |
| getattr(predictor_output, key), |
| (h, w), |
| mode="bilinear", |
| align_corners=False, |
| ) |
| result = confidence_base.clone() |
| for part_id in range(1, predictor_output.u.size(1)): |
| if resampled_confidence.size(1) != predictor_output.u.size(1): |
| |
| continue |
| result[labels == part_id] = resampled_confidence[0, part_id][labels == part_id] |
|
|
| if resampled_confidence.size(1) != predictor_output.u.size(1): |
| |
| |
| result = resampled_confidence[0, 0] |
|
|
| confidence_results[key] = result |
|
|
| return confidence_results |
|
|
|
|
| def densepose_chart_predictor_output_to_result_with_confidences( |
| predictor_output: DensePoseChartPredictorOutput, boxes: Boxes |
| ) -> DensePoseChartResultWithConfidences: |
| """ |
| Convert densepose chart predictor outputs to results |
| |
| Args: |
| predictor_output (DensePoseChartPredictorOutput): DensePose predictor |
| output with confidences to be converted to results, must contain only 1 output |
| boxes (Boxes): bounding box that corresponds to the predictor output, |
| must contain only 1 bounding box |
| Return: |
| DensePose chart-based result with confidences (DensePoseChartResultWithConfidences) |
| """ |
| assert len(predictor_output) == 1 and len(boxes) == 1, ( |
| f"Predictor output to result conversion can operate only single outputs" |
| f", got {len(predictor_output)} predictor outputs and {len(boxes)} boxes" |
| ) |
|
|
| boxes_xyxy_abs = boxes.tensor.clone() |
| boxes_xywh_abs = BoxMode.convert(boxes_xyxy_abs, BoxMode.XYXY_ABS, BoxMode.XYWH_ABS) |
| box_xywh = make_int_box(boxes_xywh_abs[0]) |
|
|
| labels = resample_fine_and_coarse_segm_to_bbox(predictor_output, box_xywh).squeeze(0) |
| uv = resample_uv_to_bbox(predictor_output, labels, box_xywh) |
| confidences = resample_confidences_to_bbox(predictor_output, labels, box_xywh) |
| return DensePoseChartResultWithConfidences(labels=labels, uv=uv, **confidences) |
|
|