Spaces:
Running
on
Zero
Running
on
Zero
from vedo import Mesh, Points, Plotter, screenshot, Arrow, Light, Plane | |
import imageio | |
import os | |
import numpy as np | |
from scipy.interpolate import Rbf, NearestNDInterpolator as Near | |
import re | |
screenshot_scale = 3 | |
cam = dict( | |
position=(-3.85922, -4.78140, 0.689328), | |
focal_point=(0.192544, 4.77379e-3, 0.0127248), | |
viewup=(0.0724348, 0.109097, 0.991388), | |
distance=5.25119, | |
clipping_range=(4.38228, 6.36775), | |
) | |
_red = [0.9, 0.1, 0.1] | |
_green= [0.4, 1.0, 0.8] | |
_blue =[0.7, 0.9, 1.0] | |
_dark_blue =[0.03, 0.4, 0.7] | |
def sort_list(l): | |
try: | |
return list(sorted(l, key=lambda x: int(re.search(r'\d+(?=\.)', x).group()))) | |
except AttributeError: | |
return sorted(l) | |
def get_lights(light_color=[255, 255, 245], offset=[0, 0, 0], intensity_mult=1): | |
# Add light sources at the given positions | |
# (grab the position and color of the arrow object) | |
orig = np.array([0, 0, 0]) + np.array(offset) | |
phl = Arrow(np.array([0.1, 0.1, 10]) + offset, orig, c=light_color).scale(0.2) | |
pfl = Arrow(np.array([1.5, 0.1, 0.3]) + offset, orig, c=light_color).scale(0.2) | |
pbl = Arrow(np.array([-1.5, 0.1, 0.3]) + offset, orig, c=light_color).scale(0.2) | |
prl = Arrow(np.array([0.1, -1.5, 0.3]) + offset, orig, c=light_color).scale(0.2) | |
pll = Arrow(np.array([0.1, 1.5, 0.3]) + offset, orig, c=light_color).scale(0.2) | |
hl = Light(phl, intensity=0.7 * intensity_mult, angle=180, ) | |
rl = Light(pfl, intensity=0.6 * intensity_mult, angle=180, ) | |
ll = Light(pbl, intensity=0.6 * intensity_mult, angle=180, ) | |
bl = Light(pll, intensity=0.6 * intensity_mult, angle=180, ) | |
fl = Light(prl, intensity=1 * intensity_mult, angle=180, ) | |
lights = [hl, fl, bl, ll, rl] | |
return lights | |
def get_mesh(mesh_name, mesh_opacity=1.0, mesh_lighting='default', rotation=[0, 0, 0], offset=[0, 0, 0], scale=0): | |
offset = np.array(offset) | |
#styles = ['default', 'metallic', 'plastic', 'shiny', 'glossy', 'ambient', 'off'] | |
mesh = Mesh(mesh_name, c=_blue, alpha=mesh_opacity).lighting(mesh_lighting) | |
if scale == 0: | |
bnd = np.array(mesh.bounds()) | |
scale = 1 / max(bnd[1]-bnd[0], bnd[3]-bnd[2], bnd[5]-bnd[4]) | |
mesh.scale(scale) | |
mesh.pos(offset) | |
mesh.rotate_x(rotation[0]) | |
mesh.rotate_y(rotation[1]) | |
mesh.rotate_z(rotation[2]) | |
# mesh.phong() | |
# mesh2.phong() | |
return mesh, scale | |
def get_ptc(ptc_name, rotation=[0, 0, 0], offset=[0, 0, 0], scale=0, color=_dark_blue): | |
offset = np.array(offset) | |
#styles = ['default', 'metallic', 'plastic', 'shiny', 'glossy', 'ambient', 'off'] | |
mesh = Points(Mesh(ptc_name), r=1).c([0.5,0.5,0.5]).alpha(0.8) | |
if scale == 0: | |
bnd = np.array(mesh.bounds()) | |
scale = 1 / max(bnd[1]-bnd[0], bnd[3]-bnd[2], bnd[5]-bnd[4]) | |
mesh.scale(scale) | |
mesh.pos(offset) | |
mesh.rotate_x(rotation[0]) | |
mesh.rotate_y(rotation[1]) | |
mesh.rotate_z(rotation[2]) | |
# mesh.phong() | |
# mesh2.phong() | |
return mesh, scale | |
def get_mesh_shadow(mesh, offset=[0, 0, 0], plane_normal=(0, 0, 1), direction=[0.1, -1.8, 3]): | |
shadow = [] | |
shad_col = np.array([0.8, 0.8, 0.8]) | |
min_z = mesh.points().min(axis=0)[2] | |
# mesh.add_shadow(plane='z', point=min_z, alpha=1, c=shad_col, culling=0.9,) | |
plane = Plane(pos=np.array([0, 0, min_z]) + np.array(offset), normal=plane_normal, s=[7, 7]).alpha(0.2) | |
shad = mesh.clone().project_on_plane(plane, direction=-np.array(direction) + np.array(offset)) | |
shad.c(shad_col).alpha(1).lighting("off").use_bounds(False) | |
shadow = shad | |
return shadow | |
def create_visual(mesh_files, directory, x,y,z, type='mesh'): | |
meshes, scales =[], [] | |
# plotter = Plotter(offscreen=True) | |
plotter = Plotter(bg=[255, 255, 255], offscreen=True) | |
frame_files = [] | |
# lights = get_lights() | |
for file in mesh_files: | |
if type == 'mesh': | |
mesh, scale = get_mesh(file, rotation=[x,y,z], mesh_lighting='metallic') | |
else: | |
mesh, scale = get_ptc(file) | |
plotter.clear() | |
shadow = get_mesh_shadow(mesh) | |
# plotter.add([mesh, shadow]) | |
plotter.show(mesh, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) | |
frame_path =file[:-4] + ".png" | |
frame_files.append(frame_path) | |
screenshot(frame_path, scale=1) | |
# Compile saved frames into a GIF | |
filename = os.path.join(directory, type+'_animation.gif') | |
with imageio.get_writer(filename, mode='I', duration=0.2) as writer: | |
for filename in frame_files: | |
image = imageio.imread(filename) | |
writer.append_data(image) | |
def create_mesh_animation(mesh_files, directory, x,y,z): | |
# Load all meshes | |
meshes = [Mesh(f) for f in mesh_files] | |
# Create a plotter | |
plotter = Plotter(bg=[255, 255, 255], offscreen=True) | |
# plotter = vedo.Plotter()# Use offscreen rendering to save frames | |
frame_files = [] # To store the path of each frame image | |
# plotter.camera.SetViewUp(0,0,1) | |
# shadow = mesh.clone().projectOnPlane(direction=(0,0,-1)) | |
# Color the shadow mesh dark and make it slightly transparent | |
for frame_id, mesh in enumerate(meshes): | |
mesh.rotate_x(x).rotate_y(y).rotate_z(z).lighting('metallic') | |
shadow = get_mesh_shadow(mesh) | |
scalars = 1- mesh.vertices[:, 2] | |
mesh.cmap('Blues', scalars) | |
# mesh.add_shadow('x', 0.95) | |
plotter.clear() | |
# plotter.add(mesh) | |
plotter.show(mesh, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) | |
frame_path = mesh_files[frame_id][:-4] + ".png" | |
frame_files.append(frame_path) | |
screenshot(frame_path, scale=1) # Save frame as image | |
#crop the images | |
# os.system("""convert -trim {0} "{1}" """.format(frame_path, frame_path)) | |
# Compile saved frames into a GIF | |
filename = os.path.join(directory, 'mesh_animation.gif') | |
with imageio.get_writer(filename, mode='I', duration=0.2) as writer: | |
for f in frame_files: | |
image = imageio.imread(f) | |
writer.append_data(image) | |
os.system("""convert -trim {0} "{1}" """.format(f, f)) | |
def create_point_cloud_animation(files, directory, x,y,z): | |
# Load all meshes | |
meshes = [Points(Mesh(f), r=1) for f in files] | |
# Create a plotter | |
plotter = Plotter(bg=[255, 255, 255], offscreen=True) | |
# plotter = vedo.Plotter()# Use offscreen rendering to save frames | |
frame_files = [] # To store the path of each frame image | |
# plotter.camera.SetViewUp(0,0,1) | |
# shadow = mesh.clone().projectOnPlane(direction=(0,0,-1)) | |
# Color the shadow mesh dark and make it slightly transparent | |
for frame_id, mesh in enumerate(meshes): | |
mesh.rotate_x(x).rotate_y(y).rotate_z(z).c([0.5,0.5,0.5]) | |
shadow = get_mesh_shadow(mesh) | |
# scalars = 1- mesh.vertices[:, 2] | |
# mesh.cmap('binary', scalars) | |
plotter.clear() | |
plotter.show(mesh, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) | |
frame_path = files[frame_id][:-4] + ".png" | |
frame_files.append(frame_path) | |
screenshot(frame_path, scale=1) # Save frame as image | |
#crop the images | |
# os.system("""convert -trim {0} "{1}" """.format(frame_path, frame_path)) | |
# Compile saved frames into a GIF | |
filename = os.path.join(directory, 'pct_animation.gif') | |
with imageio.get_writer(filename, mode='I', duration=0.2) as writer: | |
for f in frame_files: | |
image = imageio.imread(f) | |
writer.append_data(image) | |
os.system("""convert -trim {0} "{1}" """.format(f, f)) | |
def point_cloud_colormap(gt_ptc, ptc, corr_num): | |
s1, _ = get_ptc(gt_ptc, color=_red) | |
s2, _ = get_ptc(ptc, color=_blue) | |
landmarks1 = s1.vertices[:corr_num,:] | |
landmarks2 = s2.vertices[:corr_num,:] | |
x, y, z = np.split(landmarks1, 3, axis=1) | |
desc = x**2 + y**2 + z**2 | |
# itr = Rbf(x, y, z, desc) # Radial Basis Function interpolator | |
itr = Near(landmarks1, desc) # Nearest-neighbour interpolator | |
# interpolate descriptor on the full set of mesh vertices | |
xi, yi, zi = np.split(s2.vertices, 3, axis=1) | |
interpolated_desc = itr(xi, yi, zi) | |
s2.cmap('coolwarm', interpolated_desc.squeeze()).add_scalarbar(title='error') | |
# s2.point_colors(interpolated_desc, cmap='coolwarm', vmin=min(interpolated_desc), vmax=max(interpolated_desc)).addScalarBar(title='$\error$') | |
plotter = Plotter() | |
plotter.show(s2, __doc__, axes=True) | |
def mesh_colormap(gt_mesh, mesh, corr_num): | |
s1, _ = get_ptc(gt_ptc, color=_red) | |
s2, _ = get_ptc(ptc, color=_blue) | |
landmarks1 = s1.vertices[:corr_num,:] | |
landmarks2 = s2.vertices[:corr_num,:] | |
x, y, z = np.split(landmarks1, 3, axis=1) | |
desc = x**2 + y**2 + z**2 | |
# itr = Rbf(x, y, z, desc) # Radial Basis Function interpolator | |
itr = Near(landmarks1, desc) # Nearest-neighbour interpolator | |
# interpolate descriptor on the full set of mesh vertices | |
xi, yi, zi = np.split(s2.vertices, 3, axis=1) | |
interpolated_desc = itr(xi, yi, zi) | |
s2.cmap('coolwarm', interpolated_desc.squeeze()).add_scalarbar(title='error') | |
# s2.point_colors(interpolated_desc, cmap='coolwarm', vmin=min(interpolated_desc), vmax=max(interpolated_desc)).addScalarBar(title='$\error$') | |
plotter = Plotter() | |
plotter.show(s2, __doc__, axes=True) | |
def plot_two_mesh(meshfile1, meshfile2, x,y,z): | |
plotter = Plotter(bg=[255, 255, 255], offscreen=True) | |
mesh1, scale = get_ptc(meshfile1, rotation=[x,y,z]) | |
mesh1.alpha(1.0).c([0.2,0.2,0.2]) | |
# scalars = 1- mesh1.vertices[:, 2] | |
# mesh1.cmap('Oranges', scalars) | |
# mesh1.c(_dark_blue) | |
mesh2, scale = get_mesh(meshfile2, rotation=[x,y,z], mesh_lighting='shiny') | |
scalars = 1- mesh2.vertices[:, 2] | |
mesh2.cmap('Blues', scalars) | |
plotter.show(mesh1, mesh2, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) | |
frame_path =meshfile2[:-4] + ".png" | |
screenshot(frame_path, scale=1) | |
os.system("""convert -trim {0} "{1}" """.format(frame_path, frame_path)) | |
if __name__ == "__main__": | |
folder = '/home/wiss/sang/git/implicit_neuro_morph/jax_implicit_neuro_morph/exp/smal/2024_04_18_15_11_59/reconstructions' | |
prefix = 'shape_0_to_4000_' | |
# filenames = [os.path.join(folder, prefix + str(i) + '_mesh.ply') for i in range(0,11)] | |
# create_mesh_animation(filenames, folder, -45, -45, 90) | |
# filenames = [os.path.join(folder, prefix + str(i) + '_ptc.ply') for i in range(0,11)] | |
# gt_ptc = os.path.join(folder, prefix + 'gt_pointcloud_y.ply') | |
# ptc = os.path.join(folder, prefix + 'epoch_10000_time_10_ptc.ply') | |
# create_point_cloud_animation(filenames, folder, -45, -45, 90) | |
folder = '/home/wiss/sang/git/implicit_neuro_morph/jax_implicit_neuro_morph/exp/smal/2024_04_18_15_11_59/eval' | |
# mesh_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith('mesh.ply')] | |
# mesh_files = sort_list(mesh_files) | |
# create_visual(mesh_files, folder, 0,0,-90, type='mesh') | |
# create_mesh_animation(mesh_files, folder, 0,0, -90) | |
# folder = '/home/wiss/sang/git/implicit_neuro_morph/jax_implicit_neuro_morph/exp/fraust_r/2024_04_22_14_01_05/eval' | |
# mesh_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith('ptc.ply')] | |
# mesh_files = sort_list(mesh_files) | |
# create_point_cloud_animation(mesh_files, folder, 0,0,-90) | |
prefix = 'shape_0_to_4000_' | |
mesh1 = 'gt_pointcloud_y.ply' | |
mesh2 = 'step_10_mesh.ply' | |
meshfile1 = os.path.join(folder, prefix + mesh1) | |
meshfile2 = os.path.join(folder, prefix + mesh2) | |
plot_two_mesh(meshfile1, meshfile2, 0, 0, -30) | |