import os import sys import random import numpy as np import plotly.graph_objects as go from pymeshfix import MeshFix 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 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'custom_utils/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) # 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) pass if __name__ == "__main__": folder = '/home/workspace/data/dataset/cloth3d/train' frames = get_frames(folder, 'frames_all.txt') root = '/'.join(folder.split('/')[:-1]) type = folder.split('/')[-1] use_no_orient = False no_shape = False is_skirt = True 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 = '05936 0 Dress' check(folder, frame) pass