mirror of
https://github.com/wassname/PointCNN.git
synced 2026-08-20 12:00:21 +08:00
146 lines
5.4 KiB
Python
146 lines
5.4 KiB
Python
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))
|