|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import absolute_import |
|
from __future__ import division |
|
from __future__ import print_function |
|
|
|
import numpy as np |
|
|
|
import logging |
|
|
|
import torch |
|
import torch.nn as nn |
|
from pdb import set_trace as st |
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
class HeatmapGenerator(): |
|
def __init__(self, heatmap_size, num_joints=68, sigma=2): |
|
self.heatmap_size = heatmap_size |
|
|
|
self.num_joints = num_joints |
|
if sigma < 0: |
|
sigma = self.heatmap_size / 64 |
|
self.sigma = sigma |
|
size = 6 * sigma + 3 |
|
x = np.arange(0, size, 1, float) |
|
y = x[:, np.newaxis] |
|
x0, y0 = 3 * sigma + 1, 3 * sigma + 1 |
|
self.g = np.exp(-((x - x0)**2 + (y - y0)**2) / (2 * sigma**2)) |
|
|
|
|
|
def __call__(self, joints, image_size: int): |
|
"""generate heatmap gt from joints |
|
|
|
Args: |
|
joints (np.ndarray): N,3 |
|
|
|
Returns: |
|
hms: N,H,W |
|
""" |
|
hms = np.zeros((self.num_joints, self.heatmap_size, self.heatmap_size), |
|
dtype=np.float32) |
|
sigma = self.sigma |
|
|
|
|
|
feat_stride = image_size / self.heatmap_size |
|
for idx, pt in enumerate(joints): |
|
|
|
if pt[2] > 0: |
|
|
|
|
|
x = int(pt[0] / feat_stride + 0.5) |
|
y = int(pt[1] / feat_stride + |
|
0.5) |
|
if x < 0 or y < 0 or \ |
|
x >= self.heatmap_size or y >= self.heatmap_size: |
|
continue |
|
|
|
ul = int(np.round(x - 3 * sigma - 1)), int( |
|
np.round(y - 3 * sigma - 1)) |
|
br = int(np.round(x + 3 * sigma + 2)), int( |
|
np.round(y + 3 * sigma + 2)) |
|
|
|
c, d = max(0, -ul[0]), min(br[0], self.heatmap_size) - ul[0] |
|
a, b = max(0, -ul[1]), min(br[1], self.heatmap_size) - ul[1] |
|
|
|
cc, dd = max(0, ul[0]), min(br[0], self.heatmap_size) |
|
aa, bb = max(0, ul[1]), min(br[1], self.heatmap_size) |
|
hms[idx, aa:bb, cc:dd] = np.maximum(hms[idx, aa:bb, cc:dd], |
|
self.g[a:b, c:d]) |
|
return hms |
|
|
|
|
|
class HeatmapLoss(nn.Module): |
|
def __init__(self): |
|
super().__init__() |
|
|
|
def forward(self, pred, gt, mask=None): |
|
|
|
assert pred.size() == gt.size() |
|
loss = ((pred - gt)**2) |
|
if mask is not None: |
|
loss = loss * mask[:, None, :, :].expand_as(pred) |
|
|
|
loss = loss.mean() |
|
|
|
return loss |
|
|