from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import h5py
import plyfile
import numpy as np
from matplotlib import cm
import scipy.spatial.distance as distance
def save_ply(points, filename, colors=None, normals=None):
vertex = np.array([tuple(p) for p in points], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
n = len(vertex)
desc = vertex.dtype.descr
if normals is not None:
vertex_normal = np.array([tuple(n) for n in normals], dtype=[('nx', 'f4'), ('ny', 'f4'), ('nz', 'f4')])
assert len(vertex_normal) == n
desc = desc + vertex_normal.dtype.descr
if colors is not None:
vertex_color = np.array([tuple(c * 255) for c in colors],
dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')])
assert len(vertex_color) == n
desc = desc + vertex_color.dtype.descr
vertex_all = np.empty(n, dtype=desc)
for prop in vertex.dtype.names:
vertex_all[prop] = vertex[prop]
if normals is not None:
for prop in vertex_normal.dtype.names:
vertex_all[prop] = vertex_normal[prop]
if colors is not None:
for prop in vertex_color.dtype.names:
vertex_all[prop] = vertex_color[prop]
ply = plyfile.PlyData([plyfile.PlyElement.describe(vertex_all, 'vertex')], text=False)
if not os.path.exists(os.path.dirname(filename)):
os.makedirs(os.path.dirname(filename))
ply.write(filename)
def save_ply_property(points, property, property_max, filename, cmap_name='Set1'):
point_num = points.shape[0]
colors = np.full(points.shape, 0.5)
cmap = cm.get_cmap(cmap_name)
for point_idx in range(point_num):
colors[point_idx] = cmap(property[point_idx] / property_max)[:3]
save_ply(points, filename, colors)
def save_ply_batch(points_batch, file_path, points_num=None):
batch_size = points_batch.shape[0]
if type(file_path) != list:
basename = os.path.splitext(file_path)[0]
ext = '.ply'
for batch_idx in range(batch_size):
point_num = points_batch.shape[1] if points_num is None else points_num[batch_idx]
if type(file_path) == list:
save_ply(points_batch[batch_idx][:point_num], file_path[batch_idx])
else:
save_ply(points_batch[batch_idx][:point_num], '%s_%04d%s' % (basename, batch_idx, ext))
def save_ply_property_batch(points_batch, property_batch, file_path, points_num=None, property_max=None,
cmap_name='Set1'):
batch_size = points_batch.shape[0]
if type(file_path) != list:
basename = os.path.splitext(file_path)[0]
ext = '.ply'
property_max = np.max(property_batch) if property_max is None else property_max
for batch_idx in range(batch_size):
point_num = points_batch.shape[1] if points_num is None else points_num[batch_idx]
if type(file_path) == list:
save_ply_property(points_batch[batch_idx][:point_num], property_batch[batch_idx][:point_num],
property_max, file_path[batch_idx], cmap_name)
else:
save_ply_property(points_batch[batch_idx][:point_num], property_batch[batch_idx][:point_num],
property_max, '%s_%04d%s' % (basename, batch_idx, ext), cmap_name)
def save_ply_point_with_normal(data_sample, folder):
for idx, sample in enumerate(data_sample):
filename_pts = os.path.join(folder, '{:08d}.ply'.format(idx))
save_ply(sample[..., :3], filename_pts, normals=sample[..., 3:])
def grouped_shuffle(inputs):
for idx in range(len(inputs) - 1):
assert (len(inputs[idx]) == len(inputs[idx + 1]))
shuffle_indices = np.arange(inputs[0].shape[0])
np.random.shuffle(shuffle_indices)
outputs = []
for idx in range(len(inputs)):
outputs.append(inputs[idx][shuffle_indices, ...])
return outputs
def load_cls(filelist):
points = []
labels = []
folder = os.path.dirname(filelist)
for line in open(filelist):
filename = os.path.basename(line.rstrip())
data = h5py.File(os.path.join(folder, filename))
if 'normal' in data:
points.append(np.concatenate([data['data'][...], data['data'][...]], axis=-1).astype(np.float32))
else:
points.append(data['data'][...].astype(np.float32))
labels.append(np.squeeze(data['label'][:]).astype(np.int32))
return (np.concatenate(points, axis=0),
np.concatenate(labels, axis=0))
def load_cls_train_val(filelist, filelist_val):
data_train, label_train = grouped_shuffle(load_cls(filelist))
data_val, label_val = load_cls(filelist_val)
return data_train, label_train, data_val, label_val
def load_seg(filelist):
points = []
labels = []
point_nums = []
labels_seg = []
folder = os.path.dirname(filelist)
for line in open(filelist):
filename = os.path.basename(line.rstrip())
data = h5py.File(os.path.join(folder, filename))
points.append(data['data'][...].astype(np.float32))
labels.append(data['label'][...].astype(np.int32))
point_nums.append(data['data_num'][...].astype(np.int32))
labels_seg.append(data['label_seg'][...].astype(np.int32))
return (np.concatenate(points, axis=0),
np.concatenate(labels, axis=0),
np.concatenate(point_nums, axis=0),
np.concatenate(labels_seg, axis=0))