czq142857/implicit-decoder

how to rot the shape in hdf5

tianyilt opened this issue · 6 comments

thank you for your excellent work. i have succeed in run it in my own binvox dataset.It is really pretty in Interpolation.

but when i try to rot the 3D shape in hdf5, 1 can't solve the following problem:

  1. the hdf5 structure:
    data_points16 (3,4096,3)
    data_values16(3,4096,1)
    data_points32 =(3,8192,3)
    data_values32 =(3,8192,1)
    data_points64 =(3,32768,3)
    data_values64 =(3,32768,1)
    data_voxels =(3,64.64,64.1)

why the last dim of data_points is 3
why the second dim of data_points32 is 8192,which is 161616*2

  1. rot shape method
    i try to rot shape by numpy.rot90, it work in data_voxels.
    to make sure the data set is all rot, i write the following function:
def visualize_voxels(voxels, thres=0.5, output_dir='voxel_list', filename='out'):
    import mcubes
    """

    :param voxels: ndarray shape like (64,64,64,1) bool value
    :param thres: 
    :param output_dir: 
    :return: 
    """
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    voxels = np.squeeze(voxels)  # (64,64,64,1)->(64,64,64)
    model_float = voxels
    vertices, triangles = mcubes.marching_cubes(model_float, thres)
    mcubes.export_mesh(vertices, triangles, os.path.join(output_dir, filename + ".dae"))
def visualize_voxels_batch(voxels_batch, thres=0.5, output_dir='voxel_list'):
    import mcubes
    """

    :param voxels: ndarray shape like (64,64,64,1) bool value
    :param thres: 
    :param output_dir: 
    :return: 
    """
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    for t in range(voxels_batch.shape[0]):
        model_float = np.squeeze(voxels_batch[t])  # (64,64,64,1)->(64,64,64)
        vertices, triangles = mcubes.marching_cubes(model_float, thres)
        mcubes.export_mesh(vertices, triangles, os.path.join(output_dir, str(t) + ".dae"))

def rot_voxel2zheng(voxel_batch):
    return np.flip(np.rot90(voxel_batch,k=1,axes=(2,3)),axis=2)
def rot_pointorvalue2zheng(points_batch):
    d=round(points_batch.shape[1]**(1/3))
    points_batch = points_batch.reshape([points_batch.shape[0],d,d,d,points_batch.shape[-1]])#(num,d**3,3)->(num,d,d,d,3)
    points_batch = np.flip(np.rot90(points_batch,k=1,axes=(2,3)),axis=2)
    return points_batch.reshape(points_batch.shape[0],d**3,points_batch.shape[-1])

Because i can't understand the problem 1, I have no idea how to adjust the data_points and points and values of 32dims.

  1. other efforts in binvox
    after i find it hard to adjust hdf5 file. i try to adjust binvox.
    i use the tool in https://github.com/dimatura/binvox-rw-py
    but i failed in

UnicodeEncodeError: 'gbk' codec can't encode character '\x80' in position 0: illegal multibyte sequence

i have add my question to related issue

data_points32 =(N,8192,3)

This means we sample only 8192 points on 32x32x32 voxels. Since each point has 3 coordinates x,y,z, the last dim of data_points is 3.

If you want to rotate the shape, simply multiply "data_points" with a rotation matrix. Remember that the last dim of data_points is point coordinates (x,y,z). You do not need to change "data_values".

You don't have to change the code in binvox_rw.py.

Best,
Zhiqin

thank you very much! It help me a lot.

does the coordinate of a point in a shape in this hdf5 is the same as the point in binvox file? I want to check the location of point (0,0,0) and the direction of x,y,z axis.

Yes. For example, the corners of a 64x64x64 voxel model are (0,0,0), (63,63,63), ...

Best,
Zhiqin

Thank you

here is my code for rotting. Thanks sincerely for author's help and instruction.'
The Linear transformation for rotation is found by test.
Used function

  • np.flip
    to flip voxel
  • np.rot90
    to rot voxel
  • np.matmul
    used to rot point pair
  • np.apply_along_axis
    used to rot point pair
import numpy as np
def rot_voxel2zheng(voxel_batch):
    return np.flip(np.rot90(np.rot90(voxel_batch, k=1, axes=(2, 3)), k=3, axes=(1, 2)),
                   axis=3)  # 先yz转一个90度,后xy转三个90度,然后关于z轴对称
def rotx(points, len):
    """
    rot 90 degree based on x axis
    :param points: points in hdf5, shape like (model_num, sample_points_num, 3)
    we should adjust the last dim, which is the (x,y,z) coordination of a sample point
    :param len:the size of voxel like 16 32 64
    :return: ndarray,the same shape as points,(x,y,z)<-(x,y,z)*rotation_matrix'+b_matrix
    """
    new_points = np.copy(points)  # 这里不能浅拷贝,不然rot完原来的points也变了
    for model_num, model in enumerate(points):
        for sample_points_num, sample_point in enumerate(model):
            rotation_matrix = np.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]])
            b_matrix = np.array([0, len - 1, 0])
            new_points[model_num, sample_points_num, :] = np.matmul(sample_point,
                                                                    rotation_matrix.transpose()) + b_matrix

    # np.apply_along_axis(linear_transform_for_1dim, axis=2, arr=new_points)
    return new_points
def rotchair2zheng(points, len):
    """
    rot chair 2 demand direction
    :param points: points in hdf5, shape like (model_num, sample_points_num, 3)
    we should adjust the last dim, which is the (x,y,z) coordination of a sample point in a unit cubic
    (x,y,z) vary from (0,0,0) to (len-1, len-1, len-1)
    :param len:the size of voxel like 16 32 64
    :return: ndarray,the same shape as points,(x,y,z)<-(x,y,z)*rotation_matrix'+b_matrix
    """

    def linear_transform_for_1dim(a, len=len):
        """

        :param a: like points[model_num, sample_points_num, :]
        :return: (x,y,z)<-(x,y,z)*rotation_matrix'+b_matrix
        """
        # len=16
        rotation_matrix1 = np.array([[1, 0, 0], [0, 0, 1], [0, -1, 0]])
        b_matrix1 = np.array([0, 0, len - 1])
        a = np.matmul(a, rotation_matrix1.transpose()) + b_matrix1

        rotation_matrix2 = np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]])
        b_matrix2 = np.array([len - 1, 0, 0])
        a = np.matmul(a, rotation_matrix2.transpose()) + b_matrix2

        rotation_matrix3 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, -1]])
        b_matrix3 = np.array([0, 0, len - 1])
        a = np.matmul(a, rotation_matrix3.transpose()) + b_matrix3

        rotation_matrix4 = np.array([[-1, 0, 0], [0, 1, 0], [0, 0, 1]])
        b_matrix4 = np.array([len - 1, 0, 0])
        a = np.matmul(a, rotation_matrix4.transpose()) + b_matrix4  # 关于x轴对称
        return a

    new_points = np.copy(points)  # 这里不能浅拷贝,不然rot完原来的points也变了
    new_points = np.apply_along_axis(linear_transform_for_1dim, axis=2, arr=new_points)

    return new_points
if __name__ == "__main__":
    f2 = h5py.File('       .hdf5', 'r')
    f2lb = 904
    f2_points16 = rotchair2zheng(f2['points_16'][:f2lb], 16)
    f2_points32 = rotchair2zheng(f2['points_32'][:f2lb], 32)
    f2_points64 = rotchair2zheng(f2['points_64'][:f2lb], 64)
    f2_values16 = f2['values_16'][:f2lb]
    f2_values32 = f2['values_32'][:f2lb]
    f2_values64 = f2['values_64'][:f2lb]
    f2_voxels = rot_voxel2zheng2(f2['voxels'][:f2lb])

    data_points16 = f2_points16
    data_values16 = f2_values16
    data_points32 = f2_points32
    data_values32 = f2_values32
    data_points64 = f2_points64
    data_values64 = f2_values64
    data_voxels = f2_voxels

    f3 = h5py.File('      .hdf5', 'w')
    f3['points_16'] = data_points16
    f3['values_16'] = data_values16
    f3['points_32'] = data_points32
    f3['values_32'] = data_values32
    f3['points_64'] = data_points64
    f3['values_64'] = data_values64
    f3['voxels'] = data_voxels
    f3.close()