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,210 @@
1
+ """_summary_
2
+ """
3
+
4
+
5
+ import os
6
+ import numpy as np
7
+ import pickle
8
+ import logging
9
+ import pathlib
10
+ import glob
11
+ import random
12
+ import h5py
13
+ import pandas as pd
14
+ import torch
15
+ from tqdm import tqdm
16
+ from torch.utils.data import Dataset
17
+ from ..build import DATASETS
18
+ from openpoints.models.layers import fps
19
+ import warnings
20
+ warnings.filterwarnings('ignore')
21
+
22
+
23
+ def pc_normalize(pc):
24
+ centroid = np.mean(pc, axis=0)
25
+ pc = pc - centroid
26
+ m = np.max(np.sqrt(np.sum(pc ** 2, axis=1)))
27
+ pc = pc / m
28
+ return pc
29
+
30
+
31
+ @DATASETS.register_module()
32
+ class MP40(Dataset):
33
+ classes = ["wall",
34
+ "floor",
35
+ "chair",
36
+ "door"
37
+ "table",
38
+ "picture",
39
+ "cabinet",
40
+ "cushion",
41
+ "window",
42
+ "sofa"
43
+ "bed"
44
+ "curtain",
45
+ "chest_of_drawers",
46
+ "plant",
47
+ "sink"
48
+ "stairs",
49
+ "ceiling",
50
+ "toilet",
51
+ "stool",
52
+ "towel",
53
+ "mirror",
54
+ "tv_monitor",
55
+ "shower",
56
+ "column",
57
+ "bathtub",
58
+ "counter",
59
+ "fireplace",
60
+ "lighting",
61
+ "beam"
62
+ "railing",
63
+ "shelving",
64
+ "blinds",
65
+ "gym_equipment",
66
+ "seating",
67
+ "board_panel",
68
+ "furniture",
69
+ "appliances",
70
+ "clothes",
71
+ "objects",
72
+ "misc"
73
+ ]
74
+
75
+ def __init__(self,
76
+ data_dir,
77
+ num_points=1024,
78
+ split='train',
79
+ transform=None,
80
+ use_normal=False,
81
+ **kwargs
82
+ ):
83
+ self.npoints = num_points
84
+ self.preprocess = True
85
+ self.uniform = True
86
+ self.split = split
87
+ self.use_normal = use_normal
88
+ self.transform = transform
89
+
90
+ root_dir = pathlib.Path(data_dir)
91
+ data_dir = root_dir / 'raw'
92
+ data_list = root_dir / f'mattportobject_{split}_list.txt'
93
+
94
+ if not data_list.exists():
95
+ all_files = [i.name for i in data_dir.glob('*.npy')]
96
+ random.shuffle(all_files)
97
+ n_files = len(all_files)
98
+ n_train = int(0.8 * n_files)
99
+ n_val = int(0.1 * n_files)
100
+ train_files = all_files[:n_train]
101
+ val_files = all_files[n_train:n_train+n_val]
102
+ test_files = all_files[n_train+n_val:]
103
+ train_list = str(root_dir / (f'mattportobject_train_list.txt'))
104
+ val_list = str(root_dir / (f'mattportobject_val_list.txt'))
105
+ test_list = str(root_dir / (f'mattportobject_test_list.txt'))
106
+ with open(train_list, 'w') as f:
107
+ f.writelines('\n'.join(train_files))
108
+ with open(val_list, 'w') as f:
109
+ f.writelines('\n'.join(val_files))
110
+ with open(test_list, 'w') as f:
111
+ f.writelines('\n'.join(test_files))
112
+ with open(data_list, 'r') as f:
113
+ lines = f.read().splitlines()
114
+ self.datapath = [data_dir / l for l in lines]
115
+
116
+ if self.uniform:
117
+ self.save_path = os.path.join(
118
+ root_dir, 'matterport3dobjects_%s_%dpts_fps.h5' % (split, 2048))
119
+ else:
120
+ self.save_path = os.path.join(
121
+ root_dir, 'matterport3dobjects_%s_%dpts.h5' % (split, 2048))
122
+
123
+ npoints = 2048
124
+ if not os.path.exists(self.save_path):
125
+ logging.info(
126
+ 'Processing data %s (only running in the first time)...' % self.save_path)
127
+ list_of_points = []
128
+ list_of_labels = []
129
+
130
+ for index in tqdm(range(len(self.datapath)), total=len(self.datapath)):
131
+ fn = self.datapath[index]
132
+ data = np.load(fn, allow_pickle=True).item()
133
+ cls = data['label']
134
+ point_set = data['points'].astype(np.float32)
135
+ if self.uniform:
136
+ point_set = fps(torch.from_numpy(point_set).unsqueeze(
137
+ 0).cuda(), npoints).squeeze(0).cpu().numpy()
138
+ else:
139
+ point_set = point_set[:npoints, :]
140
+
141
+ list_of_points.append(point_set)
142
+ list_of_labels.append(cls)
143
+
144
+ all_points = np.stack(list_of_points)
145
+ all_labels = np.stack(list_of_labels)
146
+ all_data = {'data': all_points, 'label': all_labels}
147
+ hf = h5py.File(self.save_path, 'w')
148
+ data = hf.create_group('data')
149
+ for k, v in all_data.items():
150
+ data[k] = v
151
+ hf.close()
152
+ logging.info('Load processed data from %s...' % self.save_path)
153
+ with h5py.File(self.save_path, 'r') as f:
154
+ data = f['data']['data'][:].astype('float32')
155
+ label = f['data']['label'][:].astype('int32')
156
+
157
+ # TODO: make this in preprocessing step. not here.
158
+ cls_mapping = pd.read_csv(str(pathlib.Path(__file__).parent / "category_mapping.tsv"),
159
+ skiprows=1, header=None, sep='\t', usecols=[0, 16]).values.astype(int)
160
+
161
+ # step 1 remove negative label (useless)
162
+ idx = np.argwhere(label > 0).squeeze()
163
+ data = data[idx]
164
+ label = label[idx]
165
+
166
+ # step 2 mapping label to mat40
167
+ # cls_mapping is a np array. row 0 = wall = label(wall) --> mpcat40
168
+ label = cls_mapping[label-1][:, 1]
169
+
170
+ # step 3, remove the label not in mat40 (0, and 41)
171
+ label_bigger_0 = label > 0
172
+ label_smaller_41 = label < 41
173
+ idx = []
174
+ for i in range(len(label)):
175
+ if label_bigger_0[i] and label_smaller_41[i]:
176
+ idx.append(i)
177
+ self.data = data[idx]
178
+ self.label = label[idx] - 1
179
+
180
+ def __len__(self):
181
+ return len(self.data)
182
+
183
+ @property
184
+ def num_classes(self):
185
+ return self.label.max() + 1
186
+
187
+ def __getitem__(self, index):
188
+ points, label = self.data[index][:self.npoints], self.label[index]
189
+ if self.split == 'train':
190
+ np.random.shuffle(points)
191
+ data = {'pos': points[:, :3],
192
+ 'x': points[:, 3:6 + 3 * self.use_normal],
193
+ 'y': label
194
+ }
195
+ if self.transform is not None:
196
+ data = self.transform(data)
197
+ """_summary_
198
+ from openpoints.dataset.vis3d import vis_points
199
+
200
+ for i, idx in enumerate(np.where(self.label==22)[0]):
201
+ if i >5:
202
+ break
203
+ vis_points(self.data[idx, :, :3], self.data[idx, :, 3:6]/255.)
204
+ """
205
+ if 'heights' in data.keys():
206
+ data['x'] = torch.cat(
207
+ (data['pos'], data['heights'], data['x']), dim=1)
208
+ else:
209
+ data['x'] = torch.cat((data['pos'], data['x']), dim=1)
210
+ return data
@@ -0,0 +1,105 @@
1
+
2
+ import os, sys, zipfile, h5py, numpy as np, multiprocessing
3
+ from pathlib import Path
4
+ from tqdm import tqdm
5
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../')))
6
+ from openpoints.dataset.utils3d import *
7
+ from openpoints.dataset.vis3d import *
8
+
9
+
10
+ def unzip_folders(data_dir, unzipped_path):
11
+ for dirpath, dirs, files in os.walk(data_dir):
12
+ for file in files:
13
+ if file.endswith('zip'):
14
+ file_path = os.path.join(dirpath, file)
15
+ zip_file = zipfile.ZipFile(file_path)
16
+ for names in zip_file.namelist():
17
+ zip_file.extract(names, unzipped_path)
18
+ zip_file.close()
19
+
20
+
21
+ def save_room_objects(mesh_path, save_name):
22
+ """save the objects in a rooom together
23
+
24
+ Args:
25
+ mesh_path (_type_): _description_
26
+ save_name (_type_): _description_
27
+ """
28
+ all_points = []
29
+ all_ins_labels = []
30
+ all_cls_labels = []
31
+
32
+ points, faces, f_cls_id, f_ins_id = read_mesh_vf(mesh_path)
33
+ # category id: https://github.com/niessner/Matterport/blob/master/metadata/category_mapping.tsv
34
+ # vis_points(points[:, :3], points[:, 3:6])
35
+ f_cls_id_unique = np.unique(f_cls_id) # the unique category ids (eg. pillow, wall)
36
+ for cls in f_cls_id_unique:
37
+ face_cls_flag = f_cls_id==cls # wheter face is current cls
38
+ face_cls = faces[face_cls_flag] # pick the face which is current cls
39
+ face_cls_ins = f_ins_id[face_cls_flag] # pick the instance label of the face
40
+ for ins_id in np.unique(face_cls_ins): # for each instance
41
+ point_idx = face_cls[face_cls_ins==ins_id].reshape(-1)
42
+ points_cls_ins = points[point_idx]
43
+ all_points.append(points_cls_ins)
44
+ all_ins_labels.append(ins_id)
45
+ all_cls_labels.append(cls)
46
+ data = {'points': all_points, 'ins_labels': all_ins_labels, 'y': all_cls_labels}
47
+ np.save(f'{save_name}.npy', data)
48
+
49
+
50
+ def save_per_object(mesh_path, save_name):
51
+ """save each object in a h5 file.
52
+
53
+ Args:
54
+ mesh_path (_type_): _description_
55
+ save_name (_type_): _description_
56
+ """
57
+
58
+ points, faces, f_cls_id, f_ins_id = read_mesh_vf(mesh_path)
59
+ # category id: https://github.com/niessner/Matterport/blob/master/metadata/category_mapping.tsv
60
+ # vis_points(points[:, :3], points[:, 3:6])
61
+ f_cls_id_unique = np.unique(f_cls_id) # the unique category ids (eg. pillow, wall)
62
+ for cls in f_cls_id_unique:
63
+ face_cls_flag = f_cls_id==cls # wheter face is current cls
64
+ face_cls = faces[face_cls_flag] # pick the face which is current cls
65
+ face_cls_ins = f_ins_id[face_cls_flag] # pick the instance label of the face
66
+
67
+ for ins_id in np.unique(face_cls_ins): # for each instance
68
+ point_idx = face_cls[face_cls_ins==ins_id].reshape(-1)
69
+ points_cls_ins = points[point_idx]
70
+ vis_points(points_cls_ins[:, :3], points_cls_ins[:, 3:6])
71
+ data = {'points': points_cls_ins, 'ins_label': ins_id, 'label': cls}
72
+
73
+ # TODO: debug comment for now.
74
+ np.save(f'{save_name}_C{cls}_I{ins_id}.npy', data)
75
+
76
+
77
+ if __name__ == "__main__":
78
+ # unzip data at first.
79
+ # root_path = '/data/3D/Matterport3d/v1/scans'
80
+ # unzipped_path = '/data/3D/Matterport3d/v1/scans_unzipped'
81
+ # unzip_folders(root_path, unzipped_path)
82
+
83
+ # loading all points to a single h5 file
84
+
85
+ root_path = Path('/data/3D/Matterport3d/v1/')
86
+
87
+ raw_path = root_path.joinpath('scans_unzipped')
88
+ save_dir = root_path.joinpath('objects')
89
+ save_dir.mkdir(exist_ok=True)
90
+
91
+ all_points = []
92
+ all_ins_labels = []
93
+ all_cls_labels = []
94
+
95
+ # p = multiprocessing.Pool()
96
+ for path in Path(raw_path).rglob('*.ply'):
97
+ file_path = path.parent.joinpath(path.name)
98
+ file_name = '/'.join(path.parts[-3:])
99
+ save_name = '_'.join([path.parts[-3], path.parts[-1].split('.')[0]])
100
+ save_path = os.path.join(save_dir, save_name)
101
+ print(f'===> processing {file_name} ...')
102
+ save_per_object(file_path, save_path)
103
+ # p.apply_async(save_per_object, [file_path, save_path])
104
+ # p.close()
105
+ # p.join() # Wait for all child processes to close.
@@ -0,0 +1,3 @@
1
+ from .modelnet40_normal_resampled_loader import ModelNet
2
+ from .modelnet40_ply_2048_loader import ModelNet40Ply2048
3
+
@@ -0,0 +1,124 @@
1
+ '''
2
+ Borrowed from PointBERT
3
+ @file: ModelNet.py
4
+ @time: 2021/3/19 15:51
5
+ '''
6
+ import os
7
+ import numpy as np
8
+ import warnings
9
+ import pickle
10
+ from tqdm import tqdm
11
+ from torch.utils.data import Dataset
12
+ from ..build import DATASETS
13
+ import torch
14
+ import logging
15
+ warnings.filterwarnings('ignore')
16
+
17
+
18
+ def pc_normalize(pc):
19
+ centroid = np.mean(pc, axis=0)
20
+ pc = pc - centroid
21
+ m = np.max(np.sqrt(np.sum(pc ** 2, axis=1)))
22
+ pc = pc / m
23
+ return pc
24
+
25
+
26
+ def farthest_point_sample(point, npoint):
27
+ """
28
+ Input:
29
+ xyz: pointcloud data, [N, D]
30
+ npoint: number of samples
31
+ Return:
32
+ centroids: sampled pointcloud index, [npoint, D]
33
+ """
34
+ N, D = point.shape
35
+ xyz = point[:, :3]
36
+ centroids = np.zeros((npoint,))
37
+ distance = np.ones((N,)) * 1e10
38
+ farthest = np.random.randint(0, N)
39
+ for i in range(npoint):
40
+ centroids[i] = farthest
41
+ centroid = xyz[farthest, :]
42
+ dist = np.sum((xyz - centroid) ** 2, -1)
43
+ mask = dist < distance
44
+ distance[mask] = dist[mask]
45
+ farthest = np.argmax(distance, -1)
46
+ point = point[centroids.astype(np.int32)]
47
+ return point
48
+
49
+
50
+ @DATASETS.register_module()
51
+ class ModelNet(Dataset):
52
+ def __init__(self,
53
+ data_dir, num_points, num_classes,
54
+ use_normals=False,
55
+ split='train',
56
+ transform=None
57
+ ):
58
+ self.root = os.path.join(data_dir, 'modelnet40_normal_resampled')
59
+ self.npoints = num_points
60
+ self.use_normals = use_normals
61
+ self.num_category = num_classes
62
+ split = 'train' if split.lower() == 'train' else 'test' # val = test
63
+ self.split = split
64
+
65
+ if self.num_category == 10:
66
+ self.catfile = os.path.join(
67
+ self.root, 'modelnet10_shape_names.txt')
68
+ else:
69
+ self.catfile = os.path.join(
70
+ self.root, 'modelnet40_shape_names.txt')
71
+
72
+ self.cat = [line.rstrip() for line in open(self.catfile)]
73
+ self.classes = dict(zip(self.cat, range(len(self.cat))))
74
+
75
+ shape_ids = {}
76
+ if self.num_category == 10:
77
+ shape_ids['train'] = [line.rstrip() for line in open(
78
+ os.path.join(self.root, 'modelnet10_train.txt'))]
79
+ shape_ids['test'] = [line.rstrip() for line in open(
80
+ os.path.join(self.root, 'modelnet10_test.txt'))]
81
+ else:
82
+ shape_ids['train'] = [line.rstrip() for line in open(
83
+ os.path.join(self.root, 'modelnet40_train.txt'))]
84
+ shape_ids['test'] = [line.rstrip() for line in open(
85
+ os.path.join(self.root, 'modelnet40_test.txt'))]
86
+
87
+ assert (split == 'train' or split == 'test')
88
+ shape_names = ['_'.join(x.split('_')[0:-1]) for x in shape_ids[split]]
89
+ self.datapath = [(shape_names[i], os.path.join(self.root, shape_names[i], shape_ids[split][i]) + '.txt') for i
90
+ in range(len(shape_ids[split]))]
91
+ logging.info('The size of %s data is %d' % (split, len(self.datapath)))
92
+ self.transform = transform
93
+
94
+ def __len__(self):
95
+ return len(self.datapath)
96
+
97
+ @property
98
+ def num_classes(self):
99
+ return self.list_of_labels.max() + 1
100
+
101
+ def _get_item(self, index):
102
+ fn = self.datapath[index]
103
+ cls = self.classes[self.datapath[index][0]]
104
+ label = np.array([cls]).astype(np.int64)
105
+ point_set = np.loadtxt(fn[1], delimiter=',').astype(np.float32)
106
+ return point_set[:, 0:3], point_set[:, 3:], label[0]
107
+
108
+ def __getitem__(self, index):
109
+ points, feats, label = self._get_item(index)
110
+ if self.split == 'train':
111
+ np.random.shuffle(points)
112
+ data = {'pos': points,
113
+ 'y': label
114
+ }
115
+ if self.use_normals:
116
+ data['x'] = feats
117
+ if self.transform is not None:
118
+ data = self.transform(data)
119
+
120
+ if self.use_normals:
121
+ data['x'] = torch.cat((data['pos'], data['x']), dim=1)
122
+ if 'heights' in data.keys():
123
+ data['x'] = torch.cat((data['x'], data['heights']), dim=1)
124
+ return data
@@ -0,0 +1,160 @@
1
+ """Modified from DeepGCN and DGCNN
2
+ Reference: https://github.com/lightaime/deep_gcns_torch/tree/master/examples/classification
3
+ """
4
+ import os
5
+ import glob
6
+ import h5py
7
+ import numpy as np
8
+ import pickle
9
+ import logging
10
+ import ssl
11
+ import urllib
12
+ from pathlib import Path
13
+ from tqdm import tqdm
14
+ import torch
15
+ from torch.utils.data import Dataset
16
+ from torchvision.datasets.utils import extract_archive, check_integrity
17
+ from ..build import DATASETS
18
+
19
+
20
+ def download_and_extract_archive(url, path, md5=None):
21
+ # Works when the SSL certificate is expired for the link
22
+ path = Path(path)
23
+ extract_path = path
24
+ if not path.exists():
25
+ path.mkdir(parents=True, exist_ok=True)
26
+ file_path = path / Path(url).name
27
+ if not file_path.exists() or not check_integrity(file_path, md5):
28
+ print(f'{file_path} not found or corrupted')
29
+ print(f'downloading from {url}')
30
+ context = ssl.SSLContext()
31
+ with urllib.request.urlopen(url, context=context) as response:
32
+ with tqdm(total=response.length) as pbar:
33
+ with open(file_path, 'wb') as file:
34
+ chunk_size = 1024
35
+ chunks = iter(lambda: response.read(chunk_size), '')
36
+ for chunk in chunks:
37
+ if not chunk:
38
+ break
39
+ pbar.update(chunk_size)
40
+ file.write(chunk)
41
+ extract_archive(str(file_path), str(extract_path))
42
+ return extract_path
43
+
44
+
45
+ def load_data(data_dir, partition, url):
46
+ download_and_extract_archive(url, data_dir)
47
+ all_data = []
48
+ all_label = []
49
+ for h5_name in glob.glob(os.path.join(data_dir, 'modelnet40_ply_hdf5_2048', 'ply_data_%s*.h5' % partition)):
50
+ with h5py.File(h5_name, 'r') as f:
51
+ data = f['data'][:].astype('float32')
52
+ label = f['label'][:].astype('int64')
53
+ all_data.append(data)
54
+ all_label.append(label)
55
+ all_data = np.concatenate(all_data, axis=0)
56
+ all_label = np.concatenate(all_label, axis=0).squeeze(-1)
57
+ return all_data, all_label
58
+
59
+
60
+ @DATASETS.register_module()
61
+ class ModelNet40Ply2048(Dataset):
62
+ """
63
+ This is the data loader for ModelNet 40
64
+ ModelNet40 contains 12,311 meshed CAD models from 40 categories.
65
+ num_points: 1024 by default
66
+ data_dir
67
+ paritition: train or test
68
+ """
69
+ dir_name = 'modelnet40_ply_hdf5_2048'
70
+ md5 = 'c9ab8e6dfb16f67afdab25e155c79e59'
71
+ url = f'https://shapenet.cs.stanford.edu/media/{dir_name}.zip'
72
+ classes = ['airplane',
73
+ 'bathtub',
74
+ 'bed',
75
+ 'bench',
76
+ 'bookshelf',
77
+ 'bottle',
78
+ 'bowl',
79
+ 'car',
80
+ 'chair',
81
+ 'cone',
82
+ 'cup',
83
+ 'curtain',
84
+ 'desk',
85
+ 'door',
86
+ 'dresser',
87
+ 'flower_pot',
88
+ 'glass_box',
89
+ 'guitar',
90
+ 'keyboard',
91
+ 'lamp',
92
+ 'laptop',
93
+ 'mantel',
94
+ 'monitor',
95
+ 'night_stand',
96
+ 'person',
97
+ 'piano',
98
+ 'plant',
99
+ 'radio',
100
+ 'range_hood',
101
+ 'sink',
102
+ 'sofa',
103
+ 'stairs',
104
+ 'stool',
105
+ 'table',
106
+ 'tent',
107
+ 'toilet',
108
+ 'tv_stand',
109
+ 'vase',
110
+ 'wardrobe',
111
+ 'xbox']
112
+
113
+ def __init__(self,
114
+ num_points=1024,
115
+ data_dir="./data/ModelNet40Ply2048",
116
+ split='train',
117
+ transform=None
118
+ ):
119
+ data_dir = os.path.join(
120
+ os.getcwd(), data_dir) if data_dir.startswith('.') else data_dir
121
+ self.partition = 'train' if split.lower() == 'train' else 'test' # val = test
122
+ self.data, self.label = load_data(data_dir, self.partition, self.url)
123
+ self.num_points = num_points
124
+ logging.info(f'==> sucessfully loaded {self.partition} data')
125
+ self.transform = transform
126
+
127
+ def __getitem__(self, item):
128
+ pointcloud = self.data[item][:self.num_points]
129
+ label = self.label[item]
130
+
131
+ if self.partition == 'train':
132
+ np.random.shuffle(pointcloud)
133
+ data = {'pos': pointcloud,
134
+ 'y': label
135
+ }
136
+ if self.transform is not None:
137
+ data = self.transform(data)
138
+
139
+ if 'heights' in data.keys():
140
+ data['x'] = torch.cat((data['pos'], data['heights']), dim=1)
141
+ else:
142
+ data['x'] = data['pos']
143
+ return data
144
+
145
+ def __len__(self):
146
+ return self.data.shape[0]
147
+
148
+ @property
149
+ def num_classes(self):
150
+ return np.max(self.label) + 1
151
+
152
+ """ for visulalization
153
+ from openpoints.dataset import vis_multi_points
154
+ import copy
155
+ old_points = copy.deepcopy(data['pos'])
156
+ if self.transform is not None:
157
+ data = self.transform(data)
158
+ new_points = copy.deepcopy(data['pos'])
159
+ vis_multi_points([old_points, new_points.numpy()])
160
+ End of visulization """
@@ -0,0 +1 @@
1
+ from .data import *
@@ -0,0 +1,59 @@
1
+ import numpy as np
2
+ import torch
3
+ from ..dataset_base import DatasetBase
4
+ from ..graph_dataset import GraphDataset
5
+ from ..graph_dataset import SVDEncodingsGraphDataset
6
+ from ..graph_dataset import StructuralDataset
7
+
8
+ class MOLHIVDataset(DatasetBase):
9
+ def __init__(self,
10
+ dataset_path ,
11
+ dataset_name = 'MOLHIV' ,
12
+ **kwargs
13
+ ):
14
+ super().__init__(dataset_name = dataset_name,
15
+ **kwargs)
16
+ self.dataset_path = dataset_path
17
+
18
+ @property
19
+ def dataset(self):
20
+ try:
21
+ return self._dataset
22
+ except AttributeError:
23
+ from ogb.graphproppred import GraphPropPredDataset
24
+ self._dataset = GraphPropPredDataset(name='ogbg-molhiv', root=self.dataset_path)
25
+ return self._dataset
26
+
27
+ @property
28
+ def record_tokens(self):
29
+ try:
30
+ return self._record_tokens
31
+ except AttributeError:
32
+ split = {'training':'train',
33
+ 'validation':'valid',
34
+ 'test':'test'}[self.split]
35
+ self._record_tokens = self.dataset.get_idx_split()[split]
36
+ return self._record_tokens
37
+
38
+ def read_record(self, token):
39
+ graph, target = self.dataset[token]
40
+ graph['num_nodes'] = np.array(graph['num_nodes'], dtype=np.int16)
41
+ graph['edges'] = graph.pop('edge_index').T.astype(np.int16)
42
+ graph['edge_features'] = graph.pop('edge_feat').astype(np.int16)
43
+ graph['node_features'] = graph.pop('node_feat').astype(np.int16)
44
+ graph['target'] = np.array(target, np.float32)
45
+ return graph
46
+
47
+
48
+
49
+ class MOLHIVGraphDataset(GraphDataset,MOLHIVDataset):
50
+ pass
51
+
52
+ class MOLHIVSVDGraphDataset(SVDEncodingsGraphDataset,MOLHIVDataset):
53
+ pass
54
+
55
+ class MOLHIVStructuralGraphDataset(StructuralDataset,MOLHIVGraphDataset):
56
+ pass
57
+
58
+ class MOLHIVStructuralSVDGraphDataset(StructuralDataset,MOLHIVSVDGraphDataset):
59
+ pass
@@ -0,0 +1 @@
1
+ from .data import *