Files
cvpr_2023/data/investigate.py
T
2023-06-01 17:51:01 +02:00

282 lines
12 KiB
Python

import os
import sys
import random
import numpy as np
import plotly.graph_objects as go
from pymeshfix import MeshFix
import trimesh
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
from data.cloth3d_io import read_garment_mask, read_garment_template, read_posed_garment_frame, loadInfo, read_posed_body_frame, read_posed_body, read_posed_garment, read_curvatures, read_curvature_frame, writeOBJ
# from custom_utils.custom_utils import _maskFaces
def _maskFaces(V, F, mask, return_unfixed=False):
V_mask = mask
F_mask = np.take(V_mask, F.reshape(-1), axis=0)
F_mask = F_mask.reshape((-1, 3)).sum(axis=1) == 3
V_ind = np.zeros(V_mask.shape)
V_ind[V_mask] = np.arange(V_mask.sum())
F_new = np.take(V_ind, F[F_mask, :].reshape(-1), axis=0).reshape((-1, 3))
V_new = V[V_mask, :]
if return_unfixed:
return V_new, F_new, F[F_mask, :]
else:
return V_new, F_new
def get_frames(folder, frames_file):
frames = []
with open(os.path.join(folder, frames_file), 'r') as f:
for line in f:
frames.append(line.strip())
return frames
def plot(mesh, faces):
fig = go.Figure()
fig.add_trace(go.Mesh3d(
x=mesh[:,0],
y=mesh[:,1],
z=mesh[:,2],
i = faces[:,0],
j = faces[:,1],
k = faces[:,2]
),)
fig.update_layout(scene_aspectmode='manual', scene_aspectratio=dict(x=1, y=1, z=1),
)
helper = dict(xaxis = dict(nticks=4, range=[-1,1],),
yaxis = dict(nticks=4, range=[-1,1],),
zaxis = dict(nticks=4, range=[-1,1],),)
fig.update_layout(scene = helper,
)
fig.show()
def build_lookup_table(repeated):
# iterate through the list and create a dict from each sub array in the list where each dict has one element of the sub array as key and the other elements as value as a list and repeat for each element
lookup = {}
for i in range(len(repeated)):
for j in range(len(repeated[i])):
if len(repeated[i]) == 1:
continue
lookup[repeated[i][j]] = [repeated[i][k] for k in range(len(repeated[i]))] # if k != j
return lookup
def mask_faces(all_faces, mask, raw_mask, repeated, verts):
# if any of the vertices of a face is masked, mask the face
lookup = build_lookup_table(repeated)
faces = []
for face in all_faces:
# if any two or all three vertices of the face have the same coordinates then continue
if np.allclose(verts[face[0]], verts[face[1]]) or np.allclose(verts[face[0]], verts[face[2]]) or np.allclose(verts[face[1]], verts[face[2]]):
continue
if mask[face[0]] and mask[face[1]] and mask[face[2]]:
faces.append(face)
else:
# create three arrays of vertices from the lookup table for each vertex of the face
# but only for those vertices that are in the lookup table, otherwise createa a single element array with the vertex
v1 = lookup[face[0]] if face[0] in lookup else [face[0]]
v2 = lookup[face[1]] if face[1] in lookup else [face[1]]
v3 = lookup[face[2]] if face[2] in lookup else [face[2]]
# try each combination of vertices from the three arrays and check if the face is masked
found_replacement = False
for i in range(len(v1)):
if not found_replacement:
for j in range(len(v2)):
if not found_replacement:
for k in range(len(v3)):
if not found_replacement:
if mask[v1[i]] and mask[v2[j]] and mask[v3[k]]:
# if the euclidean distance between any two of the vertices of the face is less than 0.05 then append the face
# if np.linalg.norm(verts[v1[i]] - verts[v2[j]]) < 0.05 and np.linalg.norm(verts[v1[i]] - verts[v3[k]]) < 0.05 and np.linalg.norm(verts[v2[j]] - verts[v3[k]]) < 0.05:
#only add the face if this face originally existed among the faces of the garment
# if not np.any([np.array([v1[i], v2[j], v3[k]], dtype=np.int32) == face for face in all_faces]):
# continue
# if all vertices of the face have a value of 2 in the raw mask then don't add the face
# if np.all(raw_mask[[v1[i], v2[j], v3[k]]] == 2):
# continue
# skip face if it's area is more than 0.001 and at least one of the vertices has value of 2 in the raw mask
# if np.linalg.norm(np.cross(verts[v1[i]] - verts[v2[j]], verts[v1[i]] - verts[v3[k]])) > 0.001 and np.any(raw_mask[[v1[i], v2[j], v3[k]]] == 2):
# continue
# if np.linalg.norm(np.cross(verts[v1[i]] - verts[v2[j]], verts[v1[i]] - verts[v3[k]])) > 0.001:
# continue
# if any edge of the face is longer than 0.1 and both vertices of the edge have a value of 2 in the raw mask then skip the face
# if np.linalg.norm(verts[v1[i]] - verts[v2[j]]) > 0.05 and (raw_mask[v1[i]] == 2 or raw_mask[v2[j]] == 2):
# continue
# if np.linalg.norm(verts[v1[i]] - verts[v3[k]]) > 0.05 and (raw_mask[v1[i]] == 2 or raw_mask[v3[k]] == 2):
# continue
# if np.linalg.norm(verts[v2[j]] - verts[v3[k]]) > 0.05 and (raw_mask[v2[j]] == 2 or raw_mask[v3[k]] == 2):
# continue
faces.append(np.array([v1[i], v2[j], v3[k]], dtype=np.int32))
assert np.all(verts[face] == verts[faces[-1]])
found_replacement = True
break
# for j in range(len(v2)):
# for k in range(len(v3)):
# if mask[v1[i]] and mask[v2[j]] and mask[v3[k]]:
# faces.append([v1[i], v2[j], v3[k]])
# break
faces = np.array(faces)
V_ind = np.zeros(mask.shape, dtype=np.int32)
V_ind[mask] = np.arange(mask.sum())
F_new = np.take(V_ind, faces.reshape(-1), axis=0).reshape((-1, 3))
return F_new
def check(folder, frame):
id, frame_nr, garment = frame.split()
frame_nr = int(frame_nr)
info = loadInfo(os.path.join(folder, id, 'info.mat'))
raw_mask = read_garment_mask(folder, id, garment, return_raw=True)
mask = raw_mask > 0
mesh_posed = read_posed_garment_frame(folder, id, garment, frame_nr, mask=mask, shape=info['shape'], pose=info['poses'][:,frame_nr], deorient=use_no_orient, unshape=no_shape)
v = mesh_posed[mask,:]
is_skirt = (garment == 'Dress' or garment == 'Skirt')
skirt_mod = '_skirt' if is_skirt else ''
F = np.load(f'smpl/smpl_faces{skirt_mod}.npy').astype(np.int32)
_, faces, unfixed = _maskFaces(np.zeros((14475,3)), F, mask, True)
meshfix = MeshFix(v, faces)
holes = meshfix.extract_holes()
# plot(v, faces)
unq, idx, count = np.unique(mesh_posed, axis=0, return_counts=True, return_index=True)
repeated_groups = unq[count > 1]
new_border = []
for border in np.array(holes.points):
# find the index of the vertex in the original mesh
ind = np.argwhere(np.all(mesh_posed == border, axis=1))
new_border.extend(ind.ravel())
raw_mask[new_border] = 2
mask_2 = np.zeros((14475), dtype=bool)
mask_2_raw = np.zeros((14475), dtype=np.uint8)
mask_2[idx] = True
mask_2_raw = mask_2.astype(np.uint8)
mask_3 = np.zeros((14475), dtype=bool)
mask_3[mask_2] = raw_mask[mask_2] == 2
mask_2_raw[mask_3] = 2
v_2 = mesh_posed[mask_2,:]
_, faces_2 = _maskFaces(np.zeros((14475,3)), F, mask_2)
# plot(v_2, faces_2)
# writeOBJ('temp/investigate.obj', v, faces)
repeated = []
for repeated_group in repeated_groups:
repeated_idx = np.argwhere(np.all(mesh_posed == repeated_group, axis=1))
repeated.append(repeated_idx.ravel())
# # if a vertex from v_2 is not part of v then set the corresponding value in mask_0 to 0
# mask_0 = np.zeros((v_2.shape[0]), dtype=bool)
# for i, _v in enumerate(v_2):
# if not np.any([np.all(_v == _w) for _w in v]):
# mask_0[i] = True
# mask_0_0 = np.zeros((14475), dtype=bool)
# mask_0_0[mask_2] = 1 - mask_0
# mask_4 = np.logical_not(mask_0)
faces_3 = mask_faces(F, mask_2, mask_2_raw, repeated, mesh_posed)
# writeOBJ('temp/investigate_3.obj', v_2, faces_3)
# plot(v_2, faces_3)
# save stl
# mesh = trimesh.Trimesh(vertices=v_2, faces=faces_3, process=False, validate=False)
# mesh.export('temp/investigate_00761.stl')
# # read stl file
# mesh = trimesh.load('temp/fixed_00761.stl', process=False, validate=False)
# mesh = trimesh.load('temp/fixed_00761.ply', process=False, validate=False)
# plotly plot of mesh with v_2 vertices and faces from trimesh mesh
# faces_4 = faces_3 #np.asarray(mesh.faces)
# go.Figure(data = [go.Mesh3d(x=v_2[:, 0], y=v_2[:, 1], z=v_2[:, 2], i=faces_4[:, 0], j=faces_4[:, 1], k=faces_4[:, 2],)
# ]).show()
# plot repeated
r = []
for rr in repeated:
r.extend(rr)
x = mesh_posed
y = mesh_posed[r,:]
# go.Figure(data = [go.Scatter3d(x=x[:, 0], y=x[:, 1], z=x[:, 2], marker=dict(size=3, line=dict(width=0),), mode='markers'),
# go.Scatter3d(x=y[:, 0], y=y[:, 1], z=y[:, 2], marker=dict(size=5, line=dict(width=0),), mode='markers'),
# ]).show()
# unq, idx, count = np.unique(v, axis=0, return_counts=True, return_index=True)
# repeated_groups = unq[count > 1]
# repeated = []
# for repeated_group in repeated_groups:
# repeated_idx = np.argwhere(np.all(v == repeated_group, axis=1))
# repeated.append(repeated_idx.ravel())
# mask_3 = np.zeros((v.shape[0]), dtype=bool)
# mask_3[idx] = True
# faces_4 = mask_faces(faces.astype(np.int64), mask_3, mask_2_raw, repeated, v)
# plot(v[mask_3,:], faces_4)
return mask_2_raw, faces_3
pass
def remask(folder, frame, mask, out_folder):
id, frame_nr, garment = frame.split()
frame_nr = int(frame_nr)
info = loadInfo(os.path.join(folder, id, 'info.mat'))
if frame_nr == 0:
mesh_static = read_static_garment(folder, id, garment)
mesh_posed = read_posed_garment_frame(folder, id, garment, frame_nr, mask=None, shape=None, pose=info['poses'][:,frame_nr], deorient=True, unshape=None)
mesh_posed = mesh_posed[mask,:]
os.makedirs(os.path.join(out_folder, 'mesh_posed_no_orient'), exist_ok=True)
np.savez_compressed(os.path.join(out_folder, 'mesh_posed_no_orient', f'{id}_{frame_nr}.npz'), mesh_posed_no_orient=mesh_posed)
if __name__ == "__main__":
folder = r'D:\Work\Dataset\cloth3d\train'
frames = [f'00761_{i}' for i in range(300)]
root = '/'.join(folder.split('/')[:-1])
type = folder.split('/')[-1]
use_no_orient = False
no_shape = False
is_skirt = False
skirt_modifier = '_skirt' if is_skirt else ''
orient_mod = '_no_orient' if use_no_orient else ''
shape_mod = '_no_shape' if no_shape else ''
while True:
frame = random.choice(frames)
frame = '00761 0 Tshirt'
mask, faces = check(folder, frame)
remask(folder, frame, mask, 'temp/00761')
pass