|
|
|
|
|
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) |
|
|