| import time |
| import torch |
| import torch.nn.functional as F |
| import numpy as np |
|
|
|
|
| def get_gaussian_kernel_1d(kernel_size, sigma, device): |
| x = torch.arange(kernel_size).float() - (kernel_size // 2) |
| g = torch.exp(-((x**2) / (2 * sigma**2))) |
| g /= g.sum() |
|
|
| kernel_weight = g.view(1, 1, -1).to(device) |
|
|
| return kernel_weight |
|
|
|
|
| def gaussian_filter_1d(data, kernel_size=3, sigma=1.0, weight=None): |
| kernel_weight = ( |
| get_gaussian_kernel_1d(kernel_size, sigma, data.device) |
| if weight is None |
| else weight |
| ) |
| data = F.pad(data, (kernel_size // 2, kernel_size // 2), mode="replicate") |
| return F.conv1d(data, kernel_weight) |
|
|
|
|
| def exponential_smoothing(x, d_x, alpha=0.5): |
| return d_x + alpha * (x - d_x) |
|
|
|
|
| class OneEuroFilter: |
| |
| |
| |
| def __init__( |
| self, min_cutoff=1.0, beta=0.0, sampling_rate=30, d_cutoff=1.0, device="cuda" |
| ): |
| self.min_cutoff = min_cutoff |
| self.beta = beta |
| self.sampling_rate = sampling_rate |
| self.x_prev = None |
| self.dx_prev = None |
| self.d_cutoff = d_cutoff |
| self.pi = torch.tensor(torch.pi, device=device) |
|
|
| def smoothing_factor(self, cutoff): |
|
|
| r = 2 * self.pi * cutoff / self.sampling_rate |
| return r / (1 + r) |
|
|
| def filter(self, x): |
| if self.x_prev is None: |
| self.x_prev = x |
| self.dx_prev = torch.zeros_like(x) |
| return x |
|
|
| a_d = self.smoothing_factor(self.d_cutoff) |
| |
| dx = (x - self.x_prev) * self.sampling_rate |
|
|
| dx_hat = exponential_smoothing(dx, self.dx_prev, a_d) |
|
|
| cutoff = self.min_cutoff + self.beta * torch.abs(dx_hat) |
| a = self.smoothing_factor(cutoff) |
|
|
| x_hat = exponential_smoothing(x, self.x_prev, a) |
|
|
| self.x_prev = x_hat |
| self.dx_prev = dx_hat |
|
|
| return x_hat |
|
|
|
|
| class Filter: |
| filter_factory = { |
| "gaussian": get_gaussian_kernel_1d, |
| } |
|
|
| def __init__(self, target_data, filter_type, filter_args): |
| self.target_data = target_data |
| self.filter = self.filter_factory[filter_type] |
| self.filter_args = filter_args |
|
|
| def process(self, network_outputs): |
| filter_data = [] |
| for human in network_outputs: |
| filter_data.append(human[self.target_data]) |
| filter_data = torch.stack(filter_data, dim=0) |
|
|
| filter_data = self.filter(filter_data, **self.filter_args) |
|
|
| for i, human in enumerate(network_outputs): |
| human[self.target_data] = filter_data[i] |
|
|
|
|
| if __name__ == "__main__": |
| import argparse |
| import matplotlib.pyplot as plt |
| import numpy as np |
| from rot6d import rotation_6d_to_axis_angle, axis_angle_to_rotation_6d |
|
|
| from humans import get_smplx_joint_names |
|
|
| parser = argparse.ArgumentParser() |
| parser.add_argument("--data_path", type=str) |
| parser.add_argument("--save_path", type=str) |
| parser.add_argument("--name", type=str) |
| args = parser.parse_args() |
|
|
| fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(10, 8)) |
| data_types = ["rotvec"] |
| observe_keypoints = ["pelvis", "head", "left_wrist", "left_knee"] |
| joint_names = get_smplx_joint_names() |
|
|
| data = np.load(f"{args.data_path}/shape_{args.name}.npy") |
| fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(10, 8)) |
| for i in range(2): |
| for j in range(2): |
| x = data[:, i * 4 + j * 2] |
| print(x.shape) |
| axs[i, j].plot(x) |
|
|
| axs[i, j].set_title(f"{4 * i + 2 * j}") |
| axs[i, j].plot(np.load(f"{args.data_path}/dist_{args.name}.npy")) |
| plt.tight_layout() |
| plt.savefig(f"{args.save_path}/shape_{args.name}.jpg") |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
|
|