update
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import os
|
||||
import tqdm
|
||||
import scipy.interpolate as spi
|
||||
import numpy as np
|
||||
import plotly.graph_objects as go
|
||||
import plotly.express as ex
|
||||
|
||||
|
||||
def fill(img, mask):
|
||||
coords = np.transpose(np.stack(np.nonzero((1 - mask))), (1,0))
|
||||
img_idx = np.transpose(np.stack(np.nonzero((mask))), (1,0))
|
||||
img_data = img[img_idx[:,0], img_idx[:,1], :]
|
||||
|
||||
interpolator = spi.NearestNDInterpolator(x=img_idx, y=img_data)
|
||||
img_2 = interpolator(coords)
|
||||
res = np.zeros((512,256,3), dtype=np.float32)
|
||||
res[coords[:,0], coords[:,1], :] = img_2
|
||||
res[img_idx[:,0], img_idx[:,1], :] = img_data
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def fill_label(img, mask):
|
||||
coords = np.transpose(np.stack(np.nonzero((1 - mask))), (1,0))
|
||||
img_idx = np.transpose(np.stack(np.nonzero((mask))), (1,0))
|
||||
img_data = img[img_idx[:,0], img_idx[:,1]]
|
||||
|
||||
interpolator = spi.NearestNDInterpolator(x=img_idx, y=img_data)
|
||||
img_2 = interpolator(coords)
|
||||
res = np.zeros((512,256), dtype=np.float32)
|
||||
res[coords[:,0], coords[:,1]] = img_2
|
||||
res[img_idx[:,0], img_idx[:,1]] = img_data
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def fill_uv_maps_posed_body(folder, type):
|
||||
os.makedirs(os.path.join(folder, type + '_filled'), exist_ok=True)
|
||||
mask = np.load('custom_utils/mask_256x512.npy')
|
||||
|
||||
frames = os.listdir(os.path.join(folder, type))
|
||||
|
||||
for frame in tqdm.tqdm(frames):
|
||||
id, _ = frame.split('_')
|
||||
# mask = np.load(os.path.join(folder, 'uv_mask', id + '.npz')); mask = mask['uv_mask']
|
||||
img = np.load(os.path.join(folder, type, frame)); img = img['uv_posed_body_no_orient']
|
||||
filled = fill(img, mask)
|
||||
np.savez_compressed(os.path.join(folder, type + '_filled', frame), uv_posed_body_no_orient_filled = filled)
|
||||
|
||||
|
||||
def fill_uv_maps_curv(folder, type):
|
||||
os.makedirs(os.path.join(folder, type + '_filled'), exist_ok=True)
|
||||
mask = np.load('custom_utils/mask_256x512.npy')
|
||||
|
||||
frames = os.listdir(os.path.join(folder, type))
|
||||
|
||||
for frame in tqdm.tqdm(frames):
|
||||
id, _ = frame.split('_')
|
||||
mask = np.load(os.path.join(folder, 'uv_mask', id + '.npz')); mask = mask['uv_mask']
|
||||
img = np.load(os.path.join(folder, type, frame)); img = img['curvature_uv']
|
||||
filled = fill_label(img, mask)
|
||||
np.savez_compressed(os.path.join(folder, type + '_filled', frame), uv_curvature_filled = filled)
|
||||
|
||||
|
||||
|
||||
def fill_uv_maps_unposed(folder, type):
|
||||
os.makedirs(os.path.join(folder, type + '_filled'), exist_ok=True)
|
||||
mask = np.load('custom_utils/mask_256x512.npy')
|
||||
|
||||
frames = os.listdir(os.path.join(folder, type))
|
||||
|
||||
for frame in tqdm.tqdm(frames):
|
||||
id, _ = frame.split('_')
|
||||
mask = np.load(os.path.join(folder, 'uv_mask', id + '.npz')); mask = mask['uv_mask']
|
||||
img = np.load(os.path.join(folder, type, frame)); img = img['uv_unposed_no_shape']
|
||||
filled = fill(img, mask)
|
||||
np.savez_compressed(os.path.join(folder, type + '_filled', frame), uv_unposed_no_shape_filled = filled)
|
||||
|
||||
|
||||
|
||||
def fill_uv_maps_static(folder, type):
|
||||
os.makedirs(os.path.join(folder, type + '_filled'), exist_ok=True)
|
||||
mask = np.load('custom_utils/mask_256x512.npy')
|
||||
|
||||
frames = os.listdir(os.path.join(folder, type))
|
||||
|
||||
for frame in tqdm.tqdm(frames):
|
||||
id, _ = frame.split('.')
|
||||
mask = np.load(os.path.join(folder, 'uv_mask', id + '.npz')); mask = mask['uv_mask']
|
||||
img = np.load(os.path.join(folder, type, frame)); img = img['uv_static']
|
||||
filled = fill(img, mask)
|
||||
np.savez_compressed(os.path.join(folder, type + '_filled', frame), uv_static_filled = filled)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# fill_uv_maps_static(folder='/home/workspace/local-data/train_100', type='uv_static')
|
||||
# fill_uv_maps_unposed(folder='/home/workspace/local-data/train_100', type='uv_unposed_no_shape')
|
||||
# fill_uv_maps_curv(folder='/home/workspace/local-data/train_100', type='uv_curvature')
|
||||
fill_uv_maps_posed_body(folder='/home/workspace/local-data/train_100', type='uv_posed_body_no_orient')
|
||||
|
||||
|
||||
print()
|
||||
@@ -0,0 +1,138 @@
|
||||
import numpy as np
|
||||
from struct import pack, unpack
|
||||
|
||||
|
||||
"""
|
||||
Reads PC2 files, and proposed format PC16 files
|
||||
Inputs:
|
||||
- file: path to .pc2/.pc16 file
|
||||
- float16: False for PC2 files, True for PC16
|
||||
Output:
|
||||
- data: dictionary with .pc2/.pc16 file data
|
||||
NOTE: 16-bit floats lose precision with high values (positive or negative),
|
||||
we do not recommend using this format for data outside range [-2, 2]
|
||||
"""
|
||||
def readPC2(file, float16=False):
|
||||
assert file.endswith('.pc2') and not float16 or file.endswith('.pc16') and float16, 'File format not consistent with specified input format'
|
||||
data = {}
|
||||
bytes = 2 if float16 else 4
|
||||
dtype = np.float16 if float16 else np.float32
|
||||
with open(file, 'rb') as f:
|
||||
# Header
|
||||
data['sign'] = f.read(12)
|
||||
# data['version'] = int.from_bytes(f.read(4), 'little')
|
||||
data['version'] = unpack('<i', f.read(4))[0]
|
||||
# Num points
|
||||
# data['nPoints'] = int.from_bytes(f.read(4), 'little')
|
||||
data['nPoints'] = unpack('<i', f.read(4))[0]
|
||||
# Start frame
|
||||
data['startFrame'] = unpack('f', f.read(4))
|
||||
# Sample rate
|
||||
data['sampleRate'] = unpack('f', f.read(4))
|
||||
# Number of samples
|
||||
# data['nSamples'] = int.from_bytes(f.read(4), 'little')
|
||||
data['nSamples'] = unpack('<i', f.read(4))[0]
|
||||
# Animation data
|
||||
size = data['nPoints']*data['nSamples']*3*bytes
|
||||
data['V'] = np.frombuffer(f.read(size), dtype=dtype).astype(np.float32)
|
||||
data['V'] = data['V'].reshape(data['nSamples'], data['nPoints'], 3)
|
||||
|
||||
return data
|
||||
|
||||
"""
|
||||
Reads an specific frame of PC2/PC16 files
|
||||
Inputs:
|
||||
- file: path to .pc2/.pc16 file
|
||||
- frame: number of the frame to read
|
||||
- float16: False for PC2 files, True for PC16
|
||||
Output:
|
||||
- T: mesh vertex data at specified frame
|
||||
"""
|
||||
def readPC2Frame(file, frame, float16=False):
|
||||
assert file.endswith('.pc2') and not float16 or file.endswith('.pc16') and float16, 'File format not consistent with specified input format'
|
||||
assert frame >= 0 and isinstance(frame,int), 'Frame must be a positive integer'
|
||||
bytes = 2 if float16 else 4
|
||||
dtype = np.float16 if float16 else np.float32
|
||||
with open(file,'rb') as f:
|
||||
# Num points
|
||||
f.seek(16)
|
||||
# nPoints = int.from_bytes(f.read(4), 'little')
|
||||
nPoints = unpack('<i', f.read(4))[0]
|
||||
# Number of samples
|
||||
f.seek(28)
|
||||
# nSamples = int.from_bytes(f.read(4), 'little')
|
||||
nSamples = unpack('<i', f.read(4))[0]
|
||||
if frame > nSamples:
|
||||
print("Frame index outside size")
|
||||
print("\tN. frame: " + str(frame))
|
||||
print("\tN. samples: " + str(nSamples))
|
||||
return
|
||||
# Read frame
|
||||
size = nPoints * 3 * bytes
|
||||
f.seek(size * frame, 1) # offset from current '1'
|
||||
T = np.frombuffer(f.read(size), dtype=dtype).astype(np.float32)
|
||||
return T.reshape(nPoints, 3)
|
||||
|
||||
"""
|
||||
Writes PC2 and PC16 files
|
||||
Inputs:
|
||||
- file: path to file (overwrites if exists)
|
||||
- V: 3D animation data as a three dimensional array (N. Frames x N. Vertices x 3)
|
||||
- float16: False for writing as PC2 file, True for PC16
|
||||
This function assumes 'startFrame' to be 0 and 'sampleRate' to be 1
|
||||
NOTE: 16-bit floats lose precision with high values (positive or negative),
|
||||
we do not recommend using this format for data outside range [-2, 2]
|
||||
"""
|
||||
def writePC2(file, V, float16=False):
|
||||
assert file.endswith('.pc2') and not float16 or file.endswith('.pc16') and float16, 'File format not consistent with specified input format'
|
||||
if float16: V = V.astype(np.float16)
|
||||
else: V = V.astype(np.float32)
|
||||
with open(file, 'wb') as f:
|
||||
# Create the header
|
||||
headerFormat='<12siiffi'
|
||||
headerStr = pack(headerFormat, b'POINTCACHE2\0',
|
||||
1, V.shape[1], 0, 1, V.shape[0])
|
||||
f.write(headerStr)
|
||||
# Write vertices
|
||||
f.write(V.tobytes())
|
||||
|
||||
"""
|
||||
Reads OBJ files
|
||||
Only handles vertices, faces and UV maps
|
||||
Input:
|
||||
- file: path to .obj file
|
||||
Outputs:
|
||||
- V: 3D vertices
|
||||
- F: 3D faces
|
||||
- Vt: UV vertices
|
||||
- Ft: UV faces
|
||||
Correspondence between mesh and UV map is implicit in F to Ft correspondences
|
||||
If no UV map data in .obj file, it shall return Vt=None and Ft=None
|
||||
"""
|
||||
def readOBJ(file):
|
||||
V, Vt, F, Ft = [], [], [], []
|
||||
with open(file, 'r') as f:
|
||||
T = f.readlines()
|
||||
for t in T:
|
||||
# 3D vertex
|
||||
if t.startswith('v '):
|
||||
v = [float(n) for n in t.replace('v ','').split(' ')]
|
||||
V += [v]
|
||||
# UV vertex
|
||||
elif t.startswith('vt '):
|
||||
v = [float(n) for n in t.replace('vt ','').split(' ')]
|
||||
Vt += [v]
|
||||
# Face
|
||||
elif t.startswith('f '):
|
||||
idx = [n.split('/') for n in t.replace('f ','').split(' ')]
|
||||
f = [int(n[0]) - 1 for n in idx]
|
||||
F += [f]
|
||||
# UV face
|
||||
if '/' in t:
|
||||
f = [int(n[1]) - 1 for n in idx]
|
||||
Ft += [f]
|
||||
V = np.array(V, np.float32)
|
||||
Vt = np.array(Vt, np.float32)
|
||||
if Ft: assert len(F) == len(Ft), 'Inconsistent .obj file, mesh and UV map do not have the same number of faces'
|
||||
else: Vt, Ft = None, None
|
||||
return V, F, Vt, Ft
|
||||
Reference in New Issue
Block a user