Download hoho/vis.py from usm3d/tools: direct link, hf CLI and curl.
- Browser
- Download file 5 kB
-
https://huggingface.co/usm3d/tools/resolve/refs%2Fpr%2F5/hoho/vis.py
- Command line
-
hf download hf://usm3d/tools@refs/pr/5/hoho/vis.py
-
curl -L -o vis.py https://huggingface.co/usm3d/tools/resolve/refs%2Fpr%2F5/hoho/vis.py
5 kB
| import trimesh | |
| import numpy as np | |
| from copy import deepcopy | |
| from PIL import Image | |
| from . import color_mappings | |
| def line(p1, p2, c=(255,0,0), resolution=10, radius=0.05): | |
| '''draws a 3d cylinder along the line (p1, p2)''' | |
| # check colors | |
| if len(c) == 1: | |
| c = [c[0]]*4 | |
| elif len(c) == 3: | |
| c = [*c, 255] | |
| elif len(c) != 4: | |
| raise ValueError(f'{c} is not a valid color (must have 1,3, or 4 elements).') | |
| # compute length and direction of segment | |
| p1, p2 = np.asarray(p1), np.asarray(p2) | |
| l = np.linalg.norm(p2-p1) | |
| direction = (p2 - p1) / l | |
| # point z along direction of segment | |
| T = np.eye(4) | |
| T[:3, 2] = direction | |
| T[:3, 3] = (p1+p2)/2 | |
| #reorthogonalize basis | |
| b0, b1 = T[:3, 0], T[:3, 1] | |
| if np.abs(np.dot(b0, direction)) < np.abs(np.dot(b1, direction)): | |
| T[:3, 1] = -np.cross(b0, direction) | |
| else: | |
| T[:3, 0] = np.cross(b1, direction) | |
| # generate and transform mesh | |
| mesh = trimesh.primitives.Cylinder(radius=radius, height=l, transform=T) | |
| # apply uniform color | |
| mesh.visual.vertex_colors = np.ones_like(mesh.visual.vertex_colors)*c | |
| return mesh | |
| def show_wf(row, radius=10): | |
| EDGE_CLASSES = ['eave', | |
| 'ridge', | |
| 'step_flashing', | |
| 'rake', | |
| 'flashing', | |
| 'post', | |
| 'valley', | |
| 'hip', | |
| 'transition_line'] | |
| return [line(a,b, radius=radius, c=color_mappings.gestalt_color_mapping[EDGE_CLASSES[cls_id]]) for (a,b), cls_id in zip(np.stack([*row['wf_vertices']])[np.stack(row['wf_edges'])], row['edge_semantics'])] | |
| # return [line(a,b, radius=radius, c=color_mappings.edge_colors[cls_id]) for (a,b), cls_id in zip(np.stack([*row['wf_vertices']])[np.stack(row['wf_edges'])], row['edge_semantics'])] | |
| def show_grid(edges, meshes=None, row_length=5): | |
| ''' | |
| edges: list of list of meshes | |
| meshes: optional corresponding list of meshes | |
| row_length: number of meshes per row | |
| returns trimesh.Scene() | |
| ''' | |
| T = np.eye(4) | |
| out = [] | |
| edges = [sum(e[1:], e[0]) for e in edges] | |
| row_height = 1.1 * max((e.extents for e in edges), key=lambda e: e[1])[1] | |
| col_width = 1.1 * max((e.extents for e in edges), key=lambda e: e[0])[0] | |
| # print(row_height, col_width) | |
| if meshes is None: | |
| meshes = [None]*len(edges) | |
| for i, (gt, mesh) in enumerate(zip(edges, meshes), start=0): | |
| mesh = deepcopy(mesh) | |
| gt = deepcopy(gt) | |
| if i%row_length != 0: | |
| T[0, 3] += col_width | |
| else: | |
| T[0, 3] = 0 | |
| T[1, 3] += row_height | |
| # print(T[0,3]/col_width, T[2,3]/row_height) | |
| if mesh is not None: | |
| mesh.apply_transform(T) | |
| out.append(mesh) | |
| gt.apply_transform(T) | |
| out.append(gt) | |
| out.extend([mesh, gt]) | |
| return trimesh.Scene(out) | |
| def visualize_order_images(row_order): | |
| return create_image_grid(row_order['ade20k'] + row_order['gestalt'] + [visualize_depth(dm) for dm in row_order['depthcm']], num_per_row=len(row_order['ade20k'])) | |
| def create_image_grid(images, target_length=312, num_per_row=2): | |
| # Calculate the target size for the first image | |
| first_img = images[0] | |
| aspect_ratio = first_img.width / first_img.height | |
| new_width = int((target_length ** 2 * aspect_ratio) ** 0.5) | |
| new_height = int((target_length ** 2 / aspect_ratio) ** 0.5) | |
| # Resize the first image | |
| resized_images = [img.resize((new_width, new_height), Image.Resampling.LANCZOS) for img in images] | |
| # Calculate the grid size | |
| num_rows = (len(resized_images) + num_per_row - 1) // num_per_row | |
| grid_width = new_width * num_per_row | |
| grid_height = new_height * num_rows | |
| # Create a new image for the grid | |
| grid_img = Image.new('RGB', (grid_width, grid_height)) | |
| # Paste the images into the grid | |
| for i, img in enumerate(resized_images): | |
| x_offset = (i % num_per_row) * new_width | |
| y_offset = (i // num_per_row) * new_height | |
| grid_img.paste(img, (x_offset, y_offset)) | |
| return grid_img | |
| import matplotlib.pyplot as plt | |
| def visualize_depth(depth, min_depth=None, max_depth=None, cmap='rainbow'): | |
| depth = np.array(depth) | |
| if min_depth is None: | |
| min_depth = np.min(depth) | |
| if max_depth is None: | |
| max_depth = np.max(depth) | |
| # Normalize the depth to be between 0 and 1 | |
| depth = (depth - min_depth) / (max_depth - min_depth) | |
| depth = np.clip(depth, 0, 1) | |
| # Use the matplotlib colormap to convert the depth to an RGB image | |
| cmap = plt.get_cmap(cmap) | |
| depth_image = (cmap(depth) * 255).astype(np.uint8) | |
| # Convert the depth image to a PIL image | |
| depth_image = Image.fromarray(depth_image) | |
| return depth_image |