File size: 3,407 Bytes
43ca9e0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import numpy as np
import open3d_pycg as o3d
import os
import torch
from sklearn.decomposition import PCA


def merge_meshes(mesh_list):
    merged = o3d.geometry.TriangleMesh()
    v_offset = 0

    for mesh in mesh_list:
        vertices = np.asarray(mesh.vertices)
        triangles = np.asarray(mesh.triangles) + v_offset

        merged.vertices.extend(o3d.utility.Vector3dVector(vertices))
        merged.triangles.extend(o3d.utility.Vector3iVector(triangles))

        v_offset += len(vertices)

    return merged


def voxelgrid_to_open3d(voxels: np.ndarray, threshold=0.5):
    if len(voxels.shape) > 3:
        C, D, H, W = voxels.shape
        flat_feats = voxels.reshape(C, -1).transpose(1,0)
        pca = PCA(n_components=3)
        reduced = pca.fit_transform(flat_feats)
        # Compute feature norm and PCA color std

        # Normalize for RGB
        reduced -= reduced.min(0)
        reduced /= reduced.max(0) + 1e-6

        # Compute norms and color std
        norms = np.linalg.norm(flat_feats, axis=1)
        color_std = np.std(reduced, axis=1)

        # Filter: active voxels with non-trivial color
        mask = (norms > threshold) & (color_std > 1e-3)

        # zz, yy, xx = np.meshgrid(np.arange(D), np.arange(H), np.arange(W), indexing='ij')
        xx, yy, zz = np.meshgrid(np.arange(D), np.arange(H), np.arange(W), indexing='ij')
        coords = np.stack([xx, yy, zz], axis=-1).reshape(-1, 3)
        valid_coords = coords[mask]
        valid_colors = reduced[mask]

        pcd = o3d.geometry.PointCloud()
        pcd.points = o3d.utility.Vector3dVector(valid_coords.astype(np.float32))
        pcd.colors = o3d.utility.Vector3dVector(valid_colors.astype(np.float32))
    else:
        coords = np.argwhere(voxels > threshold)
        pcd = o3d.geometry.PointCloud()
        pcd.points = o3d.utility.Vector3dVector(coords)
    return pcd


def save_voxelgrid_as_ply(voxels: np.ndarray, filename: str, threshold=0.5):
    pcd = voxelgrid_to_open3d(voxels, threshold)
    o3d.io.write_point_cloud(filename, pcd)


def voxelize_sq_francis(file_name):
    superquadric_mesh = o3d.io.read_triangle_mesh(file_name)
    vertices = np.clip(np.asarray(superquadric_mesh.vertices), -0.5 + 1e-6, 0.5 - 1e-6)
    superquadric_mesh.vertices = o3d.utility.Vector3dVector(vertices)
    theta = np.pi / 2
    #superquadric_mesh.rotate(R_x, center=(0, 0, 0))
    voxel_grid = o3d.geometry.VoxelGrid.create_from_triangle_mesh_within_bounds(
        superquadric_mesh, voxel_size=1/64, min_bound=(-0.5, -0.5, -0.5), max_bound=(0.5, 0.5, 0.5))
    
    vertices = np.array([voxel.grid_index for voxel in voxel_grid.get_voxels()])
    unique_points = np.unique(vertices, axis=0)
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(unique_points)
    o3d.io.write_point_cloud("merged_mesh_voxelized.ply", pcd)

    zeros = np.zeros((unique_points.shape[0], 1))
    unique_points_4d = np.hstack((zeros, unique_points))  # shape [N, 4]
    unique_points_4d_torch = torch.from_numpy(unique_points_4d).to(dtype=torch.int32, device='cpu')
    my_coords_orig = unique_points_4d_torch

    coords_dense = torch.ones(1, 1, 64, 64, 64).to(device='cpu', dtype=torch.float32) * 0.0
    for i in range(my_coords_orig.shape[0]):
      x, y, z = my_coords_orig[i, 1], my_coords_orig[i, 2], my_coords_orig[i, 3]
      coords_dense[0, 0, x, y, z] = 1.0
    return coords_dense