openpoints 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. openpoints/__init__.py +3 -0
  2. openpoints/cpp/__init__.py +6 -0
  3. openpoints/cpp/chamfer_dist/__init__.py +110 -0
  4. openpoints/cpp/chamfer_dist/setup.py +19 -0
  5. openpoints/cpp/chamfer_dist/test.py +34 -0
  6. openpoints/cpp/emd/__init__.py +3 -0
  7. openpoints/cpp/emd/emd.py +88 -0
  8. openpoints/cpp/emd/setup.py +27 -0
  9. openpoints/cpp/emd/test_emd_loss.py +45 -0
  10. openpoints/cpp/pointnet2_batch/__init__.py +24 -0
  11. openpoints/cpp/pointnet2_batch/setup.py +23 -0
  12. openpoints/cpp/pointops/__init__.py +0 -0
  13. openpoints/cpp/pointops/functions/__init__.py +0 -0
  14. openpoints/cpp/pointops/functions/pointops.py +314 -0
  15. openpoints/cpp/pointops/setup.py +37 -0
  16. openpoints/cpp/pointops/src/__init__.py +0 -0
  17. openpoints/dataset/__init__.py +10 -0
  18. openpoints/dataset/atom3d/__init__.py +1 -0
  19. openpoints/dataset/atom3d/psr.py +38 -0
  20. openpoints/dataset/build.py +98 -0
  21. openpoints/dataset/data_util.py +192 -0
  22. openpoints/dataset/datalist.py +67 -0
  23. openpoints/dataset/dataset_base.py +96 -0
  24. openpoints/dataset/graph_dataset/__init__.py +3 -0
  25. openpoints/dataset/graph_dataset/graph_dataset.py +93 -0
  26. openpoints/dataset/graph_dataset/stack_with_pad.py +91 -0
  27. openpoints/dataset/graph_dataset/structural_dataset.py +73 -0
  28. openpoints/dataset/graph_dataset/svd_encodings_dataset.py +110 -0
  29. openpoints/dataset/grid_sample.py +21 -0
  30. openpoints/dataset/matterport3d/__init__.py +1 -0
  31. openpoints/dataset/matterport3d/category_mapping.tsv +1660 -0
  32. openpoints/dataset/matterport3d/matterport3d.py +210 -0
  33. openpoints/dataset/matterport3d/matterport3d_dataprocessing.py +105 -0
  34. openpoints/dataset/modelnet/__init__.py +3 -0
  35. openpoints/dataset/modelnet/modelnet40_normal_resampled_loader.py +124 -0
  36. openpoints/dataset/modelnet/modelnet40_ply_2048_loader.py +160 -0
  37. openpoints/dataset/molhiv/__init__.py +1 -0
  38. openpoints/dataset/molhiv/data.py +59 -0
  39. openpoints/dataset/molpcba/__init__.py +1 -0
  40. openpoints/dataset/molpcba/data.py +59 -0
  41. openpoints/dataset/parsers/__init__.py +1 -0
  42. openpoints/dataset/parsers/class_map.py +19 -0
  43. openpoints/dataset/parsers/constants.py +1 -0
  44. openpoints/dataset/parsers/parser.py +17 -0
  45. openpoints/dataset/parsers/parser_factory.py +29 -0
  46. openpoints/dataset/parsers/parser_image_folder.py +69 -0
  47. openpoints/dataset/parsers/parser_image_in_tar.py +222 -0
  48. openpoints/dataset/parsers/parser_image_tar.py +72 -0
  49. openpoints/dataset/parsers/parser_tfds.py +297 -0
  50. openpoints/dataset/pcqm4m/__init__.py +1 -0
  51. openpoints/dataset/pcqm4m/data.py +62 -0
  52. openpoints/dataset/pcqm4mv2/__init__.py +1 -0
  53. openpoints/dataset/pcqm4mv2/data.py +87 -0
  54. openpoints/dataset/s3dis/__init__.py +2 -0
  55. openpoints/dataset/s3dis/s3dis.py +156 -0
  56. openpoints/dataset/s3dis/s3dis_block.py +96 -0
  57. openpoints/dataset/s3dis/s3dis_sphere.py +349 -0
  58. openpoints/dataset/scannetv2/__init__.py +1 -0
  59. openpoints/dataset/scannetv2/scannet.py +176 -0
  60. openpoints/dataset/scanobjectnn/__init__.py +3 -0
  61. openpoints/dataset/scanobjectnn/scanobjectnn.py +110 -0
  62. openpoints/dataset/semantic_kitti/__init__.py +1 -0
  63. openpoints/dataset/semantic_kitti/helper_tool.py +286 -0
  64. openpoints/dataset/semantic_kitti/label_mapping.yaml +211 -0
  65. openpoints/dataset/semantic_kitti/semantickitti.py +229 -0
  66. openpoints/dataset/semantic_kitti/utils/meta/anno_paths.txt +272 -0
  67. openpoints/dataset/semantic_kitti/utils/meta/class_names.txt +13 -0
  68. openpoints/dataset/semantic_kitti/utils/semantic-kitti.yaml +211 -0
  69. openpoints/dataset/shapenet/__init__.py +1 -0
  70. openpoints/dataset/shapenet/shapenet55.py +76 -0
  71. openpoints/dataset/shapenet/shapenetpart.py +121 -0
  72. openpoints/dataset/shapenetpart/__init__.py +1 -0
  73. openpoints/dataset/shapenetpart/shapenet55.py +75 -0
  74. openpoints/dataset/shapenetpart/shapenetpart.py +388 -0
  75. openpoints/dataset/vis2d.py +17 -0
  76. openpoints/dataset/vis3d.py +153 -0
  77. openpoints/loss/__init__.py +3 -0
  78. openpoints/loss/build.py +281 -0
  79. openpoints/loss/cross_entropy.py +38 -0
  80. openpoints/loss/distill_loss.py +76 -0
  81. openpoints/models/__init__.py +10 -0
  82. openpoints/models/backbone/Stratified_transformer.py +558 -0
  83. openpoints/models/backbone/__init__.py +11 -0
  84. openpoints/models/backbone/baafnet.py +527 -0
  85. openpoints/models/backbone/ball_dgcnn.py +123 -0
  86. openpoints/models/backbone/curvenet.py +793 -0
  87. openpoints/models/backbone/debug_invvit.py +114 -0
  88. openpoints/models/backbone/deepgcn.py +143 -0
  89. openpoints/models/backbone/dgcnn.py +119 -0
  90. openpoints/models/backbone/graphvit3d.py +134 -0
  91. openpoints/models/backbone/grouppointnet.py +100 -0
  92. openpoints/models/backbone/pct.py +163 -0
  93. openpoints/models/backbone/pointmlp.py +417 -0
  94. openpoints/models/backbone/pointnet.py +199 -0
  95. openpoints/models/backbone/pointnetv2.py +511 -0
  96. openpoints/models/backbone/pointnext.py +663 -0
  97. openpoints/models/backbone/pointnextPyG.py +555 -0
  98. openpoints/models/backbone/pointtransformer.py +293 -0
  99. openpoints/models/backbone/pointvector.py +853 -0
  100. openpoints/models/backbone/pointvit.py +392 -0
  101. openpoints/models/backbone/pointvit_inv.py +942 -0
  102. openpoints/models/backbone/pointvit_inv_old.py +784 -0
  103. openpoints/models/backbone/randlenet.py +318 -0
  104. openpoints/models/backbone/resnet.py +342 -0
  105. openpoints/models/backbone/simpleview.py +153 -0
  106. openpoints/models/backbone/simpleview_util.py +292 -0
  107. openpoints/models/build.py +13 -0
  108. openpoints/models/classification/__init__.py +5 -0
  109. openpoints/models/classification/cls_base.py +136 -0
  110. openpoints/models/classification/point_bert.py +154 -0
  111. openpoints/models/layers/__init__.py +14 -0
  112. openpoints/models/layers/activation.py +57 -0
  113. openpoints/models/layers/attention.py +103 -0
  114. openpoints/models/layers/conv.py +167 -0
  115. openpoints/models/layers/drop.py +164 -0
  116. openpoints/models/layers/graph_conv.py +122 -0
  117. openpoints/models/layers/group.py +415 -0
  118. openpoints/models/layers/group_embed.py +286 -0
  119. openpoints/models/layers/helpers.py +43 -0
  120. openpoints/models/layers/kmeans.py +119 -0
  121. openpoints/models/layers/knn.py +110 -0
  122. openpoints/models/layers/local_aggregation.py +286 -0
  123. openpoints/models/layers/mlp.py +129 -0
  124. openpoints/models/layers/norm.py +106 -0
  125. openpoints/models/layers/padding.py +56 -0
  126. openpoints/models/layers/patch_embed.py +37 -0
  127. openpoints/models/layers/registry.py +168 -0
  128. openpoints/models/layers/subsample.py +185 -0
  129. openpoints/models/layers/upsampling.py +106 -0
  130. openpoints/models/layers/weight_init.py +89 -0
  131. openpoints/models/reconstruction/__init__.py +8 -0
  132. openpoints/models/reconstruction/base_recontruct.py +216 -0
  133. openpoints/models/reconstruction/maskedpoint.py +116 -0
  134. openpoints/models/reconstruction/maskedpointgroup.py +168 -0
  135. openpoints/models/reconstruction/maskedpointvit.py +253 -0
  136. openpoints/models/reconstruction/nodeshuffle.py +11 -0
  137. openpoints/models/registry.py +149 -0
  138. openpoints/models/segmentation/__init__.py +6 -0
  139. openpoints/models/segmentation/base_seg.py +278 -0
  140. openpoints/models/segmentation/vit_seg.py +126 -0
  141. openpoints/optim/__init__.py +15 -0
  142. openpoints/optim/adabelief.py +201 -0
  143. openpoints/optim/adafactor.py +167 -0
  144. openpoints/optim/adahessian.py +156 -0
  145. openpoints/optim/adamp.py +105 -0
  146. openpoints/optim/adamw.py +122 -0
  147. openpoints/optim/lamb.py +192 -0
  148. openpoints/optim/lars.py +135 -0
  149. openpoints/optim/lookahead.py +61 -0
  150. openpoints/optim/madgrad.py +184 -0
  151. openpoints/optim/nadam.py +92 -0
  152. openpoints/optim/nvnovograd.py +120 -0
  153. openpoints/optim/optim_factory.py +306 -0
  154. openpoints/optim/radam.py +89 -0
  155. openpoints/optim/rmsprop_tf.py +139 -0
  156. openpoints/optim/sgdp.py +70 -0
  157. openpoints/scheduler/__init__.py +8 -0
  158. openpoints/scheduler/cosine_lr.py +124 -0
  159. openpoints/scheduler/multistep_lr.py +65 -0
  160. openpoints/scheduler/plateau_lr.py +113 -0
  161. openpoints/scheduler/poly_lr.py +116 -0
  162. openpoints/scheduler/scheduler.py +110 -0
  163. openpoints/scheduler/scheduler_factory.py +118 -0
  164. openpoints/scheduler/step_lr.py +65 -0
  165. openpoints/scheduler/tanh_lr.py +117 -0
  166. openpoints/transforms/__init__.py +7 -0
  167. openpoints/transforms/point_transform_cpu.py +332 -0
  168. openpoints/transforms/point_transformer_gpu.py +764 -0
  169. openpoints/transforms/transforms_factory.py +60 -0
  170. openpoints/utils/__init__.py +8 -0
  171. openpoints/utils/ckpt_util.py +438 -0
  172. openpoints/utils/config.py +113 -0
  173. openpoints/utils/dist_utils.py +54 -0
  174. openpoints/utils/logger.py +170 -0
  175. openpoints/utils/metrics.py +311 -0
  176. openpoints/utils/random.py +16 -0
  177. openpoints/utils/registry.py +294 -0
  178. openpoints/utils/str2bool.py +11 -0
  179. openpoints/utils/wandb.py +88 -0
  180. openpoints-0.1.0.dist-info/METADATA +150 -0
  181. openpoints-0.1.0.dist-info/RECORD +184 -0
  182. openpoints-0.1.0.dist-info/WHEEL +5 -0
  183. openpoints-0.1.0.dist-info/licenses/LICENSE +21 -0
  184. openpoints-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,96 @@
1
+ import torch
2
+ import torch.utils.data as data
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+ # class S3DIS(data.Dataset):
12
+ # r"""The (pre-processed) Stanford Large-Scale 3D Indoor Spaces dataset from
13
+ # the `"3D Semantic Parsing of Large-Scale Indoor Spaces"
14
+ # <https://openaccess.thecvf.com/content_cvpr_2016/papers/Armeni_3D_Semantic_Parsing_CVPR_2016_paper.pdf>`_
15
+ # paper, containing point clouds of six large-scale indoor parts in three
16
+ # buildings with 12 semantic elements (and one clutter class).
17
+
18
+ # Args:
19
+ # root (string): Root directory where the dataset should be saved.
20
+ # test_area (int, optional): Which area to use for testing (1-6).
21
+ # (default: :obj:`6`)
22
+ # train (bool, optional): If :obj:`True`, loads the training dataset,
23
+ # otherwise the test dataset. (default: :obj:`True`)
24
+ # transform (callable, optional): A function/transform that takes in an
25
+ # :obj:`torch_geometric.data.Data` object and returns a transformed
26
+ # version. The data object will be transformed before every access.
27
+ # (default: :obj:`None`)
28
+ # pre_transform (callable, optional): A function/transform that takes in
29
+ # an :obj:`torch_geometric.data.Data` object and returns a
30
+ # transformed version. The data object will be transformed before
31
+ # being saved to disk. (default: :obj:`None`)
32
+ # pre_filter (callable, optional): A function that takes in an
33
+ # :obj:`torch_geometric.data.Data` object and returns a boolean
34
+ # value, indicating whether the data object should be included in the
35
+ # final dataset. (default: :obj:`None`)
36
+ # """
37
+
38
+ # url = ('https://shapenet.cs.stanford.edu/media/'
39
+ # 'indoor3d_sem_seg_hdf5_data.zip')
40
+
41
+ # def __init__(self, root, test_area=6, train=True, transform=None,
42
+ # pre_transform=None, pre_filter=None):
43
+ # assert test_area >= 1 and test_area <= 6
44
+ # self.test_area = test_area
45
+ # super().__init__(root, transform, pre_transform, pre_filter)
46
+ # path = self.processed_paths[0] if train else self.processed_paths[1]
47
+ # self.data, self.slices = torch.load(path)
48
+
49
+ # @property
50
+ # def raw_file_names(self):
51
+ # return ['all_files.txt', 'room_filelist.txt']
52
+
53
+ # @property
54
+ # def processed_file_names(self):
55
+ # return [f'{split}_{self.test_area}.pt' for split in ['train', 'test']]
56
+
57
+ # def download(self):
58
+ # path = download_url(self.url, self.root)
59
+ # extract_zip(path, self.root)
60
+ # os.unlink(path)
61
+ # shutil.rmtree(self.raw_dir)
62
+ # name = self.url.split('/')[-1].split('.')[0]
63
+ # os.rename(osp.join(self.root, name), self.raw_dir)
64
+
65
+ # def process(self):
66
+ # import h5py
67
+
68
+ # with open(self.raw_paths[0], 'r') as f:
69
+ # filenames = [x.split('/')[-1] for x in f.read().split('\n')[:-1]]
70
+
71
+ # with open(self.raw_paths[1], 'r') as f:
72
+ # rooms = f.read().split('\n')[:-1]
73
+
74
+ # xs, ys = [], []
75
+ # for filename in filenames:
76
+ # f = h5py.File(osp.join(self.raw_dir, filename))
77
+ # xs += torch.from_numpy(f['data'][:]).unbind(0)
78
+ # ys += torch.from_numpy(f['label'][:]).to(torch.long).unbind(0)
79
+
80
+ # test_area = f'Area_{self.test_area}'
81
+ # train_data_list, test_data_list = [], []
82
+ # for i, (x, y) in enumerate(zip(xs, ys)):
83
+ # data = Data(pos=x[:, :3], x=x[:, 3:], y=y)
84
+
85
+ # if self.pre_filter is not None and not self.pre_filter(data):
86
+ # continue
87
+ # if self.pre_transform is not None:
88
+ # data = self.pre_transform(data)
89
+
90
+ # if test_area not in rooms[i]:
91
+ # train_data_list.append(data)
92
+ # else:
93
+ # test_data_list.append(data)
94
+
95
+ # torch.save(self.collate(train_data_list), self.processed_paths[0])
96
+ # torch.save(self.collate(test_data_list), self.processed_paths[1])
@@ -0,0 +1,349 @@
1
+ import torch
2
+ import torch.utils.data as data
3
+ import numpy as np
4
+ import os
5
+ import pickle
6
+ from sklearn.neighbors import KDTree
7
+ from ..build import DATASETS
8
+ from ..data_util import crop_pc, voxelize
9
+ from tqdm import tqdm
10
+ import logging
11
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
12
+
13
+
14
+ @DATASETS.register_module()
15
+ class S3DISSphere(data.Dataset):
16
+ label_to_names = {0: 'ceiling',
17
+ 1: 'floor',
18
+ 2: 'wall',
19
+ 3: 'beam',
20
+ 4: 'column',
21
+ 5: 'window',
22
+ 6: 'door',
23
+ 7: 'chair',
24
+ 8: 'table',
25
+ 9: 'bookcase',
26
+ 10: 'sofa',
27
+ 11: 'board',
28
+ 12: 'clutter'}
29
+ name_to_label = {v: i for i, v in enumerate(label_to_names.values())}
30
+ classes = list(label_to_names.values())
31
+ color_mean = np.array([0.5136457, 0.49523646, 0.44921124])
32
+ color_std = np.array([0.18308958, 0.18415008, 0.19252081])
33
+ num_classes = 13
34
+ class2color = {'ceiling': [0, 255, 0],
35
+ 'floor': [0, 0, 255],
36
+ 'wall': [0, 255, 255],
37
+ 'beam': [255, 255, 0],
38
+ 'column': [255, 0, 255],
39
+ 'window': [100, 100, 255],
40
+ 'door': [200, 200, 100],
41
+ 'chair': [255, 0, 0],
42
+ 'table': [170, 120, 200],
43
+ 'bookcase': [10, 200, 100],
44
+ 'sofa': [200, 100, 100],
45
+ 'board': [200, 200, 200],
46
+ 'clutter': [50, 50, 50]}
47
+ cmap = np.array([*class2color.values()]).astype(np.uint8)
48
+ gravity_dim = 2
49
+ """S3DIS dataset for scene segmentation task.
50
+ Args:
51
+ voxel_size: grid length for pre-subsampling point clouds.
52
+ in_radius: radius of each input spheres.
53
+ num_points: max number of points for the input spheres.
54
+ num_steps: number of spheres for one training epoch.
55
+ num_epochs: total epochs.
56
+ data_root: root path for data.
57
+ transform: data transformations.
58
+ split: dataset split name.
59
+ """
60
+ def __init__(self, voxel_size,
61
+ in_radius, num_points, num_steps, num_epochs,
62
+ data_root=None,
63
+ transform=None,
64
+ split='train',
65
+ centering=False,
66
+ **kwargs):
67
+
68
+ super().__init__()
69
+ self.epoch = 0
70
+ self.transform = transform
71
+ self.voxel_size = voxel_size
72
+ self.in_radius = in_radius
73
+ self.num_points = num_points
74
+ self.num_steps = num_steps
75
+ self.num_epochs = num_epochs
76
+ self.centering = centering
77
+ self.data_root = data_root
78
+ self.train_clouds = ['Area_1', 'Area_2', 'Area_3', 'Area_4', 'Area_6']
79
+ self.val_clouds = ['Area_5']
80
+ self.split = split
81
+
82
+ if split == 'train':
83
+ cloud_names = self.train_clouds
84
+ else:
85
+ cloud_names = self.val_clouds
86
+
87
+ processed_dir = os.path.join(data_root, 'processed')
88
+ if not os.path.exists(processed_dir):
89
+ os.makedirs(processed_dir)
90
+
91
+ # prepare data
92
+ filename = os.path.join(
93
+ processed_dir, f'{split}_{voxel_size:.3f}_data.pkl')
94
+ if not os.path.exists(filename):
95
+ cloud_points_list, cloud_points_color_list, cloud_points_label_list = [], [], []
96
+ sub_cloud_points_list, sub_cloud_points_label_list, sub_cloud_points_color_list = [], [], []
97
+ sub_cloud_tree_list = []
98
+ cloud_rooms_list = []
99
+ for cloud_idx, cloud_name in enumerate(cloud_names):
100
+ # Pass if the cloud has already been computed
101
+ # Get rooms of the current cloud
102
+ cloud_folder = os.path.join(data_root,cloud_name)
103
+ room_folders = [os.path.join(cloud_folder, room) for room in os.listdir(cloud_folder) if
104
+ os.path.isdir(os.path.join(cloud_folder, room))]
105
+ # Initiate containers
106
+ cloud_points = np.empty((0, 3), dtype=np.float32)
107
+ cloud_colors = np.empty((0, 3), dtype=np.float32)
108
+ cloud_classes = np.empty((0, 1), dtype=np.int32)
109
+ cloud_room_split = [0]
110
+ # Loop over rooms
111
+ for i, room_folder in enumerate(room_folders):
112
+ print(
113
+ 'Cloud %s - Room %d/%d : %s' % (
114
+ cloud_name, i + 1, len(room_folders), room_folder.split('\\')[-1]))
115
+ room_npoints = []
116
+ for object_name in os.listdir(os.path.join(room_folder, 'Annotations')):
117
+ if object_name[-4:] == '.txt':
118
+ # Text file containing point of the object
119
+ object_file = os.path.join(room_folder, 'Annotations', object_name)
120
+ # Object class and ID
121
+ tmp = object_name[:-4].split('_')[0]
122
+ if tmp in self.name_to_label:
123
+ object_class = self.name_to_label[tmp]
124
+ elif tmp in ['stairs']:
125
+ object_class = self.name_to_label['clutter']
126
+ else:
127
+ raise ValueError(
128
+ 'Unknown object name: ' + str(tmp))
129
+ # Read object points and colors
130
+ try:
131
+ object_data = np.loadtxt(object_file)
132
+ except:
133
+ logging.info(f"error in reading file {object_file}")
134
+ # Stack all data
135
+ room_npoints.append(len(object_data))
136
+ cloud_points = np.vstack(
137
+ (cloud_points, object_data[:, 0:3].astype(np.float32)))
138
+ cloud_colors = np.vstack(
139
+ (cloud_colors, object_data[:, 3:6].astype(np.uint8)))
140
+ object_classes = np.full(
141
+ (object_data.shape[0], 1), object_class, dtype=np.int32)
142
+ cloud_classes = np.vstack(
143
+ (cloud_classes, object_classes))
144
+ cloud_room_split.append(cloud_room_split[-1]+sum(room_npoints))
145
+ cloud_points_list.append(cloud_points)
146
+ cloud_points_color_list.append(cloud_colors)
147
+ cloud_points_label_list.append(cloud_classes)
148
+ cloud_rooms_list.append(cloud_room_split)
149
+
150
+ sub_cloud_file = os.path.join(
151
+ processed_dir, cloud_name + f'_{voxel_size:.3f}_sub.pkl')
152
+ if os.path.exists(sub_cloud_file):
153
+ with open(sub_cloud_file, 'rb') as f:
154
+ sub_points, sub_colors, sub_labels, search_tree = pickle.load(
155
+ f)
156
+ else:
157
+ if voxel_size > 0:
158
+ sub_points, sub_colors, sub_labels = crop_pc(
159
+ cloud_points, cloud_colors, cloud_classes, voxel_size=voxel_size)
160
+ sub_labels = np.squeeze(sub_labels)
161
+ else:
162
+ sub_points = cloud_points
163
+ sub_colors = cloud_colors
164
+ sub_labels = cloud_classes
165
+
166
+ # Get chosen neighborhoods
167
+ search_tree = KDTree(sub_points, leaf_size=50)
168
+
169
+ with open(sub_cloud_file, 'wb') as f:
170
+ pickle.dump((sub_points, sub_colors,
171
+ sub_labels, search_tree), f)
172
+
173
+ sub_cloud_points_list.append(sub_points)
174
+ sub_cloud_points_color_list.append(sub_colors)
175
+ sub_cloud_points_label_list.append(sub_labels)
176
+ sub_cloud_tree_list.append(search_tree)
177
+
178
+ # original points
179
+ self.clouds_points = cloud_points_list
180
+ self.clouds_points_colors = cloud_points_color_list
181
+ self.clouds_points_labels = cloud_points_label_list
182
+ self.clouds_rooms = cloud_rooms_list
183
+
184
+ # grid subsampled points
185
+ self.sub_clouds_points = sub_cloud_points_list
186
+ self.sub_clouds_points_colors = sub_cloud_points_color_list
187
+ self.sub_clouds_points_labels = sub_cloud_points_label_list
188
+ self.sub_cloud_trees = sub_cloud_tree_list
189
+
190
+ with open(filename, 'wb') as f:
191
+ pickle.dump((self.clouds_points, self.clouds_points_colors, self.clouds_points_labels, self.clouds_rooms,
192
+ self.sub_clouds_points, self.sub_clouds_points_colors, self.sub_clouds_points_labels,
193
+ self.sub_cloud_trees), f)
194
+ print(f"{filename} saved successfully")
195
+ else:
196
+ with open(filename, 'rb') as f:
197
+ (self.clouds_points, self.clouds_points_colors, self.clouds_points_labels,
198
+ self.clouds_rooms,
199
+ self.sub_clouds_points, self.sub_clouds_points_colors, self.sub_clouds_points_labels,
200
+ self.sub_cloud_trees) = pickle.load(f)
201
+ print(f"{filename} loaded successfully")
202
+
203
+ # prepare iteration indices
204
+ filename = os.path.join(processed_dir,
205
+ f'{split}_{voxel_size:.3f}_{self.num_epochs}_{self.num_steps}_iterinds.pkl')
206
+ if not os.path.exists(filename):
207
+ potentials = []
208
+ min_potentials = [] # self.sub_cloud_trees, the tree for the grid_subsampled area
209
+ for cloud_i, tree in enumerate(self.sub_cloud_trees):
210
+ print(f"{split}/{cloud_i} has {tree.data.shape[0]} points")
211
+ cur_potential = np.random.rand(tree.data.shape[0]) * 1e-3
212
+ potentials.append(cur_potential)
213
+ min_potentials.append(float(np.min(cur_potential)))
214
+ self.cloud_inds = []
215
+ self.point_inds = []
216
+ self.noise = []
217
+ for ep in tqdm(range(self.num_epochs)):
218
+ for st in range(self.num_steps):
219
+ # cloud_ind is the index for area in each split. for test, only 1 cloud.
220
+ cloud_ind = int(np.argmin(min_potentials))
221
+ point_ind = np.argmin(potentials[cloud_ind])
222
+ self.cloud_inds.append(cloud_ind)
223
+ self.point_inds.append(point_ind)
224
+ points = np.array(
225
+ self.sub_cloud_trees[cloud_ind].data, copy=False) # sub_points
226
+ center_point = points[point_ind, :].reshape(1, -1)
227
+ noise = np.random.normal(
228
+ scale=self.in_radius / 10, size=center_point.shape)
229
+ self.noise.append(noise)
230
+ pick_point = center_point + noise.astype(center_point.dtype)
231
+ # Indices of points in input region
232
+ query_inds = self.sub_cloud_trees[cloud_ind].query_radius(pick_point,
233
+ r=self.in_radius,
234
+ return_distance=True,
235
+ sort_results=True)[0][0]
236
+ cur_num_points = query_inds.shape[0]
237
+ if self.num_points < cur_num_points:
238
+ query_inds = query_inds[:self.num_points]
239
+ # Update potentials (Tuckey weights)
240
+ dists = np.sum(
241
+ np.square((points[query_inds] - pick_point).astype(np.float32)), axis=1)
242
+ tukeys = np.square(1 - dists / np.square(self.in_radius))
243
+ tukeys[dists > np.square(self.in_radius)] = 0
244
+ potentials[cloud_ind][query_inds] += tukeys
245
+ min_potentials[cloud_ind] = float(
246
+ np.min(potentials[cloud_ind]))
247
+ with open(filename, 'wb') as f:
248
+ pickle.dump((self.cloud_inds, self.point_inds, self.noise), f)
249
+ print(f"{filename} saved successfully")
250
+ else:
251
+ with open(filename, 'rb') as f:
252
+ self.cloud_inds, self.point_inds, self.noise = pickle.load(f)
253
+ print(f"{filename} loaded successfully")
254
+
255
+ # prepare validation projection inds
256
+ filename = os.path.join(
257
+ processed_dir, f'{split}_{voxel_size:.3f}_proj.pkl')
258
+ if not os.path.exists(filename):
259
+ proj_ind_list = []
260
+ for points, search_tree in zip(self.clouds_points, self.sub_cloud_trees):
261
+ # points: the original points. 700K points
262
+ # subcloud_trees: the tree of the subsampeld points. 500K points
263
+ # find the nearest point in the subsampled points for each point in the original points.
264
+ proj_inds = np.squeeze(search_tree.query(
265
+ points, return_distance=False))
266
+ proj_inds = proj_inds.astype(np.int32)
267
+ proj_ind_list.append(proj_inds)
268
+ self.projections = proj_ind_list
269
+ with open(filename, 'wb') as f:
270
+ pickle.dump(self.projections, f)
271
+ print(f"{filename} saved successfully")
272
+ else:
273
+ with open(filename, 'rb') as f:
274
+ self.projections = pickle.load(f)
275
+ print(f"{filename} loaded successfully")
276
+
277
+ def __getitem__(self, idx):
278
+ """
279
+ Returns:
280
+ pts: (N, 3), a point cloud.
281
+ mask: (N, ), 0/1 mask to distinguish padding points.
282
+ features: (input_features_dim, N), input points features.
283
+ pts_labels: (N), point label.
284
+ current_cloud_index: (1), cloud index.
285
+ input_inds: (N), the index of input points in point cloud.
286
+ """
287
+ cloud_ind = self.cloud_inds[idx + self.epoch * self.num_steps]
288
+ point_ind = self.point_inds[idx + self.epoch * self.num_steps]
289
+ noise = self.noise[idx + self.epoch * self.num_steps]
290
+ points = np.array(
291
+ self.sub_cloud_trees[cloud_ind].data, copy=False) # subpoints
292
+ center_point = points[point_ind, :].reshape(1, -1)
293
+ pick_point = center_point + noise.astype(center_point.dtype)
294
+ # Indices of points in input region
295
+ # the point index in the subsampled point tree.
296
+ query_inds = self.sub_cloud_trees[cloud_ind].query_radius(pick_point,
297
+ r=self.in_radius,
298
+ return_distance=True,
299
+ sort_results=True)[0][0]
300
+ # Number collected
301
+ cur_num_points = query_inds.shape[0]
302
+ if self.num_points < cur_num_points:
303
+ shuffle_choice = np.random.permutation(np.arange(self.num_points))
304
+ input_inds = query_inds[:self.num_points][shuffle_choice]
305
+ mask = torch.ones(self.num_points).type(torch.int32)
306
+ else:
307
+ shuffle_choice = np.random.permutation(np.arange(cur_num_points))
308
+ query_inds = query_inds[shuffle_choice]
309
+ padding_choice = np.random.choice(
310
+ cur_num_points, self.num_points - cur_num_points)
311
+ input_inds = np.hstack([query_inds, query_inds[padding_choice]])
312
+ mask = torch.zeros(self.num_points).type(torch.int32)
313
+ mask[:cur_num_points] = 1
314
+ # points: the whole point of an area (voxel downsampled).
315
+ # input_inds: the point index of the current area.
316
+ original_points = points[input_inds]
317
+ pts = (original_points - pick_point).astype(np.float32)
318
+ colors = self.sub_clouds_points_colors[cloud_ind][input_inds].astype(
319
+ np.float32)
320
+ labels = self.sub_clouds_points_labels[cloud_ind][input_inds].astype(
321
+ np.int64)
322
+ current_cloud_index = np.array(cloud_ind).astype(np.int64)
323
+
324
+ data = {'pos': pts,
325
+ 'x': colors,
326
+ 'y': labels,
327
+ 'mask': mask,
328
+ 'cloud_index': current_cloud_index,
329
+ 'input_inds': input_inds,
330
+ }
331
+ """ vis
332
+ from openpoints.dataset import vis_multi_points, vis_points
333
+ vis_multi_points([points, pts], [self.sub_clouds_points_colors[cloud_ind]/255., colors/255.])
334
+
335
+ import copy
336
+ old_data = copy.deepcopy(data)
337
+ if self.transform is not None:
338
+ data = self.transform(data)
339
+ vis_multi_points([old_data['pos'][:, :3], data['pos'][:, :3].numpy()], colors=[old_data['x'][:, :3]/255.,data['x'][:, :3].numpy()])
340
+ """
341
+ if self.transform is not None:
342
+ data = self.transform(data)
343
+
344
+ if 'heights' not in data.keys():
345
+ data['heights'] = torch.from_numpy(original_points[:, self.gravity_dim:self.gravity_dim+1].astype(np.float32))
346
+ return data
347
+
348
+ def __len__(self):
349
+ return self.num_steps
@@ -0,0 +1 @@
1
+ from .scannet import ScanNet
@@ -0,0 +1,176 @@
1
+ import os
2
+ import os.path as osp
3
+ import numpy as np
4
+ import torch
5
+ from torch.utils.data import Dataset
6
+ from ..build import DATASETS
7
+ from ..data_util import crop_pc, voxelize
8
+ from ...transforms.point_transform_cpu import PointsToTensor
9
+ import glob
10
+ from tqdm import tqdm
11
+ import logging
12
+ import pickle
13
+
14
+
15
+ VALID_CLASS_IDS = [
16
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33, 34, 36, 39
17
+ ]
18
+
19
+ SCANNET_COLOR_MAP = {
20
+ 0: (0., 0., 0.),
21
+ 1: (174., 199., 232.),
22
+ 2: (152., 223., 138.),
23
+ 3: (31., 119., 180.),
24
+ 4: (255., 187., 120.),
25
+ 5: (188., 189., 34.),
26
+ 6: (140., 86., 75.),
27
+ 7: (255., 152., 150.),
28
+ 8: (214., 39., 40.),
29
+ 9: (197., 176., 213.),
30
+ 10: (148., 103., 189.),
31
+ 11: (196., 156., 148.),
32
+ 12: (23., 190., 207.),
33
+ 14: (247., 182., 210.),
34
+ 15: (66., 188., 102.),
35
+ 16: (219., 219., 141.),
36
+ 17: (140., 57., 197.),
37
+ 18: (202., 185., 52.),
38
+ 19: (51., 176., 203.),
39
+ 20: (200., 54., 131.),
40
+ 21: (92., 193., 61.),
41
+ 22: (78., 71., 183.),
42
+ 23: (172., 114., 82.),
43
+ 24: (255., 127., 14.),
44
+ 25: (91., 163., 138.),
45
+ 26: (153., 98., 156.),
46
+ 27: (140., 153., 101.),
47
+ 28: (158., 218., 229.),
48
+ 29: (100., 125., 154.),
49
+ 30: (178., 127., 135.),
50
+ 32: (146., 111., 194.),
51
+ 33: (44., 160., 44.),
52
+ 34: (112., 128., 144.),
53
+ 35: (96., 207., 209.),
54
+ 36: (227., 119., 194.),
55
+ 37: (213., 92., 176.),
56
+ 38: (94., 106., 211.),
57
+ 39: (82., 84., 163.),
58
+ 40: (100., 85., 144.),
59
+ }
60
+
61
+
62
+
63
+ @DATASETS.register_module()
64
+ class ScanNet(Dataset):
65
+ num_classes = 20
66
+ classes = ['wall', 'floor', 'cabinet', 'bed', 'chair', 'sofa', 'table', 'door', 'window', 'bookshelf', 'picture',
67
+ 'counter', 'desk', 'curtain', 'refrigerator', 'shower curtain', 'toilet', 'sink', 'bathtub', 'otherfurniture']
68
+ gravity_dim = 2
69
+
70
+ color_mean = [0.46259782, 0.46253258, 0.46253258]
71
+ color_std = [0.693565 , 0.6852543 , 0.68061745]
72
+ """ScanNet dataset, loading the subsampled entire room as input without block/sphere subsampling.
73
+ number of points per room in average, median, and std: (145841.0, 158783.87179487178, 84200.84445829492)
74
+ """
75
+ def __init__(self,
76
+ data_root='data/ScanNet',
77
+ split='train',
78
+ voxel_size=0.04,
79
+ voxel_max=None,
80
+ transform=None,
81
+ loop=1, presample=False, variable=False,
82
+ n_shifted=1
83
+ ):
84
+ super().__init__()
85
+ self.split = split
86
+ self.voxel_size = voxel_size
87
+ self.voxel_max = voxel_max
88
+ self.transform = transform
89
+ self.presample = presample
90
+ self.variable = variable
91
+ self.loop = loop
92
+ self.n_shifted = n_shifted
93
+ self.pipe_transform = PointsToTensor()
94
+
95
+ if split == "train" or split == 'val':
96
+ self.data_list = glob.glob(os.path.join(data_root, split, "*.pth"))
97
+ elif split == 'trainval':
98
+ self.data_list = glob.glob(os.path.join(
99
+ data_root, "train", "*.pth")) + glob.glob(os.path.join(data_root, "val", "*.pth"))
100
+ elif split == 'test':
101
+ self.data_list = glob.glob(os.path.join(data_root, split, "*.pth"))
102
+ else:
103
+ raise ValueError("no such split: {}".format(split))
104
+
105
+ logging.info("Totally {} samples in {} set.".format(
106
+ len(self.data_list), split))
107
+
108
+ processed_root = os.path.join(data_root, 'processed')
109
+ filename = os.path.join(
110
+ processed_root, f'scannet_{split}_{voxel_size:.3f}.pkl')
111
+ if presample and not os.path.exists(filename):
112
+ np.random.seed(0)
113
+ self.data = []
114
+ for item in tqdm(self.data_list, desc=f'Loading ScanNet {split} split'):
115
+ data = torch.load(item)
116
+ coord, feat, label = data[0:3]
117
+ coord, feat, label = crop_pc(
118
+ coord, feat, label, self.split, self.voxel_size, self.voxel_max, variable=self.variable)
119
+ cdata = np.hstack(
120
+ (coord, feat, np.expand_dims(label, -1))).astype(np.float32)
121
+ self.data.append(cdata)
122
+ npoints = np.array([len(data) for data in self.data])
123
+ logging.info('split: %s, median npoints %.1f, avg num points %.1f, std %.1f' % (
124
+ self.split, np.median(npoints), np.average(npoints), np.std(npoints)))
125
+ os.makedirs(processed_root, exist_ok=True)
126
+ with open(filename, 'wb') as f:
127
+ pickle.dump(self.data, f)
128
+ print(f"{filename} saved successfully")
129
+ elif presample:
130
+ with open(filename, 'rb') as f:
131
+ self.data = pickle.load(f)
132
+ print(f"{filename} load successfully")
133
+ # median, average, std of number of points after voxel sampling for val set.
134
+ # (100338.5, 109686.1282051282, 57024.51083415437)
135
+ # before voxel sampling
136
+ # (145841.0, 158783.87179487178, 84200.84445829492)
137
+ def __getitem__(self, idx):
138
+ data_idx = idx % len(self.data_list)
139
+ if self.presample:
140
+ coord, feat, label = np.split(self.data[data_idx], [3, 6], axis=1)
141
+ else:
142
+ data_path = self.data_list[data_idx]
143
+ data = torch.load(data_path)
144
+ coord, feat, label = data[0:3]
145
+
146
+ feat = (feat + 1) * 127.5
147
+ label = label.astype(np.long).squeeze()
148
+ data = {'pos': coord.astype(np.float32), 'x': feat.astype(np.float32), 'y': label}
149
+ """debug
150
+ from openpoints.dataset import vis_multi_points
151
+ import copy
152
+ old_data = copy.deepcopy(data)
153
+ if self.transform is not None:
154
+ data = self.transform(data)
155
+ data['pos'], data['x'], data['y'] = crop_pc(
156
+ data['pos'], data['x'], data['y'], self.split, self.voxel_size, self.voxel_max,
157
+ downsample=not self.presample, variable=self.variable)
158
+
159
+ vis_multi_points([old_data['pos'][:, :3], data['pos'][:, :3]], colors=[old_data['x'][:, :3]/255.,data['x'][:, :3]])
160
+ """
161
+ if self.transform is not None:
162
+ data = self.transform(data)
163
+
164
+ if not self.presample:
165
+ data['pos'], data['x'], data['y'] = crop_pc(
166
+ data['pos'], data['x'], data['y'], self.split, self.voxel_size, self.voxel_max,
167
+ downsample=not self.presample, variable=self.variable)
168
+
169
+ data = self.pipe_transform(data)
170
+
171
+ if 'heights' not in data.keys():
172
+ data['heights'] = data['pos'][:, self.gravity_dim:self.gravity_dim+1] - data['pos'][:, self.gravity_dim:self.gravity_dim+1].min()
173
+ return data
174
+
175
+ def __len__(self):
176
+ return len(self.data_list) * self.loop
@@ -0,0 +1,3 @@
1
+ from .scanobjectnn import ScanObjectNNHardest
2
+
3
+