Compare commits
5
Commits
db1a1b8307
...
dc2bc318a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc2bc318a7 | ||
|
|
2d78839f69 | ||
|
|
745d18a324 | ||
|
|
cac382ef19 | ||
|
|
05341fd48f |
+3
-1
@@ -164,4 +164,6 @@ cython_debug/
|
|||||||
temp/
|
temp/
|
||||||
dataset/
|
dataset/
|
||||||
wandb_login.py
|
wandb_login.py
|
||||||
custom_data/dijsktra.npy
|
custom_data/dijsktra*
|
||||||
|
|
||||||
|
*.out
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+30
-2
@@ -30,7 +30,9 @@ from pytorch3d.structures import Meshes
|
|||||||
class PoseRenderer(Module):
|
class PoseRenderer(Module):
|
||||||
def __init__(self, device='cuda') -> None:
|
def __init__(self, device='cuda') -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
colors = np.load('custom_data/pose_colors.npy')
|
# colors = np.load('custom_data/pose_colors.npy')
|
||||||
|
colors = np.load('custom_data/body_colors_interpolated_unweighted.npy')
|
||||||
|
|
||||||
self.textures = TexturesVertex(verts_features=torch.from_numpy(colors).to(device)[None, :, :])
|
self.textures = TexturesVertex(verts_features=torch.from_numpy(colors).to(device)[None, :, :])
|
||||||
self.cam = torch.tensor([3.0, 0.0, 0.0], device=device).cpu().numpy()
|
self.cam = torch.tensor([3.0, 0.0, 0.0], device=device).cpu().numpy()
|
||||||
|
|
||||||
@@ -52,4 +54,30 @@ class PoseRenderer(Module):
|
|||||||
|
|
||||||
output = renderer(Meshes(verts[None,:,:], faces[None,:,:], textures=self.textures))
|
output = renderer(Meshes(verts[None,:,:], faces[None,:,:], textures=self.textures))
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
|
||||||
|
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
|
||||||
|
from superSMPL.smpl_torch import SMPL
|
||||||
|
import plotly.express as ex
|
||||||
|
renderer = PoseRenderer()
|
||||||
|
smpl = SMPL(path='superSMPL', device='cuda')
|
||||||
|
pose = torch.rand(72, dtype=torch.float32, device='cuda')
|
||||||
|
pose[:3] = 0
|
||||||
|
shape = torch.rand(11, dtype=torch.float32, device='cuda')
|
||||||
|
# pose_out[1] = 0.5 # np.random.uniform(-np.pi, np.pi)
|
||||||
|
# generate random number between -np.pi, np.pi
|
||||||
|
|
||||||
|
# start = time()
|
||||||
|
|
||||||
|
body = smpl(pose.unsqueeze(0), shape.unsqueeze(0), remove=False)
|
||||||
|
body_to_render = body[0,:,[0,2,1]]
|
||||||
|
# and rotate it 90 degress along the z axis
|
||||||
|
body_to_render = torch.matmul(torch.tensor([[0,1,0],[-1,0,0],[0,0,1]], dtype=torch.float32, device=body_to_render.device), body_to_render.T).T
|
||||||
|
|
||||||
|
out = renderer(body_to_render, torch.from_numpy(smpl.f_all).to(body_to_render.get_device()))
|
||||||
|
|
||||||
|
ex.imshow(out[0, ..., :3].cpu().numpy()).show()
|
||||||
|
|
||||||
|
print(out)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
|
||||||
|
|
||||||
|
# os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
|
||||||
|
# os.environ["CUDA_VISIBLE_DEVICES"] = '3'
|
||||||
|
|
||||||
|
import torch
|
||||||
|
from torch.utils.data import Dataset
|
||||||
|
import numpy as np
|
||||||
|
from tqdm import tqdm
|
||||||
|
from time import time
|
||||||
|
from cloth3d.read import DataReader
|
||||||
|
from utils.data_utils import Frame, read_frames_file, mask_faces, get_normals_from_depth, get_camera, filter_info, resize_image
|
||||||
|
from superSMPL.smpl_torch import SMPL
|
||||||
|
from data.pose_renderer import PoseRenderer
|
||||||
|
|
||||||
|
|
||||||
|
class Dataset(Dataset):
|
||||||
|
def __init__(self, device='cuda'):
|
||||||
|
self.device = device
|
||||||
|
self.smpl = SMPL(path='superSMPL', device=device)
|
||||||
|
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return int(1e6)
|
||||||
|
|
||||||
|
|
||||||
|
def __getitem__(self, idx):
|
||||||
|
# generate a random tenssor of size 3 with values betweeen -pi and pi
|
||||||
|
angles = torch.rand(3) * 2 * np.pi - np.pi
|
||||||
|
angles = angles.to(self.device)
|
||||||
|
matrix = self.smpl.rodrigues(angles[None, None, :]).to(self.device)[0]
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'angles': angles,
|
||||||
|
'matrix': matrix,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from torch.utils.data import DataLoader
|
||||||
|
|
||||||
|
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||||
|
dataset = Dataset(device=device)
|
||||||
|
train_dataloader = DataLoader(dataset, batch_size=4, drop_last=True, shuffle=False)
|
||||||
|
|
||||||
|
for batch in train_dataloader:
|
||||||
|
batch
|
||||||
|
pass
|
||||||
|
|
||||||
|
pass
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# Use an existing image as the base
|
# Use an existing image as the base
|
||||||
# FROM nvcr.io/nvidia/pytorch:23.04-py3
|
# FROM nvcr.io/nvidia/pytorch:23.04-py3
|
||||||
FROM pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
|
FROM pytorch/pytorch:2.0.1-cuda11.7-cudnn8-devel
|
||||||
# FROM pytorch/pytorch:1.12.0-cuda11.3-cudnn8-devel
|
# FROM pytorch/pytorch:1.12.0-cuda11.3-cudnn8-devel
|
||||||
|
|
||||||
# Add the current user to the image
|
# Add the current user to the image
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ services:
|
|||||||
- capabilities: [gpu]
|
- capabilities: [gpu]
|
||||||
|
|
||||||
lhunor_torch_3:
|
lhunor_torch_3:
|
||||||
image: lhunor_reconstruction:v2.0
|
image: lhunor_reconstruction:v2.0.1
|
||||||
container_name: lhunor_reconstruction_v2.0
|
container_name: lhunor_reconstruction_v2.0.1
|
||||||
ipc: host
|
ipc: host
|
||||||
tty: true
|
tty: true
|
||||||
ulimits:
|
ulimits:
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ class ConvNeXtReverseMaskPose(nn.Module):
|
|||||||
if norm_layer is None:
|
if norm_layer is None:
|
||||||
norm_layer = partial(LayerNorm2d, eps=1e-6)
|
norm_layer = partial(LayerNorm2d, eps=1e-6)
|
||||||
|
|
||||||
|
stage: List[nn.Module] = []
|
||||||
|
for _ in range(3):
|
||||||
|
stage.append(block(block_setting[0].input_channels, layer_scale, 0))
|
||||||
|
self.stage_smooth = nn.Sequential(*stage).to(device)
|
||||||
|
|
||||||
self.first = nn.Sequential(
|
self.first = nn.Sequential(
|
||||||
nn.ConvTranspose2d(block_setting[0].input_channels, block_setting[0].out_channels, kernel_size=2, stride=2),
|
nn.ConvTranspose2d(block_setting[0].input_channels, block_setting[0].out_channels, kernel_size=2, stride=2),
|
||||||
norm_layer(block_setting[0].out_channels),
|
norm_layer(block_setting[0].out_channels),
|
||||||
@@ -111,7 +116,8 @@ class ConvNeXtReverseMaskPose(nn.Module):
|
|||||||
input, features = x
|
input, features = x
|
||||||
else:
|
else:
|
||||||
input = x
|
input = x
|
||||||
x = self.first(input)
|
x = self.stage_smooth(input)
|
||||||
|
x = self.first(x)
|
||||||
f = self.layers(x)
|
f = self.layers(x)
|
||||||
x = self.stage_pose(f)
|
x = self.stage_pose(f)
|
||||||
pose = torch.sigmoid(self.last(x))
|
pose = torch.sigmoid(self.last(x))
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
|
||||||
|
# os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
|
||||||
|
|
||||||
|
import torch
|
||||||
|
import numpy as np
|
||||||
|
from torch import nn, Tensor
|
||||||
|
from torch.nn import functional as F
|
||||||
|
from functools import partial
|
||||||
|
from typing import Any, Callable, List, Optional, Sequence
|
||||||
|
|
||||||
|
torch.set_float32_matmul_precision('high')
|
||||||
|
|
||||||
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ViewEncoder(nn.Module):
|
||||||
|
def __init__(self, bottleneck_size):
|
||||||
|
super(ViewEncoder, self).__init__()
|
||||||
|
self.bottleneck_size = bottleneck_size
|
||||||
|
|
||||||
|
# Encoder
|
||||||
|
self.encoder = nn.Sequential(
|
||||||
|
nn.Linear(3*3, 64),
|
||||||
|
nn.ReLU(),
|
||||||
|
nn.Linear(64, 128),
|
||||||
|
nn.ReLU(),
|
||||||
|
nn.Linear(128, 256),
|
||||||
|
nn.ReLU(),
|
||||||
|
nn.Linear(256, 512),
|
||||||
|
nn.ReLU(),
|
||||||
|
nn.Linear(512, bottleneck_size),
|
||||||
|
nn.ReLU()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Decoder
|
||||||
|
self.decoder = nn.Sequential(
|
||||||
|
nn.Linear(bottleneck_size, 512),
|
||||||
|
nn.ReLU(),
|
||||||
|
nn.Linear(512, 256),
|
||||||
|
nn.ReLU(),
|
||||||
|
nn.Linear(256, 128),
|
||||||
|
nn.ReLU(),
|
||||||
|
nn.Linear(128, 64),
|
||||||
|
nn.ReLU(),
|
||||||
|
nn.Linear(64, 3*3),
|
||||||
|
nn.Tanh(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
# Encode
|
||||||
|
matrix = self.encoder(x.view(-1, 3*3))
|
||||||
|
|
||||||
|
# Decode
|
||||||
|
x = self.decoder(matrix)
|
||||||
|
x = x * np.pi
|
||||||
|
return x.view(-1, 3, 3), matrix
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# test the model
|
||||||
|
model = ViewEncoder(bottleneck_size=128).to('cuda')
|
||||||
|
# model = torch.compile(model)
|
||||||
|
print(model)
|
||||||
|
print(sum(p.numel() for p in model.parameters() if p.requires_grad))
|
||||||
|
print(sum(p.numel() for p in model.parameters()))
|
||||||
|
|
||||||
|
x = torch.rand((4, 3, 3)).to('cuda')
|
||||||
|
output = model(x)
|
||||||
|
|
||||||
|
# from torchviz import make_dot
|
||||||
|
# graph = make_dot(output, params=dict(model.named_parameters()))
|
||||||
|
# graph.render("model_graph", format="pdf")
|
||||||
|
|
||||||
|
pass
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
|
||||||
|
os.environ["CUDA_VISIBLE_DEVICES"] = '0' #config['gpu']
|
||||||
|
import torch
|
||||||
|
|
||||||
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser(description='')
|
||||||
|
parser.add_argument('--name', type=str)
|
||||||
|
parser.add_argument('--config', type=str)
|
||||||
|
parser.add_argument('--debug', action='store_true')
|
||||||
|
args = vars(parser.parse_args())
|
||||||
|
|
||||||
|
# config_module = importlib.import_module(args['config'])
|
||||||
|
# config = config_module.config
|
||||||
|
|
||||||
|
|
||||||
|
import wandb
|
||||||
|
import numpy as np
|
||||||
|
import torch.optim as optim
|
||||||
|
import torch.nn as nn
|
||||||
|
from torch.utils.data import DataLoader
|
||||||
|
# from torchgeometry.losses.dice import DiceLoss
|
||||||
|
# from torchmetrics import Dice
|
||||||
|
|
||||||
|
from data.view_dataset import Dataset
|
||||||
|
from utils.utils import Accumulator
|
||||||
|
from models.view_encoder import ViewEncoder
|
||||||
|
import plotly.express as ex
|
||||||
|
|
||||||
|
|
||||||
|
def init_wandb():
|
||||||
|
run = wandb.init(project='reconstruction', name='view_1', notes='', dir='/tmp', tags=['view'])
|
||||||
|
artifact = wandb.Artifact('code', type='code')
|
||||||
|
artifact.add_file('scripts/view_encoder_train.py')
|
||||||
|
artifact.add_file('models/view_encoder.py')
|
||||||
|
artifact.add_file('data/view_dataset.py')
|
||||||
|
config_file_names = [key for key in sys.modules.keys() if key.startswith('configs.')]
|
||||||
|
for config_file_name in config_file_names:
|
||||||
|
file_name = '/'.join(config_file_name.split('.')) + '.py'
|
||||||
|
if os.path.exists(file_name):
|
||||||
|
artifact.add_file(file_name)
|
||||||
|
run.log_artifact(artifact)
|
||||||
|
|
||||||
|
|
||||||
|
class OrthogonalLoss(nn.Module):
|
||||||
|
def __init__(self):
|
||||||
|
super(OrthogonalLoss, self).__init__()
|
||||||
|
|
||||||
|
def forward(self, tensor):
|
||||||
|
# Reshape the input tensor into a square matrix
|
||||||
|
matrix = tensor.view(-1, tensor.size(-1)//2, tensor.size(-1)//2)
|
||||||
|
# matrix = matrix / torch.norm(matrix, dim=1, keepdim=True) # Normalize the rows
|
||||||
|
|
||||||
|
# Compute the Gram matrix
|
||||||
|
gram_matrix = torch.matmul(matrix, matrix.t())
|
||||||
|
|
||||||
|
# Compute the Frobenius norm of the difference between the Gram matrix and the identity matrix
|
||||||
|
loss = torch.norm(gram_matrix - torch.eye(gram_matrix.size(0)).to(tensor.device))
|
||||||
|
|
||||||
|
return loss
|
||||||
|
|
||||||
|
|
||||||
|
def train_step(batch):
|
||||||
|
model.train()
|
||||||
|
|
||||||
|
pred, matrix = model(batch['matrix'])
|
||||||
|
|
||||||
|
mse = loss_fn(pred, batch['matrix'])
|
||||||
|
ortho_loss = ortho_loss_fn(matrix)
|
||||||
|
loss = mse + ortho_loss
|
||||||
|
|
||||||
|
# TODO: calculate max of ortho_loss
|
||||||
|
|
||||||
|
# print(f'Loss: {loss} MSE: {mse}')
|
||||||
|
|
||||||
|
optimizer.zero_grad()
|
||||||
|
loss.backward()
|
||||||
|
optimizer.step()
|
||||||
|
|
||||||
|
|
||||||
|
return { 'train/loss': loss, 'train/mse': mse, 'train/ortho_loss': ortho_loss }
|
||||||
|
|
||||||
|
|
||||||
|
def valid_step(batch):
|
||||||
|
model.eval()
|
||||||
|
with torch.inference_mode():
|
||||||
|
pred, matrix = model(batch['matrix'])
|
||||||
|
|
||||||
|
mse = loss_fn(pred, batch['matrix'])
|
||||||
|
ortho_loss = ortho_loss_fn(matrix)
|
||||||
|
loss = mse + ortho_loss
|
||||||
|
|
||||||
|
|
||||||
|
return { 'valid/loss': loss, 'valid/mse': mse }
|
||||||
|
|
||||||
|
|
||||||
|
def plot_everything(batch, type):
|
||||||
|
model.eval()
|
||||||
|
with torch.inference_mode():
|
||||||
|
pred = model(batch['matrix'])
|
||||||
|
|
||||||
|
matrix = batch['matrix'].cpu().numpy()
|
||||||
|
pred = pred.detach().cpu().numpy()
|
||||||
|
|
||||||
|
matrix_str = [np.array2string(matrix[i], precision=2, suppress_small=True) for i in range(4)]
|
||||||
|
pred_str = [np.array2string(pred[i], precision=2, suppress_small=True) for i in range(4)]
|
||||||
|
|
||||||
|
logs = { f'{type}/matrix': wandb.Table(data=[[matrix_str, pred_str]], columns=['matrix', 'pred']), }
|
||||||
|
|
||||||
|
return logs
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# wandb.login(host='https://wandb2.lnrweb.com', key='local-2a78b434e9bc51e9f12625f8321a9e3ee34af16d')
|
||||||
|
if not args['debug']:
|
||||||
|
init_wandb()
|
||||||
|
|
||||||
|
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||||
|
|
||||||
|
batch_size = 128
|
||||||
|
use_cache = False
|
||||||
|
|
||||||
|
train_dataset = Dataset(device=device)
|
||||||
|
valid_dataset = Dataset(device=device,)
|
||||||
|
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, drop_last=True, num_workers=0)
|
||||||
|
valid_dataloader = DataLoader(valid_dataset, batch_size=batch_size, drop_last=True, num_workers=0)
|
||||||
|
train_accumulator = Accumulator()
|
||||||
|
valid_accumulator = Accumulator()
|
||||||
|
|
||||||
|
model = ViewEncoder(bottleneck_size=1024).to(device)
|
||||||
|
|
||||||
|
loss_fn = nn.MSELoss()
|
||||||
|
ortho_loss_fn = OrthogonalLoss()
|
||||||
|
optimizer = optim.Adam(model.parameters(), lr=0.001)
|
||||||
|
# lr_scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.999, verbose=False)
|
||||||
|
# optimizer = optim.SGD(model.parameters(), lr=0.1)
|
||||||
|
|
||||||
|
iteration = 0
|
||||||
|
epoch = 0
|
||||||
|
while True:
|
||||||
|
|
||||||
|
for batch in train_dataloader:
|
||||||
|
train_loss = train_step(batch)
|
||||||
|
train_accumulator.update(train_loss)
|
||||||
|
|
||||||
|
if iteration % 1000 == 0 or (iteration < 1000 and iteration % 100 == 0):
|
||||||
|
to_log = dict({ **train_loss, **{ 'current_step': iteration } })
|
||||||
|
if iteration % 1000 == 0 or (iteration < 1000 and iteration % 1000 == 0):
|
||||||
|
train_figs = plot_everything(batch, 'train')
|
||||||
|
to_log = { **to_log, **train_figs }
|
||||||
|
# if iteration == 0:
|
||||||
|
# to_log = { **to_log, **{ 'model/summary': wandb.Html(get_summary_html(model)) } }
|
||||||
|
|
||||||
|
if not args['debug']:
|
||||||
|
wandb.log(to_log, step=iteration)
|
||||||
|
train_accumulator.reset()
|
||||||
|
iteration += 1
|
||||||
|
# print(f'Iteration {iteration} finished')
|
||||||
|
|
||||||
|
epoch += 1
|
||||||
|
print(f'Epoch {epoch} finished')
|
||||||
|
|
||||||
|
# if not iteration % 1000 == 0:
|
||||||
|
# continue
|
||||||
|
|
||||||
|
# for batch in valid_dataloader:
|
||||||
|
# valid_loss = valid_step(batch)
|
||||||
|
# valid_accumulator.update(valid_loss)
|
||||||
|
|
||||||
|
|
||||||
|
# to_log = dict({ **valid_loss, **{ 'current_step': iteration } })
|
||||||
|
# valid_figs = plot_everything(batch, 'train')
|
||||||
|
# to_log = { **to_log, **valid_figs }
|
||||||
|
# valid_accumulator.reset()
|
||||||
|
|
||||||
|
# if not args['debug']:
|
||||||
|
# wandb.log(to_log, step=iteration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pass
|
||||||
@@ -167,7 +167,9 @@ class SMPL(Module):
|
|||||||
v_shaped = torch.stack(v_shaped, axis=-1)
|
v_shaped = torch.stack(v_shaped, axis=-1)
|
||||||
|
|
||||||
# J = torch.matmul(self.J_regressor, v_shaped)
|
# J = torch.matmul(self.J_regressor, v_shaped)
|
||||||
J = torch.stack([torch.matmul(self.J_regressor[g.to(torch.long)], v_shaped[i, :, :, g.to(torch.long)]) for i, g in enumerate(betas[:,-1])])
|
J = torch.stack([torch.matmul(self.J_regressor[torch.greater(g, 0.5).to(torch.long)], v_shaped[i, :, :, torch.greater(g, 0.5).to(torch.long)]) for i, g in enumerate(betas[:,-1])])
|
||||||
|
J0 = torch.reshape(J[:,0,:], (-1, 1, 3))
|
||||||
|
J = J - J0
|
||||||
R_cube_big = self.rodrigues(pose.reshape(-1, 1, 3)).reshape(batch_num, -1, 3, 3)
|
R_cube_big = self.rodrigues(pose.reshape(-1, 1, 3)).reshape(batch_num, -1, 3, 3)
|
||||||
|
|
||||||
if verts is not None:
|
if verts is not None:
|
||||||
@@ -177,7 +179,7 @@ class SMPL(Module):
|
|||||||
I_cube = (torch.eye(3, dtype=torch.float32).unsqueeze(dim=0) + \
|
I_cube = (torch.eye(3, dtype=torch.float32).unsqueeze(dim=0) + \
|
||||||
torch.zeros((batch_num, R_cube.shape[1], 3, 3), dtype=torch.float32)).to(self.device)
|
torch.zeros((batch_num, R_cube.shape[1], 3, 3), dtype=torch.float32)).to(self.device)
|
||||||
lrotmin = (R_cube - I_cube).reshape(batch_num, -1, 1).squeeze(dim=2)
|
lrotmin = (R_cube - I_cube).reshape(batch_num, -1, 1).squeeze(dim=2)
|
||||||
v_posed = torch.stack([v_shaped[i, :, :, g.to(torch.long)] + torch.tensordot(lrotmin[i], self.posedirs[g.to(torch.long)], dims=([0], [2])) for i, g in enumerate(betas[:,-1])])
|
v_posed = torch.stack([v_shaped[i, :, :, torch.greater(g, 0.5).to(torch.long)] + torch.tensordot(lrotmin[i], self.posedirs[torch.greater(g, 0.5).to(torch.long)], dims=([0], [2])) for i, g in enumerate(betas[:,-1])])
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
results.append(
|
results.append(
|
||||||
@@ -211,7 +213,7 @@ class SMPL(Module):
|
|||||||
joints = torch.matmul(results, torch.transpose(torch.concat([J, torch.ones((J.shape[0], 24, 1), dtype=torch.float32, device=J.get_device())], axis=-1)[:,:,None,:],2,3))[:,:,:3,0]
|
joints = torch.matmul(results, torch.transpose(torch.concat([J, torch.ones((J.shape[0], 24, 1), dtype=torch.float32, device=J.get_device())], axis=-1)[:,:,None,:],2,3))[:,:,:3,0]
|
||||||
|
|
||||||
weights = self.weights if remove else self.weights_all
|
weights = self.weights if remove else self.weights_all
|
||||||
T = torch.stack([torch.tensordot(results[i], weights[g.to(torch.long)], dims=([0], [1])).permute(2, 0, 1) for i, g in enumerate(betas[:,-1])])
|
T = torch.stack([torch.tensordot(results[i], weights[torch.greater(g, 0.5).to(torch.long)], dims=([0], [1])).permute(2, 0, 1) for i, g in enumerate(betas[:,-1])])
|
||||||
rest_shape_h = torch.cat(
|
rest_shape_h = torch.cat(
|
||||||
(v_posed, torch.ones((batch_num, v_posed.shape[1], 1), dtype=torch.float32).to(self.device)), dim=2
|
(v_posed, torch.ones((batch_num, v_posed.shape[1], 1), dtype=torch.float32).to(self.device)), dim=2
|
||||||
)
|
)
|
||||||
|
|||||||
+277
-20
@@ -3,7 +3,7 @@ import sys
|
|||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
|
||||||
|
|
||||||
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
|
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
|
||||||
os.environ["CUDA_VISIBLE_DEVICES"] = '3'
|
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
|
||||||
# os.environ["CUDA_LAUNCH_BLOCKING"] = '1'
|
# os.environ["CUDA_LAUNCH_BLOCKING"] = '1'
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
@@ -11,7 +11,7 @@ from torch.nn import Module
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from superSMPL.smpl_torch import SMPL
|
from superSMPL.smpl_torch import SMPL
|
||||||
import trimesh
|
import trimesh
|
||||||
|
import time
|
||||||
import plotly.express as ex
|
import plotly.express as ex
|
||||||
import plotly.graph_objects as go
|
import plotly.graph_objects as go
|
||||||
|
|
||||||
@@ -78,11 +78,13 @@ def get_distances(vertices, edges):
|
|||||||
from scipy.sparse.csgraph import dijkstra
|
from scipy.sparse.csgraph import dijkstra
|
||||||
num_vertices = vertices.shape[0]
|
num_vertices = vertices.shape[0]
|
||||||
|
|
||||||
edge_lengths = np.linalg.norm(vertices[edges[:, 0]] - vertices[edges[:,1]], axis=-1)
|
# edge_lengths = np.linalg.norm(vertices[edges[:, 0]] - vertices[edges[:,1]], axis=-1)
|
||||||
|
edge_lengths = np.ones(edges.shape[0])
|
||||||
adjacency_matrix = csr_matrix((edge_lengths.flatten(), (edges[:, 0], edges[:, 1])), shape=(num_vertices, num_vertices))
|
adjacency_matrix = csr_matrix((edge_lengths.flatten(), (edges[:, 0], edges[:, 1])), shape=(num_vertices, num_vertices))
|
||||||
|
|
||||||
# Compute the distances between all vertices using Dijkstra's algorithm
|
# Compute the distances between all vertices using Dijkstra's algorithm
|
||||||
distances = dijkstra(adjacency_matrix, directed=False)
|
# distances = dijkstra(adjacency_matrix, directed=False)
|
||||||
|
distances = dijkstra(adjacency_matrix, directed=False, unweighted=True)
|
||||||
|
|
||||||
return distances
|
return distances
|
||||||
|
|
||||||
@@ -108,14 +110,147 @@ def get_distances2(vertices, faces):
|
|||||||
return distances
|
return distances
|
||||||
|
|
||||||
|
|
||||||
|
import networkx as nx
|
||||||
|
from scipy.spatial.distance import cdist
|
||||||
|
|
||||||
|
# def order_mesh_vertices(vertices, distances, edges):
|
||||||
|
# # Create a graph with vertices as nodes and distances as edge weights
|
||||||
|
# graph = nx.Graph()
|
||||||
|
# graph.add_nodes_from(range(len(vertices)))
|
||||||
|
# # calcualate the edge lengths
|
||||||
|
# edge_lengths = np.array([np.linalg.norm(vertices[edges[i, 0]] - vertices[edges[i, 1]]) for i in range(edges.shape[0])])
|
||||||
|
|
||||||
|
# # Add edges to the graph based on the mesh edges
|
||||||
|
# for edge, edge_length in zip(edges, edge_lengths):
|
||||||
|
# graph.add_edge(edge[0], edge[1], weight=edge_length)
|
||||||
|
|
||||||
|
# ordered_vertices = []
|
||||||
|
# ordered_indices = []
|
||||||
|
|
||||||
|
# start_vertex = 0
|
||||||
|
# # Perform breadth-first search starting from the selected vertex
|
||||||
|
# visited = set()
|
||||||
|
# queue = [(1221, 1221)] # Tuple of (vertex, index)
|
||||||
|
|
||||||
|
# while queue:
|
||||||
|
# vertex, index = queue.pop(0)
|
||||||
|
# if vertex not in visited:
|
||||||
|
# visited.add(vertex)
|
||||||
|
# ordered_vertices.append(vertices[vertex])
|
||||||
|
# ordered_indices.append(vertex)
|
||||||
|
# # neighbors = sorted(graph.neighbors(vertex), key=lambda n: graph.edges[vertex, n]['weight'])
|
||||||
|
# neighbors = graph.neighbors(vertex)
|
||||||
|
# queue.extend([(n, n) for n in neighbors])
|
||||||
|
|
||||||
|
# return np.array(ordered_vertices), np.array(ordered_indices)
|
||||||
|
|
||||||
|
from collections import deque
|
||||||
|
def order_mesh_vertices(vertices, distances, edges):
|
||||||
|
# Create a graph with vertices as nodes and distances as edge weights
|
||||||
|
graph = nx.Graph()
|
||||||
|
graph.add_nodes_from(range(len(vertices)))
|
||||||
|
|
||||||
|
# Calculate the edge lengths
|
||||||
|
edge_lengths = np.linalg.norm(vertices[edges[:, 0]] - vertices[edges[:, 1]], axis=1)
|
||||||
|
|
||||||
|
# Add edges to the graph based on the mesh edges
|
||||||
|
for edge, edge_length in zip(edges, edge_lengths):
|
||||||
|
graph.add_edge(edge[0], edge[1], weight=edge_length)
|
||||||
|
|
||||||
|
ordered_indices = []
|
||||||
|
|
||||||
|
start_vertex = 13833
|
||||||
|
# Perform breadth-first search starting from the selected vertex
|
||||||
|
visited = set()
|
||||||
|
queue = deque([start_vertex])
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
vertex = queue.popleft()
|
||||||
|
if vertex not in visited:
|
||||||
|
visited.add(vertex)
|
||||||
|
ordered_indices.append(vertex)
|
||||||
|
neighbors = sorted(graph.neighbors(vertex), key=lambda n: graph.edges[vertex, n]['weight'])
|
||||||
|
# neighbors = graph.neighbors(vertex)
|
||||||
|
queue.extend(neighbors)
|
||||||
|
|
||||||
|
return np.array(ordered_indices)
|
||||||
|
|
||||||
|
|
||||||
def interpolate_colors(distance_matrix, colored_indices, colored_colors):
|
def interpolate_colors(distance_matrix, colored_indices, colored_colors):
|
||||||
from scipy.spatial import distance
|
from scipy.spatial import distance, cKDTree
|
||||||
all_colors = np.array(np.meshgrid(np.arange(0,256), np.arange(0,256), np.arange(0,256))).T.reshape(-1,3)
|
all_colors = np.array(np.meshgrid(np.arange(0,256), np.arange(0,256), np.arange(0,256))).T.reshape(-1,3)
|
||||||
color_map = dict()
|
color_map = dict()
|
||||||
for idx, color in enumerate(all_colors):
|
for idx, color in enumerate(all_colors):
|
||||||
color_map[tuple(color)] = color
|
color_map[tuple(color)] = color
|
||||||
|
color_map_array = np.array(list(color_map.values()))
|
||||||
|
|
||||||
num_vertices = distance_matrix.shape[0]
|
num_vertices = distance_matrix.shape[0]
|
||||||
|
kd_tree = cKDTree(color_map_array)
|
||||||
|
|
||||||
|
# Create an array to store the interpolated colors
|
||||||
|
interpolated_colors = np.zeros((num_vertices, 3), dtype=np.uint8)
|
||||||
|
|
||||||
|
# Assign the given colors to the corresponding vertices
|
||||||
|
for index, color in zip(colored_indices, colored_colors):
|
||||||
|
interpolated_colors[index] = color
|
||||||
|
|
||||||
|
used_colors = set([tuple(color) for color in colored_colors])
|
||||||
|
|
||||||
|
# Interpolate colors for the remaining vertices
|
||||||
|
for vertex in range(num_vertices):
|
||||||
|
print(vertex)
|
||||||
|
if vertex not in colored_indices:
|
||||||
|
# start = time.time()
|
||||||
|
# Find the distances from the current vertex to the colored vertices
|
||||||
|
distances = distance_matrix[vertex, colored_indices]
|
||||||
|
# take the three closest one only
|
||||||
|
closest_indices = np.argsort(distances)[:3]
|
||||||
|
distances = distances[closest_indices]
|
||||||
|
# print(time.time() - start)
|
||||||
|
|
||||||
|
# Calculate the weights for color interpolation based on inverse distances
|
||||||
|
weights = 1.0 / distances
|
||||||
|
# Normalize the weights to sum up to 1
|
||||||
|
weights /= np.sum(weights)
|
||||||
|
# Interpolate the colors based on the weights
|
||||||
|
color = np.dot(weights, np.array(colored_colors)[closest_indices]).astype(np.uint8)
|
||||||
|
|
||||||
|
# get the closest color to this from color_map if this color is not available
|
||||||
|
if tuple(color) in used_colors:
|
||||||
|
start = time.time()
|
||||||
|
color_idx = kd_tree.query(color, workers=48)[1]
|
||||||
|
color = color_map_array[color_idx]
|
||||||
|
# if color is already in used_colors then get the next closest color until find one that is not in used_colors
|
||||||
|
k = 2
|
||||||
|
while tuple(color) in used_colors:
|
||||||
|
neighbour_dist, color_idx = kd_tree.query(color, k=k, workers=48)
|
||||||
|
color = color_map_array[color_idx[-1]]
|
||||||
|
k += 1
|
||||||
|
# assert neighbour_dist[-1] < 5
|
||||||
|
# color = color_map[min(color_map.keys(), key=lambda x: distance.euclidean(x, color))]
|
||||||
|
print(time.time() - start)
|
||||||
|
|
||||||
|
# start = time.time()
|
||||||
|
interpolated_colors[vertex] = color
|
||||||
|
used_colors.add(tuple(color))
|
||||||
|
# color_map.pop(tuple(color))
|
||||||
|
# color_map_array = np.delete(color_map_array, np.where(np.all(color_map_array == color, axis=1))[0], axis=0)
|
||||||
|
# np.delete(color_map_array, np.where , axis=0)
|
||||||
|
# print(time.time() - start)
|
||||||
|
|
||||||
|
return interpolated_colors
|
||||||
|
|
||||||
|
|
||||||
|
def interpolate_colors_2(distance_matrix, colored_indices, colored_colors):
|
||||||
|
from scipy.spatial import distance, cKDTree
|
||||||
|
all_colors = np.array(np.meshgrid(np.arange(0,256), np.arange(0,256), np.arange(0,256))).T.reshape(-1,3)
|
||||||
|
color_map = dict()
|
||||||
|
for idx, color in enumerate(all_colors):
|
||||||
|
color_map[tuple(color)] = color
|
||||||
|
color_map_array = np.array(list(color_map.values()))
|
||||||
|
|
||||||
|
num_vertices = distance_matrix.shape[0]
|
||||||
|
kd_tree = cKDTree(color_map_array)
|
||||||
|
|
||||||
# Create an array to store the interpolated colors
|
# Create an array to store the interpolated colors
|
||||||
interpolated_colors = np.zeros((num_vertices, 3), dtype=np.uint8)
|
interpolated_colors = np.zeros((num_vertices, 3), dtype=np.uint8)
|
||||||
@@ -126,6 +261,7 @@ def interpolate_colors(distance_matrix, colored_indices, colored_colors):
|
|||||||
|
|
||||||
# Interpolate colors for the remaining vertices
|
# Interpolate colors for the remaining vertices
|
||||||
for vertex in range(num_vertices):
|
for vertex in range(num_vertices):
|
||||||
|
print(vertex)
|
||||||
if vertex not in colored_indices:
|
if vertex not in colored_indices:
|
||||||
# Find the distances from the current vertex to the colored vertices
|
# Find the distances from the current vertex to the colored vertices
|
||||||
distances = distance_matrix[vertex, colored_indices]
|
distances = distance_matrix[vertex, colored_indices]
|
||||||
@@ -141,14 +277,83 @@ def interpolate_colors(distance_matrix, colored_indices, colored_colors):
|
|||||||
|
|
||||||
# get the closest color to this from color_map if this color is not available
|
# get the closest color to this from color_map if this color is not available
|
||||||
if tuple(color) not in color_map:
|
if tuple(color) not in color_map:
|
||||||
color = color_map[min(color_map.keys(), key=lambda x: distance.euclidean(x, color))]
|
kd_tree = cKDTree(color_map_array)
|
||||||
|
color_idx = kd_tree.query(color, workers=48)[1]
|
||||||
|
color = color_map_array[color_idx]
|
||||||
|
# color = color_map[min(color_map.keys(), key=lambda x: distance.euclidean(x, color))]
|
||||||
|
|
||||||
interpolated_colors[vertex] = color
|
interpolated_colors[vertex] = color
|
||||||
|
color_map.pop(tuple(color))
|
||||||
|
color_map_array = np.delete(color_map_array, np.where(np.all(color_map_array == color, axis=1))[0], axis=0)
|
||||||
|
# np.delete(color_map_array, np.where , axis=0)
|
||||||
|
|
||||||
return interpolated_colors
|
return interpolated_colors
|
||||||
|
|
||||||
|
|
||||||
|
def get_edges(faces):
|
||||||
|
edges = []
|
||||||
|
unique_edges = set()
|
||||||
|
|
||||||
|
# Iterate over each face
|
||||||
|
for face in faces:
|
||||||
|
# Get the vertices of the current face
|
||||||
|
v0, v1, v2 = face
|
||||||
|
|
||||||
|
# Define the three edges of the current face
|
||||||
|
# and add them to the unique_edges set
|
||||||
|
edge0 = tuple(sorted((v0, v1)))
|
||||||
|
edge1 = tuple(sorted((v1, v2)))
|
||||||
|
edge2 = tuple(sorted((v2, v0)))
|
||||||
|
|
||||||
|
unique_edges.add(edge0)
|
||||||
|
unique_edges.add(edge1)
|
||||||
|
unique_edges.add(edge2)
|
||||||
|
|
||||||
|
# Convert the unique_edges set to a list
|
||||||
|
edges = list(unique_edges)
|
||||||
|
|
||||||
|
# Convert the list of edges to a numpy array
|
||||||
|
edges = np.array(edges)
|
||||||
|
|
||||||
|
return edges
|
||||||
|
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
from plyfile import PlyData
|
||||||
|
# Read the .ply file
|
||||||
|
plydata = PlyData.read('custom_data/body_color_init.ply')
|
||||||
|
|
||||||
|
# Get the vertex coordinates
|
||||||
|
vertices = plydata['vertex']
|
||||||
|
coordinates = np.vstack((vertices['x'], vertices['y'], vertices['z'])).T
|
||||||
|
|
||||||
|
# Get the vertex colors
|
||||||
|
colors = np.vstack((vertices['red'], vertices['green'], vertices['blue'])).T
|
||||||
|
|
||||||
|
return coordinates, colors
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def find_corresponding_vertices(mesh1_vertices, mesh2_vertices, indices_mesh1):
|
||||||
|
corresponding_vertices_mesh2 = []
|
||||||
|
# mesh1_vertices[:, [1, 2]] = mesh1_vertices[:, [2, 1]]
|
||||||
|
for index_mesh1 in indices_mesh1:
|
||||||
|
vertex_mesh1 = mesh1_vertices[index_mesh1]
|
||||||
|
for i, vertex_mesh2 in enumerate(mesh2_vertices):
|
||||||
|
if np.allclose(vertex_mesh1, vertex_mesh2):
|
||||||
|
corresponding_vertices_mesh2.append(i)
|
||||||
|
break
|
||||||
|
return np.array(corresponding_vertices_mesh2)
|
||||||
|
|
||||||
|
def transform_selected_indices(selected_indices, new_order):
|
||||||
|
mapping = {old_idx: new_idx for new_idx, old_idx in enumerate(new_order)}
|
||||||
|
transformed_indices = np.array([mapping[idx] for idx in selected_indices])
|
||||||
|
return transformed_indices
|
||||||
|
|
||||||
|
def transform_faces(faces, new_order):
|
||||||
|
mapping = {old_idx: new_idx for new_idx, old_idx in enumerate(new_order)}
|
||||||
|
transformed_faces = np.array([[mapping[idx] for idx in face] for face in faces])
|
||||||
|
return transformed_faces
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
@@ -185,21 +390,69 @@ if __name__ == '__main__':
|
|||||||
continue
|
continue
|
||||||
colored_vertices[idx] = color
|
colored_vertices[idx] = color
|
||||||
|
|
||||||
# dist = get_distances(body, m.edges)
|
# create a 3d plotly scatter plot fo body vertices with vertex 26157 highlited and limits between -1 and 1
|
||||||
# # dist = compute_distances(body, faces)
|
# fig = go.Figure(data=[go.Scatter3d(x=body[:,0], y=body[:,1], z=body[:,2], mode='markers', marker=dict(color='blue', size=1))])
|
||||||
# np.save('custom_data/dijsktra.npy', dist)
|
# fig.add_trace(go.Scatter3d(x=[body[26157,0]], y=[body[26157,1]], z=[body[26157,2]], mode='markers', marker=dict(color='red', size=5)))
|
||||||
|
# fig.update_layout(scene=dict(xaxis=dict(range=[-1,1]), yaxis=dict(range=[-1,1]), zaxis=dict(range=[-1,1])))
|
||||||
|
# fig.show()
|
||||||
|
|
||||||
dist = np.load('custom_data/dijsktra.npy')
|
|
||||||
colors = interpolate_colors(dist, list(colored_vertices.keys()), list(colored_vertices.values()))
|
|
||||||
|
|
||||||
weights = dist[0,:]
|
|
||||||
# define a gradient rgb colors for body based on weights that is not just gray
|
|
||||||
colors = np.zeros((body.shape[0], 3))
|
# dist = get_distances(body, get_edges(faces))
|
||||||
colors[:,0] = weights
|
# # # dist = compute_distances(body, faces)
|
||||||
colors[:,1] = weights
|
# np.save('custom_data/dijsktra_int.npy', dist)
|
||||||
colors[:,2] = weights
|
|
||||||
colors = colors * 255
|
body_ply, colors_ply = get_data()
|
||||||
colors = colors.astype(np.uint8)
|
# rotate body_ply -90 degress along x axis
|
||||||
|
body_ply = body_ply[:,[0,2,1]]
|
||||||
|
# rotate body_ply 180 degress along y axis
|
||||||
|
body_ply[:,2] = -body_ply[:,2]
|
||||||
|
|
||||||
|
# colored_vertices.pop(13833)
|
||||||
|
# colored_vertices[1221] = np.array([0, 128, 0]).astype(np.uint8)
|
||||||
|
c = find_corresponding_vertices(body_ply, body, list(colored_vertices.keys()))
|
||||||
|
# c = np.delete(c, np.where(c == 180))
|
||||||
|
|
||||||
|
dist = np.load('custom_data/dijsktra2.npy')
|
||||||
|
ordered_indices = order_mesh_vertices(body, dist, get_edges(faces))
|
||||||
|
# reverse ordered_indices
|
||||||
|
# ordered_indices = ordered_indices[::-1]
|
||||||
|
|
||||||
|
c = transform_selected_indices(c, ordered_indices)
|
||||||
|
body = body[ordered_indices]
|
||||||
|
dist = dist[ordered_indices]
|
||||||
|
dist = dist[:,ordered_indices]
|
||||||
|
faces = transform_faces(faces, ordered_indices)
|
||||||
|
colors = interpolate_colors(dist, list(c), list(colored_vertices.values()))
|
||||||
|
np.save('custom_data/body_colors_interpolated_unweighted.npy', colors)
|
||||||
|
|
||||||
|
#c = [14110, 3192, 25113, 10822, 27513, 25872]
|
||||||
|
# generate a gradient grayscale colors for the vertice based ont heir indices
|
||||||
|
# colors = np.zeros((body.shape[0], 3))
|
||||||
|
# colors[:,0] = np.arange(body.shape[0]) / body.shape[0]
|
||||||
|
# colors[:,1] = np.arange(body.shape[0]) / body.shape[0]
|
||||||
|
# colors[:,2] = np.arange(body.shape[0]) / body.shape[0]
|
||||||
|
# colors = colors * 255
|
||||||
|
# colors = colors.astype(np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
# weights = dist[0,:]
|
||||||
|
# # define a gradient rgb colors for body based on weights that is not just gray
|
||||||
|
# colors = np.zeros((body.shape[0], 3))
|
||||||
|
# colors[:,0] = weights
|
||||||
|
# colors[:,1] = weights
|
||||||
|
# colors[:,2] = weights
|
||||||
|
# colors = colors * 255
|
||||||
|
# colors = colors.astype(np.uint8)
|
||||||
|
|
||||||
|
# # define a gradient rgb colors for body based on their distance from vertex 1221
|
||||||
|
# colors = np.zeros((body.shape[0], 3))
|
||||||
|
# colors[:,0] = dist[1221,:]
|
||||||
|
# colors[:,1] = dist[1221,:]
|
||||||
|
# colors[:,2] = dist[1221,:]
|
||||||
|
# norm = colors / np.max(colors)
|
||||||
|
# colors = colors * 255
|
||||||
|
|
||||||
# get the distances between all vertices using dijsktra algorithm without get_dijsktra
|
# get the distances between all vertices using dijsktra algorithm without get_dijsktra
|
||||||
# from scipy.sparse import csr_matrix
|
# from scipy.sparse import csr_matrix
|
||||||
@@ -212,7 +465,7 @@ if __name__ == '__main__':
|
|||||||
# colors[:,0] = (body[:,0] - np.min(body[:,0])) / (np.max(body[:,0]) - np.min(body[:,0]))
|
# colors[:,0] = (body[:,0] - np.min(body[:,0])) / (np.max(body[:,0]) - np.min(body[:,0]))
|
||||||
# colors[:,1] = (body[:,1] - np.min(body[:,1])) / (np.max(body[:,1]) - np.min(body[:,1]))
|
# colors[:,1] = (body[:,1] - np.min(body[:,1])) / (np.max(body[:,1]) - np.min(body[:,1]))
|
||||||
# colors[:,2] = (body[:,2] - np.min(body[:,2])) / (np.max(body[:,2]) - np.min(body[:,2]))
|
# colors[:,2] = (body[:,2] - np.min(body[:,2])) / (np.max(body[:,2]) - np.min(body[:,2]))
|
||||||
fig = go.Figure(data=[go.Mesh3d(x=body[:,0], y=body[:,2], z=body[:,1], i=faces[:,0], j=faces[:,2], k=faces[:,1], vertexcolor=colors)])
|
fig = go.Figure(data=[go.Mesh3d(x=body[:,0], y=body[:,2], z=body[:,1], i=faces[:,0], j=faces[:,1], k=faces[:,2], vertexcolor=colors)])
|
||||||
fig.update_layout(scene=dict(xaxis=dict(range=[-1,1]), yaxis=dict(range=[-1,1]), zaxis=dict(range=[-1,1])))
|
fig.update_layout(scene=dict(xaxis=dict(range=[-1,1]), yaxis=dict(range=[-1,1]), zaxis=dict(range=[-1,1])))
|
||||||
fig.show()
|
fig.show()
|
||||||
# np.save('custom_data/pose_colors.npy', colors.astype(np.float32))
|
# np.save('custom_data/pose_colors.npy', colors.astype(np.float32))
|
||||||
@@ -222,6 +475,10 @@ if __name__ == '__main__':
|
|||||||
# fig.update_layout(scene=dict(xaxis=dict(range=[-1,1]), yaxis=dict(range=[-1,1]), zaxis=dict(range=[-1,1])))
|
# fig.update_layout(scene=dict(xaxis=dict(range=[-1,1]), yaxis=dict(range=[-1,1]), zaxis=dict(range=[-1,1])))
|
||||||
# fig.show()
|
# fig.show()
|
||||||
|
|
||||||
|
# save body with colors into a ply file
|
||||||
|
m = trimesh.Trimesh(vertices=body, faces=faces, vertex_colors=colors)
|
||||||
|
m.export('custom_data/body_colors.ply')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
Reference in New Issue
Block a user