-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathdata_utils.py
More file actions
118 lines (95 loc) · 4.26 KB
/
Copy pathdata_utils.py
File metadata and controls
118 lines (95 loc) · 4.26 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import os
import numpy as np
import h5py
def read_h5_geo(filedir):
pc = h5py.File(filedir, 'r')['data'][:]
coords = pc[:,0:3].astype('int')
return coords
def write_h5_geo(filedir, coords):
data = coords.astype('uint8')
with h5py.File(filedir, 'w') as h:
h.create_dataset('data', data=data, shape=data.shape)
return
def read_ply_ascii_geo(filedir):
files = open(filedir)
data = []
for i, line in enumerate(files):
wordslist = line.split(' ')
try:
line_values = []
for i, v in enumerate(wordslist):
if v == '\n': continue
line_values.append(float(v))
except ValueError: continue
data.append(line_values)
data = np.array(data)
coords = data[:,0:3].astype('int')
return coords
def write_ply_ascii_geo(filedir, coords):
if os.path.exists(filedir): os.system('rm '+filedir)
f = open(filedir,'a+')
f.writelines(['ply\n','format ascii 1.0\n'])
f.write('element vertex '+str(coords.shape[0])+'\n')
f.writelines(['property float x\n','property float y\n','property float z\n'])
f.write('end_header\n')
coords = coords.astype('int')
for p in coords:
f.writelines([str(p[0]), ' ', str(p[1]), ' ',str(p[2]), '\n'])
f.close()
return
###########################################################################################################
import torch
import MinkowskiEngine as ME
def array2vector(array, step):
"""ravel 2D array with multi-channel to one 1D vector by sum each channel with different step.
"""
array, step = array.long().cpu(), step.long().cpu()
vector = sum([array[:,i]*(step**i) for i in range(array.shape[-1])])
return vector
def isin(data, ground_truth):
""" Input data and ground_truth are torch tensor of shape [N, D].
Returns a boolean vector of the same length as `data` that is True
where an element of `data` is in `ground_truth` and False otherwise.
"""
device = data.device
data, ground_truth = data.cpu(), ground_truth.cpu()
step = torch.max(data.max(), ground_truth.max()) + 1
data = array2vector(data, step)
ground_truth = array2vector(ground_truth, step)
mask = np.isin(data.cpu().numpy(), ground_truth.cpu().numpy())
return torch.Tensor(mask).bool().to(device)
def istopk(data, nums, rho=1.0):
""" Input data is sparse tensor and nums is a list of shape [batch_size].
Returns a boolean vector of the same length as `data` that is True
where an element of `data` is the top k (=nums*rho) value and False otherwise.
"""
mask = torch.zeros(len(data), dtype=torch.bool)
row_indices_per_batch = data._batchwise_row_indices
for row_indices, N in zip(row_indices_per_batch, nums):
k = int(min(len(row_indices), N*rho))
_, indices = torch.topk(data.F[row_indices].squeeze().detach().cpu(), k)# must CPU.
mask[row_indices[indices]]=True
return mask.bool().to(data.device)
def sort_spare_tensor(sparse_tensor):
""" Sort points in sparse tensor according to their coordinates.
"""
indices_sort = np.argsort(array2vector(sparse_tensor.C.cpu(),
sparse_tensor.C.cpu().max()+1))
sparse_tensor_sort = ME.SparseTensor(features=sparse_tensor.F[indices_sort],
coordinates=sparse_tensor.C[indices_sort],
tensor_stride=sparse_tensor.tensor_stride[0],
device=sparse_tensor.device)
return sparse_tensor_sort
def load_sparse_tensor(filedir, device):
coords = torch.tensor(read_ply_ascii_geo(filedir)).int()
feats = torch.ones((len(coords),1)).float()
# coords, feats = ME.utils.sparse_quantize(coordinates=coords, features=feats, quantization_size=1)
coords, feats = ME.utils.sparse_collate([coords], [feats])
x = ME.SparseTensor(features=feats, coordinates=coords, tensor_stride=1, device=device)
return x
def scale_sparse_tensor(x, factor):
coords = (x.C[:,1:]*factor).round().int()
feats = torch.ones((len(coords),1)).float()
coords, feats = ME.utils.sparse_collate([coords], [feats])
x = ME.SparseTensor(features=feats, coordinates=coords, tensor_stride=1, device=x.device)
return x