├── misc ├── fig.png ├── s3dis_asis.png └── vkitti_asis.png ├── tf_ops ├── grouping │ ├── tf_grouping.pyc │ ├── tf_grouping_g.cu.o │ ├── tf_grouping_so.so │ ├── test │ │ ├── compile.sh │ │ ├── selection_sort.cu │ │ ├── selection_sort_const.cu │ │ ├── selection_sort.cpp │ │ ├── query_ball_point.cpp │ │ ├── query_ball_point_block.cu │ │ ├── query_ball_point.cu │ │ └── query_ball_point_grid.cu │ ├── tf_grouping_op_test.py │ ├── tf_grouping_compile.sh │ ├── tf_grouping.py │ ├── tf_grouping_g.cu │ └── tf_grouping.cpp ├── sampling │ ├── tf_sampling.pyc │ ├── tf_sampling_g.cu.o │ ├── tf_sampling_so.so │ ├── tf_sampling_compile.sh │ ├── tf_sampling.py │ ├── tf_sampling_g.cu │ └── tf_sampling.cpp └── 3d_interpolation │ ├── tf_interpolate.pyc │ ├── tf_interpolate_so.so │ ├── tf_interpolate_op_test.py │ ├── tf_interpolate_compile.sh │ ├── visu_interpolation.py │ ├── tf_interpolate.py │ ├── interpolate.cpp │ └── tf_interpolate.cpp ├── utils ├── __pycache__ │ ├── loss.cpython-36.pyc │ └── tf_util.cpython-36.pyc ├── clustering.py ├── data_prep_util.py ├── pc_util.py └── test_utils.py ├── meta ├── class_names.txt ├── updata_datalabeltxt.py ├── area3_data_label.txt ├── area2_data_label.txt ├── area1_data_label.txt ├── area6_data_label.txt ├── area4_data_label.txt ├── area5_data_label.txt ├── all_data_label.txt └── anno_paths.txt ├── models └── ASIS │ ├── train.sh │ ├── estimate_mean_ins_size.py │ ├── model.py │ ├── eval_iou_accuracy.py │ ├── provider.py │ ├── part_color_mapping.json │ ├── train.py │ └── test.py ├── collect_indoor3d_data.py ├── data └── generate_input_list.py ├── LICENSE ├── gen_h5.py └── README.md /misc/fig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/misc/fig.png -------------------------------------------------------------------------------- /misc/s3dis_asis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/misc/s3dis_asis.png -------------------------------------------------------------------------------- /misc/vkitti_asis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/misc/vkitti_asis.png -------------------------------------------------------------------------------- /tf_ops/grouping/tf_grouping.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/tf_ops/grouping/tf_grouping.pyc -------------------------------------------------------------------------------- /tf_ops/sampling/tf_sampling.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/tf_ops/sampling/tf_sampling.pyc -------------------------------------------------------------------------------- /tf_ops/grouping/tf_grouping_g.cu.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/tf_ops/grouping/tf_grouping_g.cu.o -------------------------------------------------------------------------------- /tf_ops/grouping/tf_grouping_so.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/tf_ops/grouping/tf_grouping_so.so -------------------------------------------------------------------------------- /tf_ops/sampling/tf_sampling_g.cu.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/tf_ops/sampling/tf_sampling_g.cu.o -------------------------------------------------------------------------------- /tf_ops/sampling/tf_sampling_so.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/tf_ops/sampling/tf_sampling_so.so -------------------------------------------------------------------------------- /utils/__pycache__/loss.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/utils/__pycache__/loss.cpython-36.pyc -------------------------------------------------------------------------------- /tf_ops/3d_interpolation/tf_interpolate.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/tf_ops/3d_interpolation/tf_interpolate.pyc -------------------------------------------------------------------------------- /utils/__pycache__/tf_util.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/utils/__pycache__/tf_util.cpython-36.pyc -------------------------------------------------------------------------------- /tf_ops/3d_interpolation/tf_interpolate_so.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WXinlong/ASIS/HEAD/tf_ops/3d_interpolation/tf_interpolate_so.so -------------------------------------------------------------------------------- /meta/class_names.txt: -------------------------------------------------------------------------------- 1 | ceiling 2 | floor 3 | wall 4 | beam 5 | column 6 | window 7 | door 8 | table 9 | chair 10 | sofa 11 | bookcase 12 | board 13 | clutter 14 | -------------------------------------------------------------------------------- /tf_ops/grouping/test/compile.sh: -------------------------------------------------------------------------------- 1 | g++ query_ball_point.cpp -o query_ball_point 2 | nvcc query_ball_point.cu -o query_ball_point_cuda 3 | nvcc query_ball_point_block.cu -o query_ball_point_block 4 | nvcc query_ball_point_grid.cu -o query_ball_point_grid 5 | g++ -Wall selection_sort.cpp -o selection_sort 6 | nvcc selection_sort.cu -o selection_sort_cuda 7 | -------------------------------------------------------------------------------- /models/ASIS/train.sh: -------------------------------------------------------------------------------- 1 | i=$1 2 | python train.py --gpu 0 --batch_size 24 --max_epoch 100 --log_dir log${i} --learning_rate 0.001 --decay_step 300000 --restore_model None --input_list data/train_hdf5_file_list_woArea${i}.txt 3 | python estimate_mean_ins_size.py --test_area ${i} 4 | python test.py --gpu 0 --bandwidth 0.6 --log_dir log${i}_test --model_path log${i}/epoch_99.ckpt --input_list meta/area${i}_data_label.txt --verbose 5 | -------------------------------------------------------------------------------- /meta/updata_datalabeltxt.py: -------------------------------------------------------------------------------- 1 | import os 2 | import glob 3 | 4 | files = glob.glob('area?_data_label.txt') 5 | print(files) 6 | for f in files: 7 | fopen = open(f, 'r') 8 | 9 | new_lines = [] 10 | for line in fopen.readlines(): 11 | new_line = line.replace('stanford_indoor3d', 'stanford_indoor3d_ins.sem') 12 | print(new_line) 13 | new_lines.append(new_line) 14 | 15 | fwrite = open(f, 'w') 16 | 17 | fwrite.writelines(new_lines) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tf_ops/3d_interpolation/tf_interpolate_op_test.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | from tf_interpolate import three_nn, three_interpolate 4 | 5 | class GroupPointTest(tf.test.TestCase): 6 | def test(self): 7 | pass 8 | 9 | def test_grad(self): 10 | with self.test_session(): 11 | points = tf.constant(np.random.random((1,8,16)).astype('float32')) 12 | print points 13 | xyz1 = tf.constant(np.random.random((1,128,3)).astype('float32')) 14 | xyz2 = tf.constant(np.random.random((1,8,3)).astype('float32')) 15 | dist, idx = three_nn(xyz1, xyz2) 16 | weight = tf.ones_like(dist)/3.0 17 | interpolated_points = three_interpolate(points, idx, weight) 18 | print interpolated_points 19 | err = tf.test.compute_gradient_error(points, (1,8,16), interpolated_points, (1,128,16)) 20 | print err 21 | self.assertLess(err, 1e-4) 22 | 23 | if __name__=='__main__': 24 | tf.test.main() 25 | -------------------------------------------------------------------------------- /collect_indoor3d_data.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 4 | sys.path.append(BASE_DIR) 5 | import indoor3d_util 6 | 7 | anno_paths = [line.rstrip() for line in open(os.path.join(BASE_DIR, 'meta/anno_paths.txt'))] 8 | anno_paths = [os.path.join(indoor3d_util.DATA_PATH, p) for p in anno_paths] 9 | 10 | output_folder = os.path.join(BASE_DIR, 'data/stanford_indoor3d_ins.sem') 11 | if not os.path.exists(output_folder): 12 | os.mkdir(output_folder) 13 | 14 | # Note: there is an extra character in the v1.2 data in Area_5/hallway_6. It's fixed manually. 15 | for anno_path in anno_paths: 16 | print(anno_path) 17 | try: 18 | elements = anno_path.split('/') 19 | out_filename = elements[-3]+'_'+elements[-2]+'.npy' # Area_1_hallway_1.npy 20 | indoor3d_util.collect_point_label(anno_path, os.path.join(output_folder, out_filename), 'numpy') 21 | except: 22 | print(anno_path, 'ERROR!!') 23 | -------------------------------------------------------------------------------- /data/generate_input_list.py: -------------------------------------------------------------------------------- 1 | import os 2 | import glob 3 | 4 | h5_dir = "indoor3d_ins_seg_hdf5/" 5 | 6 | for i in range(6): 7 | 8 | filter_id = i + 1 9 | 10 | # For training 11 | train_fold_pattern = "Area_[!{}]*.h5".format(filter_id) 12 | dst_list_path = "train_hdf5_file_list_woArea{}.txt".format(filter_id) 13 | 14 | h5_files = glob.glob(os.path.join(h5_dir + train_fold_pattern)) 15 | 16 | f = open(dst_list_path, 'w') 17 | for h5_file in h5_files: 18 | f.write('data/' + h5_file) 19 | f.write('\n') 20 | f.close() 21 | 22 | # For test 23 | test_fold_pattern = "Area_{}*.h5".format(filter_id) 24 | dst_list_path = "test_hdf5_file_list_Area{}.txt".format(filter_id) 25 | 26 | h5_files = glob.glob(os.path.join(h5_dir + test_fold_pattern)) 27 | 28 | f = open(dst_list_path, 'w') 29 | for h5_file in h5_files: 30 | f.write('data/' + h5_file) 31 | f.write('\n') 32 | f.close() 33 | 34 | -------------------------------------------------------------------------------- /tf_ops/grouping/tf_grouping_op_test.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | from tf_grouping import query_ball_point, group_point 4 | 5 | class GroupPointTest(tf.test.TestCase): 6 | def test(self): 7 | pass 8 | 9 | def test_grad(self): 10 | with tf.device('/gpu:0'): 11 | points = tf.constant(np.random.random((1,128,16)).astype('float32')) 12 | print points 13 | xyz1 = tf.constant(np.random.random((1,128,3)).astype('float32')) 14 | xyz2 = tf.constant(np.random.random((1,8,3)).astype('float32')) 15 | radius = 0.3 16 | nsample = 32 17 | idx, pts_cnt = query_ball_point(radius, nsample, xyz1, xyz2) 18 | grouped_points = group_point(points, idx) 19 | print grouped_points 20 | 21 | with self.test_session(): 22 | print "---- Going to compute gradient error" 23 | err = tf.test.compute_gradient_error(points, (1,128,16), grouped_points, (1,8,32,16)) 24 | print err 25 | self.assertLess(err, 1e-4) 26 | 27 | if __name__=='__main__': 28 | tf.test.main() 29 | -------------------------------------------------------------------------------- /tf_ops/3d_interpolation/tf_interpolate_compile.sh: -------------------------------------------------------------------------------- 1 | # TF1.2 2 | #g++ -std=c++11 tf_interpolate.cpp -o tf_interpolate_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-8.0/include -lcudart -L /usr/local/cuda-8.0/lib64/ -O2 -D_GLIBCXX_USE_CXX11_ABI=0 3 | 4 | # TF1.4 5 | #g++ -std=c++11 tf_interpolate.cpp -o tf_interpolate_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-8.0/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda-8.0/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0 6 | g++ -std=c++11 tf_interpolate.cpp -o tf_interpolate_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-9.0/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda-9.0/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Xinlong Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /meta/area3_data_label.txt: -------------------------------------------------------------------------------- 1 | data/stanford_indoor3d_ins.sem/Area_3_conferenceRoom_1.npy 2 | data/stanford_indoor3d_ins.sem/Area_3_hallway_1.npy 3 | data/stanford_indoor3d_ins.sem/Area_3_hallway_2.npy 4 | data/stanford_indoor3d_ins.sem/Area_3_hallway_3.npy 5 | data/stanford_indoor3d_ins.sem/Area_3_hallway_4.npy 6 | data/stanford_indoor3d_ins.sem/Area_3_hallway_5.npy 7 | data/stanford_indoor3d_ins.sem/Area_3_hallway_6.npy 8 | data/stanford_indoor3d_ins.sem/Area_3_lounge_1.npy 9 | data/stanford_indoor3d_ins.sem/Area_3_lounge_2.npy 10 | data/stanford_indoor3d_ins.sem/Area_3_office_10.npy 11 | data/stanford_indoor3d_ins.sem/Area_3_office_1.npy 12 | data/stanford_indoor3d_ins.sem/Area_3_office_2.npy 13 | data/stanford_indoor3d_ins.sem/Area_3_office_3.npy 14 | data/stanford_indoor3d_ins.sem/Area_3_office_4.npy 15 | data/stanford_indoor3d_ins.sem/Area_3_office_5.npy 16 | data/stanford_indoor3d_ins.sem/Area_3_office_6.npy 17 | data/stanford_indoor3d_ins.sem/Area_3_office_7.npy 18 | data/stanford_indoor3d_ins.sem/Area_3_office_8.npy 19 | data/stanford_indoor3d_ins.sem/Area_3_office_9.npy 20 | data/stanford_indoor3d_ins.sem/Area_3_storage_1.npy 21 | data/stanford_indoor3d_ins.sem/Area_3_storage_2.npy 22 | data/stanford_indoor3d_ins.sem/Area_3_WC_1.npy 23 | data/stanford_indoor3d_ins.sem/Area_3_WC_2.npy 24 | -------------------------------------------------------------------------------- /tf_ops/grouping/tf_grouping_compile.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | #/usr/local/cuda-8.0/bin/nvcc tf_grouping_g.cu -o tf_grouping_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC 3 | /usr/local/cuda-9.0/bin/nvcc tf_grouping_g.cu -o tf_grouping_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC 4 | 5 | # TF1.2 6 | #g++ -std=c++11 tf_grouping.cpp tf_grouping_g.cu.o -o tf_grouping_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-8.0/include -lcudart -L /usr/local/cuda-8.0/lib64/ -O2 -D_GLIBCXX_USE_CXX11_ABI=0 7 | 8 | # TF1.4 9 | #g++ -std=c++11 tf_grouping.cpp tf_grouping_g.cu.o -o tf_grouping_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-8.0/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda-8.0/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0 10 | g++ -std=c++11 tf_grouping.cpp tf_grouping_g.cu.o -o tf_grouping_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-9.0/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda-9.0/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0 11 | -------------------------------------------------------------------------------- /tf_ops/sampling/tf_sampling_compile.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | #/usr/local/cuda-8.0/bin/nvcc tf_sampling_g.cu -o tf_sampling_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC 3 | /usr/local/cuda-9.0/bin/nvcc tf_sampling_g.cu -o tf_sampling_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC 4 | 5 | # TF1.2 6 | #g++ -std=c++11 tf_sampling.cpp tf_sampling_g.cu.o -o tf_sampling_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-8.0/include -lcudart -L /usr/local/cuda-8.0/lib64/ -O2 -D_GLIBCXX_USE_CXX11_ABI=0 7 | 8 | # TF1.4 9 | #g++ -std=c++11 tf_sampling.cpp tf_sampling_g.cu.o -o tf_sampling_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-8.0/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda-8.0/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0 10 | 11 | g++ -std=c++11 tf_sampling.cpp tf_sampling_g.cu.o -o tf_sampling_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-9.0/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda-9.0/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0 12 | -------------------------------------------------------------------------------- /tf_ops/3d_interpolation/visu_interpolation.py: -------------------------------------------------------------------------------- 1 | ''' Visualize part segmentation ''' 2 | import os 3 | import sys 4 | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 | sys.path.append('/home/rqi/Projects/toolkits/visualization') 6 | from show3d_balls import showpoints 7 | import numpy as np 8 | from tf_interpolate import three_nn, three_interpolate 9 | import tensorflow as tf 10 | 11 | 12 | pts2 = np.array([[0,0,1],[1,0,0],[0,1,0],[1,1,0]]).astype('float32') 13 | xyz1 = np.random.random((100,3)).astype('float32') 14 | xyz2 = np.array([[0,0,0],[1,0,0],[0,1,0],[1,1,1]]).astype('float32') 15 | 16 | def fun(xyz1,xyz2,pts2): 17 | with tf.device('/cpu:0'): 18 | points = tf.constant(np.expand_dims(pts2,0)) 19 | xyz1 = tf.constant(np.expand_dims(xyz1,0)) 20 | xyz2 = tf.constant(np.expand_dims(xyz2,0)) 21 | dist, idx = three_nn(xyz1, xyz2) 22 | #weight = tf.ones_like(dist)/3.0 23 | dist = tf.maximum(dist, 1e-10) 24 | norm = tf.reduce_sum((1.0/dist),axis=2,keep_dims=True) 25 | norm = tf.tile(norm, [1,1,3]) 26 | print norm 27 | weight = (1.0/dist) / norm 28 | interpolated_points = three_interpolate(points, idx, weight) 29 | with tf.Session('') as sess: 30 | tmp,pts1,d,w = sess.run([xyz1, interpolated_points, dist, weight]) 31 | #print w 32 | pts1 = pts1.squeeze() 33 | return pts1 34 | 35 | pts1 = fun(xyz1,xyz2,pts2) 36 | all_pts = np.zeros((104,3)) 37 | all_pts[0:100,:] = pts1 38 | all_pts[100:,:] = pts2 39 | all_xyz = np.zeros((104,3)) 40 | all_xyz[0:100,:]=xyz1 41 | all_xyz[100:,:]=xyz2 42 | showpoints(xyz2, pts2, ballradius=8) 43 | showpoints(xyz1, pts1, ballradius=8) 44 | showpoints(all_xyz, all_pts, ballradius=8) 45 | -------------------------------------------------------------------------------- /models/ASIS/estimate_mean_ins_size.py: -------------------------------------------------------------------------------- 1 | # To estimate the mean instance size of each class in training set 2 | import os 3 | import sys 4 | import numpy as np 5 | from scipy import stats 6 | import argparse 7 | 8 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 9 | sys.path.append(BASE_DIR) 10 | import provider 11 | 12 | parser = argparse.ArgumentParser() 13 | parser.add_argument('--test_area', type=int, default=6, help='The areas except this one will be used to estimate the mean instance size') 14 | FLAGS = parser.parse_args() 15 | 16 | def estimate(area): 17 | LOG_DIR = 'log{}'.format(area) 18 | num_classes = 13 19 | file_path = "data/train_hdf5_file_list_woArea{}.txt".format(area) 20 | 21 | train_file_list = provider.getDataFiles(file_path) 22 | 23 | mean_ins_size = np.zeros(num_classes) 24 | ptsnum_in_gt = [[] for itmp in range(num_classes)] 25 | 26 | train_data = [] 27 | train_group = [] 28 | train_sem = [] 29 | for h5_filename in train_file_list: 30 | cur_data, cur_group, _, cur_sem = provider.loadDataFile_with_groupseglabel_stanfordindoor(h5_filename) 31 | cur_data = np.reshape(cur_data, [-1, cur_data.shape[-1]]) 32 | cur_group = np.reshape(cur_group, [-1]) 33 | cur_sem = np.reshape(cur_sem, [-1]) 34 | 35 | un = np.unique(cur_group) 36 | for ig, g in enumerate(un): 37 | tmp = (cur_group == g) 38 | sem_seg_g = int(stats.mode(cur_sem[tmp])[0]) 39 | ptsnum_in_gt[sem_seg_g].append(np.sum(tmp)) 40 | 41 | for idx in range(num_classes): 42 | mean_ins_size[idx] = np.mean(ptsnum_in_gt[idx]).astype(np.int) 43 | 44 | print(mean_ins_size) 45 | np.savetxt(os.path.join(LOG_DIR, 'mean_ins_size.txt'),mean_ins_size) 46 | 47 | 48 | if __name__ == "__main__": 49 | estimate(FLAGS.test_area) 50 | -------------------------------------------------------------------------------- /gen_h5.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import numpy as np 4 | 5 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 6 | sys.path.append(BASE_DIR) 7 | sys.path.append(os.path.join(BASE_DIR, 'utils')) 8 | import data_prep_util 9 | import indoor3d_util 10 | 11 | 12 | # Constants 13 | data_dir = os.path.join(BASE_DIR, 'data') 14 | indoor3d_data_dir = os.path.join(data_dir, 'stanford_indoor3d_ins.sem') 15 | NUM_POINT = 4096 16 | data_dtype = 'float32' 17 | label_dtype = 'int32' 18 | 19 | # Set paths 20 | filelist = os.path.join(BASE_DIR, 'meta/all_data_label.txt') 21 | data_label_files = [os.path.join(indoor3d_data_dir, line.rstrip()) for line in open(filelist)] 22 | output_dir = os.path.join(data_dir, 'indoor3d_ins_seg_hdf5') 23 | if not os.path.exists(output_dir): 24 | os.mkdir(output_dir) 25 | output_room_filelist = os.path.join(output_dir, 'room_filelist.txt') 26 | fout_room = open(output_room_filelist, 'w') 27 | 28 | sample_cnt = 0 29 | for i in range(0, len(data_label_files)): 30 | data_label_filename = data_label_files[i] 31 | fname = os.path.basename(data_label_filename).strip('.npy') 32 | if not os.path.exists(data_label_filename): 33 | continue 34 | data, label, inslabel = indoor3d_util.room2blocks_wrapper_normalized(data_label_filename, NUM_POINT, block_size=1.0, stride=0.5, 35 | random_sample=False, sample_num=None) 36 | for _ in range(data.shape[0]): 37 | fout_room.write(os.path.basename(data_label_filename)[0:-4]+'\n') 38 | 39 | sample_cnt += data.shape[0] 40 | h5_filename = os.path.join(output_dir, '%s.h5' % fname) 41 | print('{0}: {1}, {2}, {3}'.format(h5_filename, data.shape, label.shape, inslabel.shape)) 42 | data_prep_util.save_h5ins(h5_filename, 43 | data, 44 | label, 45 | inslabel, 46 | data_dtype, label_dtype) 47 | 48 | fout_room.close() 49 | print("Total samples: {0}".format(sample_cnt)) 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Associatively Segmenting Instances and Semantics in Point Clouds 2 | 3 | The full paper is available at: https://arxiv.org/abs/1902.09852. 4 | Qualitative results of ASIS on the S3DIS and vKITTI test fold: 5 | 6 | ![](misc/s3dis_asis.png) 7 | ![](misc/vkitti_asis.png) 8 | 9 | ## Overview 10 | ![](misc/fig.png) 11 | 12 | ## Dependencies 13 | 14 | The code has been tested with Python 2.7 on Ubuntu 14.04. 15 | * [TensorFlow](https://www.tensorflow.org/) 16 | * h5py 17 | 18 | 19 | 20 | ## Data and Model 21 | 22 | * Download 3D indoor parsing dataset ([S3DIS Dataset](https://docs.google.com/forms/d/e/1FAIpQLScDimvNMCGhy_rmBA2gHfDu3naktRm6A8BPwAWWDv-Uhm6Shw/viewform?c=0&w=1)). Version 1.2 of the dataset is used in this work. 23 | 24 | ``` bash 25 | python collect_indoor3d_data.py 26 | python gen_h5.py 27 | cd data && python generate_input_list.py 28 | cd .. 29 | ``` 30 | 31 | * (optional) Trained model can be downloaded from [here](https://drive.google.com/open?id=1UF2nfXdWTOa1iXXmD54_c09rM7pr-kMK). 32 | 33 | ## Usage 34 | 35 | * Compile TF Operators 36 | 37 | Refer to [PointNet++](https://github.com/charlesq34/pointnet2) 38 | 39 | * Training 40 | ``` bash 41 | cd models/ASIS/ 42 | ln -s ../../data . 43 | sh +x train.sh 5 44 | ``` 45 | 46 | * Evaluation 47 | ``` bash 48 | python eval_iou_accuracy.py 49 | ``` 50 | 51 | Note: We test on Area5 and train on the rest folds in default. 6 fold CV can be conducted in a similar way. 52 | 53 | ## Citation 54 | If our work is useful for your research, please consider citing: 55 | 56 | @inproceedings{wang2019asis, 57 | title={Associatively Segmenting Instances and Semantics in Point Clouds}, 58 | author={Wang, Xinlong and Liu, Shu and Shen, Xiaoyong and Shen, Chunhua, and Jia, Jiaya}, 59 | booktitle={CVPR}, 60 | year={2019} 61 | } 62 | 63 | 64 | ## Acknowledgemets 65 | This code largely benefits from following repositories: 66 | [PointNet++](https://github.com/charlesq34/pointnet2), 67 | [SGPN](https://github.com/laughtervv/SGPN), 68 | [DGCNN](https://github.com/WangYueFt/dgcnn) and 69 | [DiscLoss-tf](https://github.com/hq-jiang/instance-segmentation-with-discriminative-loss-tensorflow) 70 | -------------------------------------------------------------------------------- /meta/area2_data_label.txt: -------------------------------------------------------------------------------- 1 | data/stanford_indoor3d_ins.sem/Area_2_auditorium_1.npy 2 | data/stanford_indoor3d_ins.sem/Area_2_auditorium_2.npy 3 | data/stanford_indoor3d_ins.sem/Area_2_conferenceRoom_1.npy 4 | data/stanford_indoor3d_ins.sem/Area_2_hallway_10.npy 5 | data/stanford_indoor3d_ins.sem/Area_2_hallway_11.npy 6 | data/stanford_indoor3d_ins.sem/Area_2_hallway_12.npy 7 | data/stanford_indoor3d_ins.sem/Area_2_hallway_1.npy 8 | data/stanford_indoor3d_ins.sem/Area_2_hallway_2.npy 9 | data/stanford_indoor3d_ins.sem/Area_2_hallway_3.npy 10 | data/stanford_indoor3d_ins.sem/Area_2_hallway_4.npy 11 | data/stanford_indoor3d_ins.sem/Area_2_hallway_5.npy 12 | data/stanford_indoor3d_ins.sem/Area_2_hallway_6.npy 13 | data/stanford_indoor3d_ins.sem/Area_2_hallway_7.npy 14 | data/stanford_indoor3d_ins.sem/Area_2_hallway_8.npy 15 | data/stanford_indoor3d_ins.sem/Area_2_hallway_9.npy 16 | data/stanford_indoor3d_ins.sem/Area_2_office_10.npy 17 | data/stanford_indoor3d_ins.sem/Area_2_office_11.npy 18 | data/stanford_indoor3d_ins.sem/Area_2_office_12.npy 19 | data/stanford_indoor3d_ins.sem/Area_2_office_13.npy 20 | data/stanford_indoor3d_ins.sem/Area_2_office_14.npy 21 | data/stanford_indoor3d_ins.sem/Area_2_office_1.npy 22 | data/stanford_indoor3d_ins.sem/Area_2_office_2.npy 23 | data/stanford_indoor3d_ins.sem/Area_2_office_3.npy 24 | data/stanford_indoor3d_ins.sem/Area_2_office_4.npy 25 | data/stanford_indoor3d_ins.sem/Area_2_office_5.npy 26 | data/stanford_indoor3d_ins.sem/Area_2_office_6.npy 27 | data/stanford_indoor3d_ins.sem/Area_2_office_7.npy 28 | data/stanford_indoor3d_ins.sem/Area_2_office_8.npy 29 | data/stanford_indoor3d_ins.sem/Area_2_office_9.npy 30 | data/stanford_indoor3d_ins.sem/Area_2_storage_1.npy 31 | data/stanford_indoor3d_ins.sem/Area_2_storage_2.npy 32 | data/stanford_indoor3d_ins.sem/Area_2_storage_3.npy 33 | data/stanford_indoor3d_ins.sem/Area_2_storage_4.npy 34 | data/stanford_indoor3d_ins.sem/Area_2_storage_5.npy 35 | data/stanford_indoor3d_ins.sem/Area_2_storage_6.npy 36 | data/stanford_indoor3d_ins.sem/Area_2_storage_7.npy 37 | data/stanford_indoor3d_ins.sem/Area_2_storage_8.npy 38 | data/stanford_indoor3d_ins.sem/Area_2_storage_9.npy 39 | data/stanford_indoor3d_ins.sem/Area_2_WC_1.npy 40 | data/stanford_indoor3d_ins.sem/Area_2_WC_2.npy 41 | -------------------------------------------------------------------------------- /tf_ops/grouping/test/selection_sort.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | 18 | // input: k (1), distance matrix dist (b,m,n) 19 | // output: idx (b,m,k), val (b,m,k) 20 | __global__ void selection_sort_gpu(int b, int n, int m, int k, float *dist, int *idx, float *val) { 21 | int batch_index = blockIdx.x; 22 | dist+=m*n*batch_index; 23 | idx+=m*k*batch_index; 24 | val+=m*k*batch_index; 25 | 26 | int index = threadIdx.x; 27 | int stride = blockDim.x; 28 | 29 | float *p_dist; 30 | for (int j=index;j>>(b,n,m,k,dist,idx,val); 68 | cudaDeviceSynchronize(); 69 | printf("selection sort cpu time %f\n",get_time()-t0); 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /tf_ops/3d_interpolation/tf_interpolate.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from tensorflow.python.framework import ops 3 | import sys 4 | import os 5 | BASE_DIR = os.path.dirname(__file__) 6 | sys.path.append(BASE_DIR) 7 | interpolate_module=tf.load_op_library(os.path.join(BASE_DIR, 'tf_interpolate_so.so')) 8 | def three_nn(xyz1, xyz2): 9 | ''' 10 | Input: 11 | xyz1: (b,n,3) float32 array, unknown points 12 | xyz2: (b,m,3) float32 array, known points 13 | Output: 14 | dist: (b,n,3) float32 array, distances to known points 15 | idx: (b,n,3) int32 array, indices to known points 16 | ''' 17 | return interpolate_module.three_nn(xyz1, xyz2) 18 | ops.NoGradient('ThreeNN') 19 | def three_interpolate(points, idx, weight): 20 | ''' 21 | Input: 22 | points: (b,m,c) float32 array, known points 23 | idx: (b,n,3) int32 array, indices to known points 24 | weight: (b,n,3) float32 array, weights on known points 25 | Output: 26 | out: (b,n,c) float32 array, interpolated point values 27 | ''' 28 | return interpolate_module.three_interpolate(points, idx, weight) 29 | @tf.RegisterGradient('ThreeInterpolate') 30 | def _three_interpolate_grad(op, grad_out): 31 | points = op.inputs[0] 32 | idx = op.inputs[1] 33 | weight = op.inputs[2] 34 | return [interpolate_module.three_interpolate_grad(points, idx, weight, grad_out), None, None] 35 | 36 | if __name__=='__main__': 37 | import numpy as np 38 | import time 39 | np.random.seed(100) 40 | pts = np.random.random((32,128,64)).astype('float32') 41 | tmp1 = np.random.random((32,512,3)).astype('float32') 42 | tmp2 = np.random.random((32,128,3)).astype('float32') 43 | with tf.device('/cpu:0'): 44 | points = tf.constant(pts) 45 | xyz1 = tf.constant(tmp1) 46 | xyz2 = tf.constant(tmp2) 47 | dist, idx = three_nn(xyz1, xyz2) 48 | weight = tf.ones_like(dist)/3.0 49 | interpolated_points = three_interpolate(points, idx, weight) 50 | with tf.Session('') as sess: 51 | now = time.time() 52 | for _ in range(100): 53 | ret = sess.run(interpolated_points) 54 | print time.time() - now 55 | print ret.shape, ret.dtype 56 | #print ret 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /utils/clustering.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from sklearn.cluster import MeanShift, estimate_bandwidth 4 | import time 5 | import cv2 6 | 7 | COLOR=[np.array([255,0,0]), 8 | np.array([0,255,0]), 9 | np.array([0,0,255]), 10 | np.array([125,125,0]), 11 | np.array([0,125,125]), 12 | np.array([125,0,125]), 13 | np.array([50,100,50]), 14 | np.array([100,50,100])] 15 | 16 | def cluster(prediction, bandwidth): 17 | ms = MeanShift(bandwidth, bin_seeding=True) 18 | #print ('Mean shift clustering, might take some time ...') 19 | #tic = time.time() 20 | ms.fit(prediction) 21 | #print ('time for clustering', time.time() - tic) 22 | labels = ms.labels_ 23 | cluster_centers = ms.cluster_centers_ 24 | 25 | num_clusters = cluster_centers.shape[0] 26 | 27 | return num_clusters, labels, cluster_centers 28 | 29 | def get_instance_masks(prediction, bandwidth): 30 | batch_size, h, w, feature_dim = prediction.shape 31 | 32 | instance_masks = [] 33 | for i in range(batch_size): 34 | num_clusters, labels, cluster_centers = cluster(prediction[i].reshape([h*w, feature_dim]), bandwidth) 35 | print ('Number of predicted clusters', num_clusters) 36 | labels = np.array(labels, dtype=np.uint8).reshape([h,w]) 37 | mask = np.zeros([h,w,3], dtype=np.uint8) 38 | 39 | num_clusters = min([num_clusters,8]) 40 | for mask_id in range(num_clusters): 41 | ind = np.where(labels==mask_id) 42 | mask[ind] = COLOR[mask_id] 43 | 44 | 45 | instance_masks.append(mask) 46 | 47 | return instance_masks 48 | 49 | 50 | def save_instance_masks(prediction,output_dir, bandwidth, count): 51 | batch_size, h, w, feature_dim = prediction.shape 52 | 53 | instance_masks = [] 54 | for i in range(batch_size): 55 | num_clusters, labels, cluster_centers = cluster(prediction[i].reshape([h*w, feature_dim]), bandwidth) 56 | print ('Number of predicted clusters', num_clusters) 57 | labels = np.array(labels, dtype=np.uint8).reshape([h,w]) 58 | mask = np.zeros([h,w,3], dtype=np.uint8) 59 | 60 | num_clusters = min([num_clusters,8]) 61 | for mask_id in range(num_clusters): 62 | mask = np.zeros([h,w,3], dtype=np.uint8) 63 | ind = np.where(labels==mask_id) 64 | mask[ind] = np.array([255,255,255]) 65 | output_file_name = os.path.join(output_dir, 'cluster_{}_{}.png'.format(str(count).zfill(4), str(mask_id))) 66 | cv2.imwrite(output_file_name, mask) 67 | 68 | 69 | instance_masks.append(mask) 70 | 71 | return instance_masks 72 | -------------------------------------------------------------------------------- /meta/area1_data_label.txt: -------------------------------------------------------------------------------- 1 | data/stanford_indoor3d_ins.sem/Area_1_conferenceRoom_1.npy 2 | data/stanford_indoor3d_ins.sem/Area_1_conferenceRoom_2.npy 3 | data/stanford_indoor3d_ins.sem/Area_1_copyRoom_1.npy 4 | data/stanford_indoor3d_ins.sem/Area_1_hallway_1.npy 5 | data/stanford_indoor3d_ins.sem/Area_1_hallway_2.npy 6 | data/stanford_indoor3d_ins.sem/Area_1_hallway_3.npy 7 | data/stanford_indoor3d_ins.sem/Area_1_hallway_4.npy 8 | data/stanford_indoor3d_ins.sem/Area_1_hallway_5.npy 9 | data/stanford_indoor3d_ins.sem/Area_1_hallway_6.npy 10 | data/stanford_indoor3d_ins.sem/Area_1_hallway_7.npy 11 | data/stanford_indoor3d_ins.sem/Area_1_hallway_8.npy 12 | data/stanford_indoor3d_ins.sem/Area_1_office_10.npy 13 | data/stanford_indoor3d_ins.sem/Area_1_office_11.npy 14 | data/stanford_indoor3d_ins.sem/Area_1_office_12.npy 15 | data/stanford_indoor3d_ins.sem/Area_1_office_13.npy 16 | data/stanford_indoor3d_ins.sem/Area_1_office_14.npy 17 | data/stanford_indoor3d_ins.sem/Area_1_office_15.npy 18 | data/stanford_indoor3d_ins.sem/Area_1_office_16.npy 19 | data/stanford_indoor3d_ins.sem/Area_1_office_17.npy 20 | data/stanford_indoor3d_ins.sem/Area_1_office_18.npy 21 | data/stanford_indoor3d_ins.sem/Area_1_office_19.npy 22 | data/stanford_indoor3d_ins.sem/Area_1_office_1.npy 23 | data/stanford_indoor3d_ins.sem/Area_1_office_20.npy 24 | data/stanford_indoor3d_ins.sem/Area_1_office_21.npy 25 | data/stanford_indoor3d_ins.sem/Area_1_office_22.npy 26 | data/stanford_indoor3d_ins.sem/Area_1_office_23.npy 27 | data/stanford_indoor3d_ins.sem/Area_1_office_24.npy 28 | data/stanford_indoor3d_ins.sem/Area_1_office_25.npy 29 | data/stanford_indoor3d_ins.sem/Area_1_office_26.npy 30 | data/stanford_indoor3d_ins.sem/Area_1_office_27.npy 31 | data/stanford_indoor3d_ins.sem/Area_1_office_28.npy 32 | data/stanford_indoor3d_ins.sem/Area_1_office_29.npy 33 | data/stanford_indoor3d_ins.sem/Area_1_office_2.npy 34 | data/stanford_indoor3d_ins.sem/Area_1_office_30.npy 35 | data/stanford_indoor3d_ins.sem/Area_1_office_31.npy 36 | data/stanford_indoor3d_ins.sem/Area_1_office_3.npy 37 | data/stanford_indoor3d_ins.sem/Area_1_office_4.npy 38 | data/stanford_indoor3d_ins.sem/Area_1_office_5.npy 39 | data/stanford_indoor3d_ins.sem/Area_1_office_6.npy 40 | data/stanford_indoor3d_ins.sem/Area_1_office_7.npy 41 | data/stanford_indoor3d_ins.sem/Area_1_office_8.npy 42 | data/stanford_indoor3d_ins.sem/Area_1_office_9.npy 43 | data/stanford_indoor3d_ins.sem/Area_1_pantry_1.npy 44 | data/stanford_indoor3d_ins.sem/Area_1_WC_1.npy 45 | -------------------------------------------------------------------------------- /meta/area6_data_label.txt: -------------------------------------------------------------------------------- 1 | data/stanford_indoor3d_ins.sem/Area_6_conferenceRoom_1.npy 2 | data/stanford_indoor3d_ins.sem/Area_6_copyRoom_1.npy 3 | data/stanford_indoor3d_ins.sem/Area_6_hallway_1.npy 4 | data/stanford_indoor3d_ins.sem/Area_6_hallway_2.npy 5 | data/stanford_indoor3d_ins.sem/Area_6_hallway_3.npy 6 | data/stanford_indoor3d_ins.sem/Area_6_hallway_4.npy 7 | data/stanford_indoor3d_ins.sem/Area_6_hallway_5.npy 8 | data/stanford_indoor3d_ins.sem/Area_6_hallway_6.npy 9 | data/stanford_indoor3d_ins.sem/Area_6_lounge_1.npy 10 | data/stanford_indoor3d_ins.sem/Area_6_office_10.npy 11 | data/stanford_indoor3d_ins.sem/Area_6_office_11.npy 12 | data/stanford_indoor3d_ins.sem/Area_6_office_12.npy 13 | data/stanford_indoor3d_ins.sem/Area_6_office_13.npy 14 | data/stanford_indoor3d_ins.sem/Area_6_office_14.npy 15 | data/stanford_indoor3d_ins.sem/Area_6_office_15.npy 16 | data/stanford_indoor3d_ins.sem/Area_6_office_16.npy 17 | data/stanford_indoor3d_ins.sem/Area_6_office_17.npy 18 | data/stanford_indoor3d_ins.sem/Area_6_office_18.npy 19 | data/stanford_indoor3d_ins.sem/Area_6_office_19.npy 20 | data/stanford_indoor3d_ins.sem/Area_6_office_1.npy 21 | data/stanford_indoor3d_ins.sem/Area_6_office_20.npy 22 | data/stanford_indoor3d_ins.sem/Area_6_office_21.npy 23 | data/stanford_indoor3d_ins.sem/Area_6_office_22.npy 24 | data/stanford_indoor3d_ins.sem/Area_6_office_23.npy 25 | data/stanford_indoor3d_ins.sem/Area_6_office_24.npy 26 | data/stanford_indoor3d_ins.sem/Area_6_office_25.npy 27 | data/stanford_indoor3d_ins.sem/Area_6_office_26.npy 28 | data/stanford_indoor3d_ins.sem/Area_6_office_27.npy 29 | data/stanford_indoor3d_ins.sem/Area_6_office_28.npy 30 | data/stanford_indoor3d_ins.sem/Area_6_office_29.npy 31 | data/stanford_indoor3d_ins.sem/Area_6_office_2.npy 32 | data/stanford_indoor3d_ins.sem/Area_6_office_30.npy 33 | data/stanford_indoor3d_ins.sem/Area_6_office_31.npy 34 | data/stanford_indoor3d_ins.sem/Area_6_office_32.npy 35 | data/stanford_indoor3d_ins.sem/Area_6_office_33.npy 36 | data/stanford_indoor3d_ins.sem/Area_6_office_34.npy 37 | data/stanford_indoor3d_ins.sem/Area_6_office_35.npy 38 | data/stanford_indoor3d_ins.sem/Area_6_office_36.npy 39 | data/stanford_indoor3d_ins.sem/Area_6_office_37.npy 40 | data/stanford_indoor3d_ins.sem/Area_6_office_3.npy 41 | data/stanford_indoor3d_ins.sem/Area_6_office_4.npy 42 | data/stanford_indoor3d_ins.sem/Area_6_office_5.npy 43 | data/stanford_indoor3d_ins.sem/Area_6_office_6.npy 44 | data/stanford_indoor3d_ins.sem/Area_6_office_7.npy 45 | data/stanford_indoor3d_ins.sem/Area_6_office_8.npy 46 | data/stanford_indoor3d_ins.sem/Area_6_office_9.npy 47 | data/stanford_indoor3d_ins.sem/Area_6_openspace_1.npy 48 | data/stanford_indoor3d_ins.sem/Area_6_pantry_1.npy 49 | -------------------------------------------------------------------------------- /meta/area4_data_label.txt: -------------------------------------------------------------------------------- 1 | data/stanford_indoor3d_ins.sem/Area_4_conferenceRoom_1.npy 2 | data/stanford_indoor3d_ins.sem/Area_4_conferenceRoom_2.npy 3 | data/stanford_indoor3d_ins.sem/Area_4_conferenceRoom_3.npy 4 | data/stanford_indoor3d_ins.sem/Area_4_hallway_10.npy 5 | data/stanford_indoor3d_ins.sem/Area_4_hallway_11.npy 6 | data/stanford_indoor3d_ins.sem/Area_4_hallway_12.npy 7 | data/stanford_indoor3d_ins.sem/Area_4_hallway_13.npy 8 | data/stanford_indoor3d_ins.sem/Area_4_hallway_14.npy 9 | data/stanford_indoor3d_ins.sem/Area_4_hallway_1.npy 10 | data/stanford_indoor3d_ins.sem/Area_4_hallway_2.npy 11 | data/stanford_indoor3d_ins.sem/Area_4_hallway_3.npy 12 | data/stanford_indoor3d_ins.sem/Area_4_hallway_4.npy 13 | data/stanford_indoor3d_ins.sem/Area_4_hallway_5.npy 14 | data/stanford_indoor3d_ins.sem/Area_4_hallway_6.npy 15 | data/stanford_indoor3d_ins.sem/Area_4_hallway_7.npy 16 | data/stanford_indoor3d_ins.sem/Area_4_hallway_8.npy 17 | data/stanford_indoor3d_ins.sem/Area_4_hallway_9.npy 18 | data/stanford_indoor3d_ins.sem/Area_4_lobby_1.npy 19 | data/stanford_indoor3d_ins.sem/Area_4_lobby_2.npy 20 | data/stanford_indoor3d_ins.sem/Area_4_office_10.npy 21 | data/stanford_indoor3d_ins.sem/Area_4_office_11.npy 22 | data/stanford_indoor3d_ins.sem/Area_4_office_12.npy 23 | data/stanford_indoor3d_ins.sem/Area_4_office_13.npy 24 | data/stanford_indoor3d_ins.sem/Area_4_office_14.npy 25 | data/stanford_indoor3d_ins.sem/Area_4_office_15.npy 26 | data/stanford_indoor3d_ins.sem/Area_4_office_16.npy 27 | data/stanford_indoor3d_ins.sem/Area_4_office_17.npy 28 | data/stanford_indoor3d_ins.sem/Area_4_office_18.npy 29 | data/stanford_indoor3d_ins.sem/Area_4_office_19.npy 30 | data/stanford_indoor3d_ins.sem/Area_4_office_1.npy 31 | data/stanford_indoor3d_ins.sem/Area_4_office_20.npy 32 | data/stanford_indoor3d_ins.sem/Area_4_office_21.npy 33 | data/stanford_indoor3d_ins.sem/Area_4_office_22.npy 34 | data/stanford_indoor3d_ins.sem/Area_4_office_2.npy 35 | data/stanford_indoor3d_ins.sem/Area_4_office_3.npy 36 | data/stanford_indoor3d_ins.sem/Area_4_office_4.npy 37 | data/stanford_indoor3d_ins.sem/Area_4_office_5.npy 38 | data/stanford_indoor3d_ins.sem/Area_4_office_6.npy 39 | data/stanford_indoor3d_ins.sem/Area_4_office_7.npy 40 | data/stanford_indoor3d_ins.sem/Area_4_office_8.npy 41 | data/stanford_indoor3d_ins.sem/Area_4_office_9.npy 42 | data/stanford_indoor3d_ins.sem/Area_4_storage_1.npy 43 | data/stanford_indoor3d_ins.sem/Area_4_storage_2.npy 44 | data/stanford_indoor3d_ins.sem/Area_4_storage_3.npy 45 | data/stanford_indoor3d_ins.sem/Area_4_storage_4.npy 46 | data/stanford_indoor3d_ins.sem/Area_4_WC_1.npy 47 | data/stanford_indoor3d_ins.sem/Area_4_WC_2.npy 48 | data/stanford_indoor3d_ins.sem/Area_4_WC_3.npy 49 | data/stanford_indoor3d_ins.sem/Area_4_WC_4.npy 50 | -------------------------------------------------------------------------------- /tf_ops/grouping/test/selection_sort_const.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | 18 | // input: k (1), distance matrix dist (b,m,n) 19 | // output: idx (b,m,n), dist_out (b,m,n) 20 | __global__ void selection_sort_gpu(int b, int n, int m, int k, const float *dist, int *outi, float *out) { 21 | int batch_index = blockIdx.x; 22 | dist+=m*n*batch_index; 23 | outi+=m*n*batch_index; 24 | out+=m*n*batch_index; 25 | 26 | int index = threadIdx.x; 27 | int stride = blockDim.x; 28 | 29 | // copy from dist to dist_out 30 | for (int j=index;j>>(b,n,m,k,dist,idx,dist_out); 84 | cudaDeviceSynchronize(); 85 | printf("selection sort cpu time %f\n",get_time()-t0); 86 | 87 | //for (int i=0;i 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | 18 | // input: k (1), distance matrix dist (b,m,n) 19 | // output: idx (b,m,n), val (b,m,n) 20 | void selection_sort_cpu(int b, int n, int m, int k, const float *dist, int *idx, float *val) { 21 | float *p_dist; 22 | float tmp; 23 | int tmpi; 24 | for (int i=0;i 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 18 | // output: idx (b,m,nsample) 19 | void query_ball_point_cpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) { 20 | for (int i=0;i 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 18 | // output: idx (b,m,nsample) 19 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) { 20 | int index = threadIdx.x; 21 | xyz1 += n*3*index; 22 | xyz2 += m*3*index; 23 | idx += m*nsample*index; 24 | 25 | for (int j=0;j>>(b,n,m,radius,nsample,xyz1,xyz2,idx); 113 | cudaDeviceSynchronize(); 114 | printf("query_ball_point gpu time %f\n",get_time()-t0); 115 | 116 | t0=get_time(); 117 | group_point_gpu<<<1,b>>>(b,n,c,m,nsample,points,idx,out); 118 | cudaDeviceSynchronize(); 119 | printf("grou_point gpu time %f\n",get_time()-t0); 120 | 121 | t0=get_time(); 122 | group_point_grad_gpu<<<1,b>>>(b,n,c,m,nsample,grad_out,idx,grad_points); 123 | cudaDeviceSynchronize(); 124 | printf("grou_point_grad gpu time %f\n",get_time()-t0); 125 | 126 | cudaFree(xyz1); 127 | cudaFree(xyz2); 128 | cudaFree(points); 129 | cudaFree(idx); 130 | cudaFree(out); 131 | cudaFree(grad_out); 132 | cudaFree(grad_points); 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /tf_ops/grouping/test/query_ball_point.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 18 | // output: idx (b,m,nsample) 19 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) { 20 | for (int i=0;i>>(b,n,m,radius,nsample,xyz1,xyz2,idx); 113 | cudaDeviceSynchronize(); 114 | printf("query_ball_point gpu time %f\n",get_time()-t0); 115 | 116 | t0=get_time(); 117 | group_point_gpu<<<1,1>>>(b,n,c,m,nsample,points,idx,out); 118 | cudaDeviceSynchronize(); 119 | printf("grou_point gpu time %f\n",get_time()-t0); 120 | 121 | t0=get_time(); 122 | group_point_grad_gpu<<<1,1>>>(b,n,c,m,nsample,grad_out,idx,grad_points); 123 | cudaDeviceSynchronize(); 124 | printf("grou_point_grad gpu time %f\n",get_time()-t0); 125 | 126 | cudaFree(xyz1); 127 | cudaFree(xyz2); 128 | cudaFree(points); 129 | cudaFree(idx); 130 | cudaFree(out); 131 | cudaFree(grad_out); 132 | cudaFree(grad_points); 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /tf_ops/grouping/test/query_ball_point_grid.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 18 | // output: idx (b,m,nsample) 19 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) { 20 | int batch_index = blockIdx.x; 21 | xyz1 += n*3*batch_index; 22 | xyz2 += m*3*batch_index; 23 | idx += m*nsample*batch_index; 24 | 25 | int index = threadIdx.x; 26 | int stride = blockDim.x; 27 | 28 | for (int j=index;j>>(b,n,m,radius,nsample,xyz1,xyz2,idx); 123 | cudaDeviceSynchronize(); 124 | printf("query_ball_point gpu time %f\n",get_time()-t0); 125 | 126 | t0=get_time(); 127 | group_point_gpu<<>>(b,n,c,m,nsample,points,idx,out); 128 | cudaDeviceSynchronize(); 129 | printf("grou_point gpu time %f\n",get_time()-t0); 130 | 131 | t0=get_time(); 132 | group_point_grad_gpu<<>>(b,n,c,m,nsample,grad_out,idx,grad_points); 133 | cudaDeviceSynchronize(); 134 | printf("grou_point_grad gpu time %f\n",get_time()-t0); 135 | 136 | cudaFree(xyz1); 137 | cudaFree(xyz2); 138 | cudaFree(points); 139 | cudaFree(idx); 140 | cudaFree(out); 141 | cudaFree(grad_out); 142 | cudaFree(grad_points); 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /models/ASIS/model.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | BASE_DIR = os.path.dirname(__file__) 4 | sys.path.append(BASE_DIR) 5 | sys.path.append(os.path.join(BASE_DIR, '../utils')) 6 | import tensorflow as tf 7 | import numpy as np 8 | import tf_util 9 | from pointnet_util import pointnet_sa_module, pointnet_fp_module 10 | from loss import * 11 | 12 | def placeholder_inputs(batch_size, num_point): 13 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 9)) 14 | labels_pl = tf.placeholder(tf.int32, shape=(batch_size, num_point)) 15 | sem_pl = tf.placeholder(tf.int32, shape=(batch_size, num_point)) 16 | return pointclouds_pl, labels_pl, sem_pl 17 | 18 | 19 | def get_model(point_cloud, is_training, num_class, bn_decay=None): 20 | """ Semantic segmentation PointNet, input is BxNx3, output Bxnum_class """ 21 | batch_size = point_cloud.get_shape()[0].value 22 | num_point = point_cloud.get_shape()[1].value 23 | end_points = {} 24 | l0_xyz = point_cloud[:, :, :3] 25 | l0_points = point_cloud[:, :, 3:] 26 | end_points['l0_xyz'] = l0_xyz 27 | 28 | # Layer 1 29 | l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=1024, radius=0.1, nsample=32, mlp=[32,32,64], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer1') 30 | l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=256, radius=0.2, nsample=32, mlp=[64,64,128], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer2') 31 | l3_xyz, l3_points, l3_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=64, radius=0.4, nsample=32, mlp=[128,128,256], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer3') 32 | l4_xyz, l4_points, l4_indices = pointnet_sa_module(l3_xyz, l3_points, npoint=16, radius=0.8, nsample=32, mlp=[256,256,512], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer4') 33 | 34 | # Feature Propagation layers 35 | l3_points_sem = pointnet_fp_module(l3_xyz, l4_xyz, l3_points, l4_points, [256,256], is_training, bn_decay, scope='sem_fa_layer1') 36 | l2_points_sem = pointnet_fp_module(l2_xyz, l3_xyz, l2_points, l3_points_sem, [256,256], is_training, bn_decay, scope='sem_fa_layer2') 37 | l1_points_sem = pointnet_fp_module(l1_xyz, l2_xyz, l1_points, l2_points_sem, [256,128], is_training, bn_decay, scope='sem_fa_layer3') 38 | l0_points_sem = pointnet_fp_module(l0_xyz, l1_xyz, l0_points, l1_points_sem, [128,128,128], is_training, bn_decay, scope='sem_fa_layer4') 39 | 40 | # FC layers 41 | net_sem = tf_util.conv1d(l0_points_sem, 128, 1, padding='VALID', bn=True, is_training=is_training, scope='sem_fc1', bn_decay=bn_decay) 42 | net_sem_cache = tf_util.conv1d(net_sem, 128, 1, padding='VALID', bn=True, is_training=is_training, scope='sem_cache', bn_decay=bn_decay) 43 | 44 | # ins 45 | l3_points_ins = pointnet_fp_module(l3_xyz, l4_xyz, l3_points, l4_points, [256,256], is_training, bn_decay, scope='ins_fa_layer1') 46 | l2_points_ins = pointnet_fp_module(l2_xyz, l3_xyz, l2_points, l3_points_ins, [256,256], is_training, bn_decay, scope='ins_fa_layer2') 47 | l1_points_ins = pointnet_fp_module(l1_xyz, l2_xyz, l1_points, l2_points_ins, [256,128], is_training, bn_decay, scope='ins_fa_layer3') 48 | l0_points_ins = pointnet_fp_module(l0_xyz, l1_xyz, l0_points, l1_points_ins, [128,128,128], is_training, bn_decay, scope='ins_fa_layer4') 49 | 50 | net_ins = tf_util.conv1d(l0_points_ins, 128, 1, padding='VALID', bn=True, is_training=is_training, scope='ins_fc1', bn_decay=bn_decay) 51 | 52 | net_ins = net_ins + net_sem_cache 53 | net_ins = tf_util.dropout(net_ins, keep_prob=0.5, is_training=is_training, scope='ins_dp1') 54 | net_ins = tf_util.conv1d(net_ins, 5, 1, padding='VALID', activation_fn=None, scope='ins_fc4') 55 | 56 | k = 30 57 | adj_matrix = tf_util.pairwise_distance_l1(net_ins) 58 | nn_idx = tf_util.knn_thres(adj_matrix, k=k) 59 | nn_idx = tf.stop_gradient(nn_idx) 60 | 61 | net_sem = tf_util.get_local_feature(net_sem, nn_idx=nn_idx, k=k)# [b, n, k, c] 62 | net_sem = tf.reduce_max(net_sem, axis=-2, keep_dims=False) 63 | 64 | net_sem = tf_util.dropout(net_sem, keep_prob=0.5, is_training=is_training, scope='sem_dp1') 65 | net_sem = tf_util.conv1d(net_sem, num_class, 1, padding='VALID', activation_fn=None, scope='sem_fc4') 66 | 67 | 68 | return net_sem, net_ins 69 | 70 | 71 | def get_loss(pred, ins_label, pred_sem_label, pred_sem, sem_label): 72 | """ pred: BxNxE, 73 | ins_label: BxN 74 | pred_sem_label: BxN 75 | pred_sem: BxNx13 76 | sem_label: BxN 77 | """ 78 | classify_loss = tf.losses.sparse_softmax_cross_entropy(labels=sem_label, logits=pred_sem) 79 | tf.summary.scalar('classify loss', classify_loss) 80 | 81 | feature_dim = pred.get_shape()[-1] 82 | delta_v = 0.5 83 | delta_d = 1.5 84 | param_var = 1. 85 | param_dist = 1. 86 | param_reg = 0.001 87 | 88 | disc_loss, l_var, l_dist, l_reg = discriminative_loss(pred, ins_label, feature_dim, 89 | delta_v, delta_d, param_var, param_dist, param_reg) 90 | 91 | loss = classify_loss + disc_loss 92 | 93 | tf.add_to_collection('losses', loss) 94 | return loss, classify_loss, disc_loss, l_var, l_dist, l_reg 95 | 96 | if __name__=='__main__': 97 | with tf.Graph().as_default(): 98 | inputs = tf.zeros((32,2048,3)) 99 | net, _ = get_model(inputs, tf.constant(True), 10) 100 | print(net) 101 | -------------------------------------------------------------------------------- /tf_ops/grouping/tf_grouping_g.cu: -------------------------------------------------------------------------------- 1 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 2 | // output: idx (b,m,nsample), pts_cnt (b,m) 3 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx, int *pts_cnt) { 4 | int batch_index = blockIdx.x; 5 | xyz1 += n*3*batch_index; 6 | xyz2 += m*3*batch_index; 7 | idx += m*nsample*batch_index; 8 | pts_cnt += m*batch_index; // counting how many unique points selected in local region 9 | 10 | int index = threadIdx.x; 11 | int stride = blockDim.x; 12 | 13 | for (int j=index;j>>(b,n,m,radius,nsample,xyz1,xyz2,idx,pts_cnt); 127 | //cudaDeviceSynchronize(); 128 | } 129 | void selectionSortLauncher(int b, int n, int m, int k, const float *dist, int *outi, float *out) { 130 | selection_sort_gpu<<>>(b,n,m,k,dist,outi,out); 131 | //cudaDeviceSynchronize(); 132 | } 133 | void groupPointLauncher(int b, int n, int c, int m, int nsample, const float *points, const int *idx, float *out){ 134 | group_point_gpu<<>>(b,n,c,m,nsample,points,idx,out); 135 | //cudaDeviceSynchronize(); 136 | } 137 | void groupPointGradLauncher(int b, int n, int c, int m, int nsample, const float *grad_out, const int *idx, float *grad_points){ 138 | group_point_grad_gpu<<>>(b,n,c,m,nsample,grad_out,idx,grad_points); 139 | //group_point_grad_gpu<<<1,1>>>(b,n,c,m,nsample,grad_out,idx,grad_points); 140 | //cudaDeviceSynchronize(); 141 | } 142 | -------------------------------------------------------------------------------- /tf_ops/3d_interpolation/interpolate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | 18 | // Find three nearest neigbors with square distance 19 | // input: xyz1 (b,n,3), xyz2(b,m,3) 20 | // output: dist (b,n,3), idx (b,n,3) 21 | void threenn_cpu(int b, int n, int m, const float *xyz1, const float *xyz2, float *dist, int *idx) { 22 | for (int i=0;i 0) 129 | dx = mask[:, 0] 130 | dy = mask[:, 1] 131 | dv = disk[disk > 0] 132 | 133 | # Order points by z-buffer 134 | zorder = np.argsort(points[:, 2]) 135 | points = points[zorder, :] 136 | points[:, 2] = (points[:, 2] - np.min(points[:, 2])) / (np.max(points[:, 2] - np.min(points[:, 2]))) 137 | max_depth = np.max(points[:, 2]) 138 | 139 | for i in range(points.shape[0]): 140 | j = points.shape[0] - i - 1 141 | x = points[j, 0] 142 | y = points[j, 1] 143 | xc = canvasSize/2 + (x*space) 144 | yc = canvasSize/2 + (y*space) 145 | xc = int(np.round(xc)) 146 | yc = int(np.round(yc)) 147 | 148 | px = dx + xc 149 | py = dy + yc 150 | 151 | image[px, py] = image[px, py] * 0.7 + dv * (max_depth - points[j, 2]) * 0.3 152 | 153 | image = image / np.max(image) 154 | return image 155 | 156 | def point_cloud_three_views(points): 157 | """ input points Nx3 numpy array (+y is up direction). 158 | return an numpy array gray image of size 500x1500. """ 159 | # +y is up direction 160 | # xrot is azimuth 161 | # yrot is in-plane 162 | # zrot is elevation 163 | img1 = draw_point_cloud(points, zrot=110/180.0*np.pi, xrot=45/180.0*np.pi, yrot=0/180.0*np.pi) 164 | img2 = draw_point_cloud(points, zrot=70/180.0*np.pi, xrot=135/180.0*np.pi, yrot=0/180.0*np.pi) 165 | img3 = draw_point_cloud(points, zrot=180.0/180.0*np.pi, xrot=90/180.0*np.pi, yrot=0/180.0*np.pi) 166 | image_large = np.concatenate([img1, img2, img3], 1) 167 | return image_large 168 | 169 | 170 | from PIL import Image 171 | def point_cloud_three_views_demo(): 172 | """ Demo for draw_point_cloud function """ 173 | points = read_ply('../third_party/mesh_sampling/piano.ply') 174 | im_array = point_cloud_three_views(points) 175 | img = Image.fromarray(np.uint8(im_array*255.0)) 176 | img.save('piano.jpg') 177 | 178 | if __name__=="__main__": 179 | point_cloud_three_views_demo() 180 | 181 | 182 | import matplotlib.pyplot as plt 183 | def pyplot_draw_point_cloud(points, output_filename): 184 | """ points is a Nx3 numpy array """ 185 | fig = plt.figure() 186 | ax = fig.add_subplot(111, projection='3d') 187 | ax.scatter(points[:,0], points[:,1], points[:,2]) 188 | ax.set_xlabel('x') 189 | ax.set_ylabel('y') 190 | ax.set_zlabel('z') 191 | #savefig(output_filename) 192 | 193 | def pyplot_draw_volume(vol, output_filename): 194 | """ vol is of size vsize*vsize*vsize 195 | output an image to output_filename 196 | """ 197 | points = volume_to_point_cloud(vol) 198 | pyplot_draw_point_cloud(points, output_filename) 199 | -------------------------------------------------------------------------------- /models/ASIS/eval_iou_accuracy.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from scipy import stats 4 | 5 | NUM_CLASSES = 13 6 | 7 | pred_data_label_filenames = [] 8 | for i in range(5,6): 9 | file_name = 'log{}_test/output_filelist.txt'.format(i) 10 | pred_data_label_filenames += [line.rstrip() for line in open(file_name)] 11 | 12 | gt_label_filenames = [f.rstrip('_pred\.txt') + '_gt.txt' for f in pred_data_label_filenames] 13 | 14 | num_room = len(gt_label_filenames) 15 | 16 | # Initialize... 17 | # acc and macc 18 | total_true = 0 19 | total_seen = 0 20 | true_positive_classes = np.zeros(NUM_CLASSES) 21 | positive_classes = np.zeros(NUM_CLASSES) 22 | gt_classes = np.zeros(NUM_CLASSES) 23 | # mIoU 24 | ious = np.zeros(NUM_CLASSES) 25 | totalnums = np.zeros(NUM_CLASSES) 26 | # precision & recall 27 | total_gt_ins = np.zeros(NUM_CLASSES) 28 | at = 0.5 29 | tpsins = [[] for itmp in range(NUM_CLASSES)] 30 | fpsins = [[] for itmp in range(NUM_CLASSES)] 31 | # mucov and mwcov 32 | all_mean_cov = [[] for itmp in range(NUM_CLASSES)] 33 | all_mean_weighted_cov = [[] for itmp in range(NUM_CLASSES)] 34 | 35 | 36 | for i in range(num_room): 37 | print(i) 38 | data_label = np.loadtxt(pred_data_label_filenames[i]) 39 | pred_ins = data_label[:,-1].reshape(-1).astype(np.int) 40 | pred_sem = data_label[:, -2].reshape(-1).astype(np.int) 41 | gt_label = np.loadtxt(gt_label_filenames[i]) 42 | gt_ins = gt_label[:, -1].reshape(-1).astype(np.int) 43 | gt_sem = gt_label[:, -2].reshape(-1).astype(np.int) 44 | print(gt_label.shape) 45 | 46 | # semantic acc 47 | total_true += np.sum(pred_sem == gt_sem) 48 | total_seen += pred_sem.shape[0] 49 | 50 | # pn semantic mIoU 51 | for j in xrange(gt_sem.shape[0]): 52 | gt_l = int(gt_sem[j]) 53 | pred_l = int(pred_sem[j]) 54 | gt_classes[gt_l] += 1 55 | positive_classes[pred_l] += 1 56 | true_positive_classes[gt_l] += int(gt_l==pred_l) 57 | 58 | # semantic mIoU 59 | #intersections = np.zeros(NUM_CLASSES) 60 | #unions = np.zeros(NUM_CLASSES) 61 | #un, indices = np.unique(gt_sem, return_index=True) 62 | #for segid in un: 63 | # intersect = np.sum((pred_sem == segid) & (gt_sem == segid)) 64 | # union = np.sum((pred_sem == segid) | (gt_sem == segid)) 65 | # intersections[segid] += intersect 66 | # unions[segid] += union 67 | # true_positive_classes[segid] += intersect 68 | # gt_classes[segid] += np.sum(gt_sem == segid) 69 | 70 | #iou = intersections / unions 71 | #for i_iou, iou_ in enumerate(iou): 72 | # if not np.isnan(iou_): 73 | # ious[i_iou] += iou_ 74 | # totalnums[i_iou] += 1 75 | 76 | # instance 77 | un = np.unique(pred_ins) 78 | pts_in_pred = [[] for itmp in range(NUM_CLASSES)] 79 | for ig, g in enumerate(un): # each object in prediction 80 | if g == -1: 81 | continue 82 | tmp = (pred_ins == g) 83 | sem_seg_i = int(stats.mode(pred_sem[tmp])[0]) 84 | pts_in_pred[sem_seg_i] += [tmp] 85 | 86 | un = np.unique(gt_ins) 87 | pts_in_gt = [[] for itmp in range(NUM_CLASSES)] 88 | for ig, g in enumerate(un): 89 | tmp = (gt_ins == g) 90 | sem_seg_i = int(stats.mode(gt_sem[tmp])[0]) 91 | pts_in_gt[sem_seg_i] += [tmp] 92 | 93 | # instance mucov & mwcov 94 | for i_sem in range(NUM_CLASSES): 95 | sum_cov = 0 96 | mean_cov = 0 97 | mean_weighted_cov = 0 98 | num_gt_point = 0 99 | for ig, ins_gt in enumerate(pts_in_gt[i_sem]): 100 | ovmax = 0. 101 | num_ins_gt_point = np.sum(ins_gt) 102 | num_gt_point += num_ins_gt_point 103 | for ip, ins_pred in enumerate(pts_in_pred[i_sem]): 104 | union = (ins_pred | ins_gt) 105 | intersect = (ins_pred & ins_gt) 106 | iou = float(np.sum(intersect)) / np.sum(union) 107 | 108 | if iou > ovmax: 109 | ovmax = iou 110 | ipmax = ip 111 | 112 | sum_cov += ovmax 113 | mean_weighted_cov += ovmax * num_ins_gt_point 114 | 115 | if len(pts_in_gt[i_sem]) != 0: 116 | mean_cov = sum_cov / len(pts_in_gt[i_sem]) 117 | all_mean_cov[i_sem].append(mean_cov) 118 | 119 | mean_weighted_cov /= num_gt_point 120 | all_mean_weighted_cov[i_sem].append(mean_weighted_cov) 121 | 122 | 123 | # instance precision & recall 124 | for i_sem in range(NUM_CLASSES): 125 | tp = [0.] * len(pts_in_pred[i_sem]) 126 | fp = [0.] * len(pts_in_pred[i_sem]) 127 | gtflag = np.zeros(len(pts_in_gt[i_sem])) 128 | total_gt_ins[i_sem] += len(pts_in_gt[i_sem]) 129 | 130 | for ip, ins_pred in enumerate(pts_in_pred[i_sem]): 131 | ovmax = -1. 132 | 133 | for ig, ins_gt in enumerate(pts_in_gt[i_sem]): 134 | union = (ins_pred | ins_gt) 135 | intersect = (ins_pred & ins_gt) 136 | iou = float(np.sum(intersect)) / np.sum(union) 137 | 138 | if iou > ovmax: 139 | ovmax = iou 140 | igmax = ig 141 | 142 | if ovmax >= at: 143 | tp[ip] = 1 # true 144 | else: 145 | fp[ip] = 1 # false positive 146 | 147 | tpsins[i_sem] += tp 148 | fpsins[i_sem] += fp 149 | 150 | 151 | MUCov = np.zeros(NUM_CLASSES) 152 | MWCov = np.zeros(NUM_CLASSES) 153 | for i_sem in range(NUM_CLASSES): 154 | MUCov[i_sem] = np.mean(all_mean_cov[i_sem]) 155 | MWCov[i_sem] = np.mean(all_mean_weighted_cov[i_sem]) 156 | 157 | precision = np.zeros(NUM_CLASSES) 158 | recall = np.zeros(NUM_CLASSES) 159 | for i_sem in range(NUM_CLASSES): 160 | tp = np.asarray(tpsins[i_sem]).astype(np.float) 161 | fp = np.asarray(fpsins[i_sem]).astype(np.float) 162 | tp = np.sum(tp) 163 | fp = np.sum(fp) 164 | rec = tp / total_gt_ins[i_sem] 165 | prec = tp / (tp + fp) 166 | 167 | precision[i_sem] = prec 168 | recall[i_sem] = rec 169 | 170 | 171 | LOG_FOUT = open(os.path.join('results_a5.txt'), 'w') 172 | def log_string(out_str): 173 | LOG_FOUT.write(out_str+'\n') 174 | LOG_FOUT.flush() 175 | print(out_str) 176 | 177 | 178 | 179 | # instance results 180 | log_string('Instance Segmentation MUCov: {}'.format(MUCov)) 181 | log_string('Instance Segmentation mMUCov: {}'.format(np.mean(MUCov))) 182 | log_string('Instance Segmentation MWCov: {}'.format(MWCov)) 183 | log_string('Instance Segmentation mMWCov: {}'.format(np.mean(MWCov))) 184 | log_string('Instance Segmentation Precision: {}'.format(precision)) 185 | log_string('Instance Segmentation mPrecision: {}'.format(np.mean(precision))) 186 | log_string('Instance Segmentation Recall: {}'.format(recall)) 187 | log_string('Instance Segmentation mRecall: {}'.format(np.mean(recall))) 188 | 189 | 190 | # semantic results 191 | iou_list = [] 192 | for i in range(NUM_CLASSES): 193 | iou = true_positive_classes[i]/float(gt_classes[i]+positive_classes[i]-true_positive_classes[i]) 194 | print(iou) 195 | iou_list.append(iou) 196 | 197 | log_string('Semantic Segmentation oAcc: {}'.format(sum(true_positive_classes)/float(sum(positive_classes)))) 198 | #log_string('Semantic Segmentation Acc: {}'.format(true_positive_classes / gt_classes)) 199 | log_string('Semantic Segmentation mAcc: {}'.format(np.mean(true_positive_classes / gt_classes))) 200 | log_string('Semantic Segmentation IoU: {}'.format(iou_list)) 201 | log_string('Semantic Segmentation mIoU: {}'.format(1.*sum(iou_list)/NUM_CLASSES)) 202 | -------------------------------------------------------------------------------- /tf_ops/sampling/tf_sampling_g.cu: -------------------------------------------------------------------------------- 1 | /* Furthest point sampling GPU implementation 2 | * Original author: Haoqiang Fan 3 | * Modified by Charles R. Qi 4 | * All Rights Reserved. 2017. 5 | */ 6 | 7 | __global__ void cumsumKernel(int b,int n,const float * __restrict__ inp,float * __restrict__ out){ 8 | const int BlockSize=2048; 9 | const int paddingLevel=5; 10 | __shared__ float buffer4[BlockSize*4]; 11 | __shared__ float buffer[BlockSize+(BlockSize>>paddingLevel)]; 12 | for (int i=blockIdx.x;i>2; 18 | for (int k=threadIdx.x*4;k>2)+(k>>(2+paddingLevel))]=v4; 33 | }else{ 34 | float v=0; 35 | for (int k2=k;k2>2)+(k>>(2+paddingLevel))]=v; 43 | } 44 | } 45 | int u=0; 46 | for (;(2<>(u+1));k+=blockDim.x){ 49 | int i1=(((k<<1)+2)<>paddingLevel; 52 | i2+=i2>>paddingLevel; 53 | buffer[i1]+=buffer[i2]; 54 | } 55 | } 56 | u--; 57 | for (;u>=0;u--){ 58 | __syncthreads(); 59 | for (int k=threadIdx.x;k>(u+1));k+=blockDim.x){ 60 | int i1=(((k<<1)+3)<>paddingLevel; 63 | i2+=i2>>paddingLevel; 64 | buffer[i1]+=buffer[i2]; 65 | } 66 | } 67 | __syncthreads(); 68 | for (int k=threadIdx.x*4;k>2)-1)+(((k>>2)-1)>>paddingLevel); 71 | buffer4[k]+=buffer[k2]; 72 | buffer4[k+1]+=buffer[k2]; 73 | buffer4[k+2]+=buffer[k2]; 74 | buffer4[k+3]+=buffer[k2]; 75 | } 76 | } 77 | __syncthreads(); 78 | for (int k=threadIdx.x;k>paddingLevel)]+runningsum2; 82 | float r2=runningsum+t; 83 | runningsum2=t-(r2-runningsum); 84 | runningsum=r2; 85 | __syncthreads(); 86 | } 87 | } 88 | } 89 | 90 | __global__ void binarysearchKernel(int b,int n,int m,const float * __restrict__ dataset,const float * __restrict__ query, int * __restrict__ result){ 91 | int base=1; 92 | while (base=1;k>>=1) 99 | if (r>=k && dataset[i*n+r-k]>=q) 100 | r-=k; 101 | result[i*m+j]=r; 102 | } 103 | } 104 | } 105 | __global__ void farthestpointsamplingKernel(int b,int n,int m,const float * __restrict__ dataset,float * __restrict__ temp,int * __restrict__ idxs){ 106 | if (m<=0) 107 | return; 108 | const int BlockSize=512; 109 | __shared__ float dists[BlockSize]; 110 | __shared__ int dists_i[BlockSize]; 111 | const int BufferSize=3072; 112 | __shared__ float buf[BufferSize*3]; 113 | for (int i=blockIdx.x;ibest){ 147 | best=d2; 148 | besti=k; 149 | } 150 | } 151 | dists[threadIdx.x]=best; 152 | dists_i[threadIdx.x]=besti; 153 | for (int u=0;(1<>(u+1))){ 156 | int i1=(threadIdx.x*2)<>>(b,n,inp,out); 196 | } 197 | //require b*n working space 198 | void probsampleLauncher(int b,int n,int m,const float * inp_p,const float * inp_r,float * temp,int * out){ 199 | cumsumKernel<<<32,512>>>(b,n,inp_p,temp); 200 | binarysearchKernel<<>>(b,n,m,temp,inp_r,out); 201 | } 202 | //require 32*n working space 203 | void farthestpointsamplingLauncher(int b,int n,int m,const float * inp,float * temp,int * out){ 204 | farthestpointsamplingKernel<<<32,512>>>(b,n,m,inp,temp,out); 205 | } 206 | void gatherpointLauncher(int b,int n,int m,const float * inp,const int * idx,float * out){ 207 | gatherpointKernel<<>>(b,n,m,inp,idx,out); 208 | } 209 | void scatteraddpointLauncher(int b,int n,int m,const float * out_g,const int * idx,float * inp_g){ 210 | scatteraddpointKernel<<>>(b,n,m,out_g,idx,inp_g); 211 | } 212 | 213 | -------------------------------------------------------------------------------- /models/ASIS/provider.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import numpy as np 4 | import h5py 5 | # BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 6 | # sys.path.append(BASE_DIR) 7 | # 8 | # # Download dataset for point cloud classification 9 | # DATA_DIR = os.path.join(BASE_DIR, 'data') 10 | # if not os.path.exists(DATA_DIR): 11 | # os.mkdir(DATA_DIR) 12 | # if not os.path.exists(os.path.join(DATA_DIR, 'modelnet40_ply_hdf5_2048')): 13 | # www = 'https://shapenet.cs.stanford.edu/media/modelnet40_ply_hdf5_2048.zip' 14 | # zipfile = os.path.basename(www) 15 | # os.system('wget %s; unzip %s' % (www, zipfile)) 16 | # os.system('mv %s %s' % (zipfile[:-4], DATA_DIR)) 17 | # os.system('rm %s' % (zipfile)) 18 | 19 | 20 | def shuffle_data(data, labels): 21 | """ Shuffle data and labels. 22 | Input: 23 | data: B,N,... numpy array 24 | label: B,... numpy array 25 | Return: 26 | shuffled data, label and shuffle indices 27 | """ 28 | idx = np.arange(len(labels)) 29 | np.random.shuffle(idx) 30 | return data[idx, ...], labels[idx], idx 31 | 32 | 33 | def rotate_point_cloud(batch_data): 34 | """ Randomly rotate the point clouds to augument the dataset 35 | rotation is per shape based along up direction 36 | Input: 37 | BxNx3 array, original batch of point clouds 38 | Return: 39 | BxNx3 array, rotated batch of point clouds 40 | """ 41 | rotated_data = np.zeros(batch_data.shape, dtype=np.float32) 42 | for k in range(batch_data.shape[0]): 43 | rotation_angle = np.random.uniform() * 2 * np.pi 44 | cosval = np.cos(rotation_angle) 45 | sinval = np.sin(rotation_angle) 46 | rotation_matrix = np.array([[cosval, 0, sinval], 47 | [0, 1, 0], 48 | [-sinval, 0, cosval]]) 49 | shape_pc = batch_data[k, ...] 50 | rotated_data[k, ...] = np.dot(shape_pc.reshape((-1, 3)), rotation_matrix) 51 | return rotated_data 52 | 53 | 54 | def rotate_point_cloud_by_angle(batch_data, rotation_angle): 55 | """ Rotate the point cloud along up direction with certain angle. 56 | Input: 57 | BxNx3 array, original batch of point clouds 58 | Return: 59 | BxNx3 array, rotated batch of point clouds 60 | """ 61 | rotated_data = np.zeros(batch_data.shape, dtype=np.float32) 62 | for k in range(batch_data.shape[0]): 63 | #rotation_angle = np.random.uniform() * 2 * np.pi 64 | cosval = np.cos(rotation_angle) 65 | sinval = np.sin(rotation_angle) 66 | rotation_matrix = np.array([[cosval, 0, sinval], 67 | [0, 1, 0], 68 | [-sinval, 0, cosval]]) 69 | shape_pc = batch_data[k, ...] 70 | rotated_data[k, ...] = np.dot(shape_pc.reshape((-1, 3)), rotation_matrix) 71 | return rotated_data 72 | 73 | 74 | def jitter_point_cloud(batch_data, sigma=0.01, clip=0.05): 75 | """ Randomly jitter points. jittering is per point. 76 | Input: 77 | BxNx3 array, original batch of point clouds 78 | Return: 79 | BxNx3 array, jittered batch of point clouds 80 | """ 81 | B, N, C = batch_data.shape 82 | assert(clip > 0) 83 | jittered_data = np.clip(sigma * np.random.randn(B, N, C), -1*clip, clip) 84 | jittered_data += batch_data 85 | return jittered_data 86 | 87 | 88 | def save_h5_output(h5_filename, seg, segrefine, group, grouppred, label_dtype='uint8'): 89 | print h5_filename 90 | h5_fout = h5py.File(h5_filename) 91 | h5_fout.create_dataset( 92 | 'seglabel', data=seg, 93 | compression='gzip', compression_opts=1, 94 | dtype=label_dtype) 95 | h5_fout.create_dataset( 96 | 'segrefine', data=segrefine, 97 | compression='gzip', compression_opts=1, 98 | dtype=label_dtype) 99 | h5_fout.create_dataset( 100 | 'pid', data=group, 101 | compression='gzip', compression_opts=1, 102 | dtype=label_dtype) 103 | h5_fout.create_dataset( 104 | 'predpid', data=grouppred, 105 | compression='gzip', compression_opts=1, 106 | dtype=label_dtype) 107 | h5_fout.close() 108 | 109 | def getDataFiles(list_filename): 110 | return [line.rstrip() for line in open(list_filename)] 111 | 112 | def load_h5(h5_filename): 113 | f = h5py.File(h5_filename) 114 | data = f['data'][:] 115 | label = f['label'][:] 116 | return (data, label) 117 | 118 | def loadDataFile(filename): 119 | return load_h5(filename) 120 | 121 | def load_h5_data_label_seg(h5_filename): 122 | f = h5py.File(h5_filename) 123 | data = f['data'][:] 124 | label = f['label'][:] 125 | seg = f['pid'][:] 126 | return (data, label, seg) 127 | 128 | 129 | def loadDataFile_with_seg(filename): 130 | return load_h5_data_label_seg(filename) 131 | 132 | def loadDataFile_with_grouplabel(filename): 133 | f = h5py.File(filename) 134 | data = f['data'][:] 135 | # label = f['label'][:] 136 | group = f['pid'][:]#Nx1 137 | if 'groupcategory' in f: 138 | cate = f['groupcategory'][:]#Gx1 139 | else: 140 | cate = 0 141 | return (data, group, cate) 142 | 143 | def loadDataFile_with_groupseglabel(filename): 144 | f = h5py.File(filename) 145 | data = f['data'][:] 146 | # label = f['label'][:] 147 | group = f['pid'][:]#Nx1 148 | if 'groupcategory' in f: 149 | cate = f['groupcategory'][:]#Gx1 150 | else: 151 | cate = 0 152 | seg = -1 * np.ones_like(group) 153 | for i in range(group.shape[0]): 154 | for j in range(group.shape[1]): 155 | if group[i,j,0]!=-1 and cate[i,group[i,j,0],0]!=-1: 156 | seg[i,j,0] = cate[i,group[i,j,0],0] 157 | return (data, group, cate, seg) 158 | 159 | def loadDataFile_with_groupseglabel_sunrgbd(filename): 160 | f = h5py.File(filename) 161 | data = f['data'][:] 162 | group = f['pid'][:]#NxG 163 | if 'groupcategory' in f: 164 | cate = f['groupcategory'][:]#Gx1 165 | else: 166 | cate = 0 167 | if 'seglabel' in f: 168 | seg = f['seglabel'][:] 169 | else: 170 | seg = f['seglabels'][:] 171 | return (data, group, cate, seg) 172 | 173 | def loadDataFile_with_groupseglabel_scannet(filename): 174 | f = h5py.File(filename) 175 | data = f['data'][:] 176 | # label = f['label'][:] 177 | group = f['pid'][:]#NxG 178 | if 'groupcategory' in f: 179 | cate = f['groupcategory'][:]#Gx1 180 | else: 181 | cate = 0 182 | if 'seglabel' in f: 183 | seg = f['seglabel'][:] 184 | else: 185 | seg = f['seglabels'][:] 186 | return (data, group, cate, seg) 187 | 188 | 189 | def loadDataFile_with_groupseglabel_nuyv2(filename): 190 | f = h5py.File(filename) 191 | data = f['data'][:] 192 | group = f['pid'][:]#NxG 193 | if 'groupcategory' in f: 194 | cate = f['groupcategory'][:]#Gx1 195 | else: 196 | cate = 0 197 | if 'seglabel' in f: 198 | seg = f['seglabel'][:] 199 | else: 200 | seg = f['seglabels'][:] 201 | boxes = f['bbox'][:] 202 | return (data, group, cate, seg, boxes) 203 | 204 | def loadDataFile_with_groupseglabel_stanfordindoor(filename): 205 | f = h5py.File(filename) 206 | data = f['data'][:] 207 | group = f['pid'][:].astype(np.int32)#NxG 208 | if 'label' in f: 209 | label = f['label'][:].astype(np.int32) 210 | else : 211 | label = [] 212 | if 'seglabel' in f: 213 | seg = f['seglabel'][:].astype(np.int32) 214 | else: 215 | seg = f['seglabels'][:].astype(np.int32) 216 | return (data, group, label, seg) 217 | 218 | def loadDataFile_with_img(filename): 219 | f = h5py.File(filename) 220 | data = f['data'][:] 221 | group = f['pid'][:]#NxG 222 | seg = f['seglabel'][:] 223 | img = f['img'][:].transpose([2,1,0]) 224 | return (data, group, seg, img) 225 | -------------------------------------------------------------------------------- /models/ASIS/part_color_mapping.json: -------------------------------------------------------------------------------- 1 | [[0.57, 0.15, 0.43], [0.85, 0.57, 0.29], [0.7100000000000001, 0.7100000000000001, 0.01], [0.01, 0.7100000000000001, 0.15], [0.01, 0.57, 0.85], [0.43, 0.01, 0.7100000000000001], [0.43, 0.7100000000000001, 0.57], [0.29, 0.29, 0.29], [0.29, 0.7100000000000001, 0.7100000000000001], [0.57, 0.57, 0.29], [0.57, 0.7100000000000001, 0.7100000000000001], [0.01, 0.01, 0.29], [0.29, 0.57, 0.7100000000000001], [0.29, 0.15, 0.57], [0.29, 0.7100000000000001, 0.43], [0.57, 0.29, 0.01], [0.29, 0.15, 0.15], [0.7100000000000001, 0.29, 0.01], [0.01, 0.85, 0.15], [0.85, 0.01, 0.01], [0.29, 0.15, 0.7100000000000001], [0.7100000000000001, 0.15, 0.43], [0.29, 0.43, 0.7100000000000001], [0.43, 0.43, 0.7100000000000001], [0.29, 0.57, 0.01], [0.57, 0.29, 0.29], [0.57, 0.85, 0.15], [0.15, 0.29, 0.29], [0.15, 0.7100000000000001, 0.15], [0.85, 0.01, 0.29], [0.43, 0.85, 0.29], [0.43, 0.29, 0.85], [0.57, 0.85, 0.85], [0.15, 0.57, 0.01], [0.57, 0.29, 0.15], [0.7100000000000001, 0.85, 0.57], [0.57, 0.01, 0.57], [0.01, 0.85, 0.43], [0.01, 0.01, 0.01], [0.85, 0.01, 0.43], [0.57, 0.43, 0.57], [0.85, 0.01, 0.57], [0.01, 0.43, 0.43], [0.01, 0.29, 0.85], [0.57, 0.57, 0.7100000000000001], [0.7100000000000001, 0.29, 0.57], [0.57, 0.7100000000000001, 0.43], [0.29, 0.15, 0.01], [0.57, 0.15, 0.15], [0.85, 0.57, 0.85], [0.85, 0.29, 0.85], [0.85, 0.15, 0.01], [0.85, 0.7100000000000001, 0.01], [0.01, 0.57, 0.15], [0.43, 0.01, 0.43], [0.57, 0.15, 0.85], [0.01, 0.29, 0.57], [0.29, 0.85, 0.43], [0.57, 0.29, 0.43], [0.43, 0.01, 0.29], [0.15, 0.85, 0.7100000000000001], [0.85, 0.57, 0.43], [0.01, 0.15, 0.57], [0.7100000000000001, 0.7100000000000001, 0.29], [0.7100000000000001, 0.15, 0.57], [0.43, 0.43, 0.29], [0.7100000000000001, 0.43, 0.43], [0.01, 0.43, 0.57], [0.57, 0.01, 0.15], [0.57, 0.57, 0.01], [0.29, 0.01, 0.29], [0.7100000000000001, 0.01, 0.29], [0.85, 0.85, 0.7100000000000001], [0.85, 0.15, 0.29], [0.43, 0.29, 0.57], [0.43, 0.43, 0.85], [0.85, 0.15, 0.85], [0.57, 0.85, 0.29], [0.57, 0.7100000000000001, 0.01], [0.7100000000000001, 0.85, 0.15], [0.85, 0.7100000000000001, 0.43], [0.01, 0.15, 0.01], [0.85, 0.29, 0.43], [0.43, 0.85, 0.15], [0.15, 0.01, 0.15], [0.7100000000000001, 0.7100000000000001, 0.85], [0.43, 0.29, 0.01], [0.15, 0.43, 0.29], [0.7100000000000001, 0.57, 0.15], [0.29, 0.85, 0.29], [0.29, 0.7100000000000001, 0.57], [0.57, 0.85, 0.7100000000000001], [0.15, 0.01, 0.85], [0.43, 0.15, 0.57], [0.57, 0.57, 0.15], [0.01, 0.57, 0.01], [0.15, 0.29, 0.57], [0.29, 0.57, 0.43], [0.15, 0.7100000000000001, 0.01], [0.15, 0.15, 0.15], [0.43, 0.29, 0.15], [0.7100000000000001, 0.29, 0.7100000000000001], [0.7100000000000001, 0.85, 0.43], [0.15, 0.29, 0.7100000000000001], [0.15, 0.43, 0.57], [0.01, 0.7100000000000001, 0.01], [0.85, 0.29, 0.01], [0.15, 0.01, 0.57], [0.29, 0.29, 0.7100000000000001], [0.15, 0.7100000000000001, 0.29], [0.01, 0.15, 0.43], [0.7100000000000001, 0.01, 0.15], [0.57, 0.43, 0.01], [0.85, 0.43, 0.01], [0.43, 0.85, 0.7100000000000001], [0.85, 0.43, 0.43], [0.85, 0.01, 0.15], [0.01, 0.43, 0.85], [0.15, 0.15, 0.7100000000000001], [0.29, 0.57, 0.85], [0.43, 0.15, 0.15], [0.29, 0.85, 0.85], [0.15, 0.57, 0.29], [0.85, 0.85, 0.85], [0.29, 0.43, 0.43], [0.01, 0.43, 0.29], [0.43, 0.15, 0.7100000000000001], [0.7100000000000001, 0.01, 0.57], [0.7100000000000001, 0.43, 0.15], [0.01, 0.85, 0.01], [0.85, 0.01, 0.7100000000000001], [0.57, 0.43, 0.43], [0.57, 0.85, 0.01], [0.01, 0.57, 0.43], [0.15, 0.15, 0.01], [0.85, 0.43, 0.85], [0.57, 0.15, 0.29], [0.7100000000000001, 0.7100000000000001, 0.57], [0.57, 0.01, 0.85], [0.29, 0.43, 0.15], [0.7100000000000001, 0.57, 0.7100000000000001], [0.43, 0.7100000000000001, 0.85], [0.01, 0.15, 0.15], [0.85, 0.85, 0.57], [0.43, 0.85, 0.01], [0.15, 0.15, 0.85], [0.29, 0.29, 0.43], [0.29, 0.43, 0.57], [0.7100000000000001, 0.29, 0.85], [0.15, 0.15, 0.43], [0.85, 0.7100000000000001, 0.85], [0.85, 0.15, 0.43], [0.43, 0.43, 0.15], [0.57, 0.7100000000000001, 0.15], [0.7100000000000001, 0.43, 0.57], [0.7100000000000001, 0.43, 0.01], [0.85, 0.29, 0.29], [0.85, 0.15, 0.15], [0.43, 0.57, 0.85], [0.01, 0.85, 0.29], [0.29, 0.7100000000000001, 0.15], [0.57, 0.85, 0.57], [0.43, 0.43, 0.57], [0.01, 0.7100000000000001, 0.7100000000000001], [0.57, 0.15, 0.57], [0.57, 0.57, 0.43], [0.85, 0.57, 0.57], [0.85, 0.7100000000000001, 0.7100000000000001], [0.57, 0.7100000000000001, 0.85], [0.15, 0.85, 0.85], [0.29, 0.57, 0.57], [0.15, 0.7100000000000001, 0.85], [0.57, 0.01, 0.29], [0.29, 0.7100000000000001, 0.01], [0.7100000000000001, 0.29, 0.15], [0.85, 0.01, 0.85], [0.29, 0.01, 0.57], [0.29, 0.01, 0.7100000000000001], [0.7100000000000001, 0.85, 0.29], [0.85, 0.29, 0.7100000000000001], [0.43, 0.15, 0.43], [0.01, 0.01, 0.15], [0.01, 0.7100000000000001, 0.57], [0.7100000000000001, 0.15, 0.01], [0.7100000000000001, 0.15, 0.15], [0.29, 0.29, 0.85], [0.01, 0.43, 0.7100000000000001], [0.57, 0.15, 0.01], [0.85, 0.15, 0.7100000000000001], [0.43, 0.43, 0.01], [0.29, 0.85, 0.57], [0.01, 0.29, 0.43], [0.57, 0.43, 0.29], [0.43, 0.29, 0.43], [0.85, 0.7100000000000001, 0.29], [0.7100000000000001, 0.85, 0.85], [0.43, 0.43, 0.43], [0.43, 0.29, 0.7100000000000001], [0.7100000000000001, 0.57, 0.57], [0.57, 0.29, 0.85], [0.01, 0.15, 0.7100000000000001], [0.7100000000000001, 0.7100000000000001, 0.15], [0.15, 0.85, 0.01], [0.43, 0.7100000000000001, 0.7100000000000001], [0.43, 0.57, 0.43], [0.7100000000000001, 0.01, 0.85], [0.29, 0.43, 0.29], [0.57, 0.15, 0.7100000000000001], [0.29, 0.57, 0.15], [0.15, 0.29, 0.43], [0.43, 0.85, 0.57], [0.43, 0.57, 0.57], [0.7100000000000001, 0.01, 0.01], [0.85, 0.85, 0.29], [0.15, 0.01, 0.29], [0.85, 0.29, 0.15], [0.15, 0.01, 0.01], [0.01, 0.01, 0.57], [0.15, 0.57, 0.15], [0.15, 0.43, 0.85], [0.01, 0.01, 0.7100000000000001], [0.85, 0.15, 0.57], [0.29, 0.15, 0.29], [0.15, 0.29, 0.15], [0.43, 0.85, 0.43], [0.01, 0.15, 0.29], [0.85, 0.7100000000000001, 0.15], [0.01, 0.01, 0.85], [0.7100000000000001, 0.57, 0.85], [0.01, 0.85, 0.57], [0.29, 0.85, 0.7100000000000001], [0.15, 0.01, 0.7100000000000001], [0.85, 0.57, 0.15], [0.15, 0.57, 0.85], [0.15, 0.43, 0.15], [0.15, 0.85, 0.57], [0.7100000000000001, 0.85, 0.01], [0.7100000000000001, 0.01, 0.7100000000000001], [0.15, 0.43, 0.43], [0.01, 0.57, 0.7100000000000001], [0.43, 0.01, 0.57], [0.01, 0.57, 0.57], [0.57, 0.43, 0.7100000000000001], [0.7100000000000001, 0.29, 0.29], [0.15, 0.43, 0.7100000000000001], [0.57, 0.43, 0.15], [0.01, 0.7100000000000001, 0.29], [0.7100000000000001, 0.57, 0.01], [0.01, 0.29, 0.15], [0.29, 0.85, 0.01], [0.57, 0.29, 0.57], [0.85, 0.43, 0.29], [0.7100000000000001, 0.43, 0.29], [0.29, 0.7100000000000001, 0.85], [0.85, 0.57, 0.01], [0.01, 0.29, 0.7100000000000001], [0.15, 0.57, 0.7100000000000001], [0.85, 0.57, 0.7100000000000001], [0.85, 0.43, 0.7100000000000001], [0.15, 0.57, 0.43], [0.15, 0.85, 0.29], [0.15, 0.29, 0.85], [0.7100000000000001, 0.29, 0.43], [0.15, 0.15, 0.29], [0.43, 0.7100000000000001, 0.01], [0.29, 0.7100000000000001, 0.29], [0.7100000000000001, 0.7100000000000001, 0.43], [0.29, 0.85, 0.15], [0.43, 0.15, 0.29], [0.29, 0.01, 0.15], [0.57, 0.01, 0.01], [0.85, 0.85, 0.15], [0.43, 0.7100000000000001, 0.15], [0.43, 0.7100000000000001, 0.29], [0.7100000000000001, 0.57, 0.43], [0.29, 0.29, 0.57], [0.29, 0.01, 0.43], [0.85, 0.7100000000000001, 0.57], [0.57, 0.29, 0.7100000000000001], [0.43, 0.29, 0.29], [0.7100000000000001, 0.43, 0.7100000000000001], [0.43, 0.57, 0.29], [0.43, 0.01, 0.15], [0.15, 0.7100000000000001, 0.57], [0.01, 0.29, 0.29], [0.29, 0.01, 0.01], [0.7100000000000001, 0.15, 0.85], [0.57, 0.7100000000000001, 0.29], [0.57, 0.7100000000000001, 0.57], [0.15, 0.29, 0.01], [0.29, 0.43, 0.01], [0.7100000000000001, 0.15, 0.7100000000000001], [0.85, 0.85, 0.43], [0.7100000000000001, 0.15, 0.29], [0.7100000000000001, 0.7100000000000001, 0.7100000000000001], [0.29, 0.57, 0.29], [0.85, 0.43, 0.57], [0.01, 0.57, 0.29], [0.57, 0.01, 0.43], [0.01, 0.29, 0.01], [0.29, 0.01, 0.85], [0.43, 0.57, 0.15], [0.85, 0.85, 0.01], [0.29, 0.15, 0.43], [0.29, 0.29, 0.15], [0.01, 0.43, 0.01], [0.43, 0.85, 0.85], [0.15, 0.7100000000000001, 0.7100000000000001], [0.15, 0.85, 0.43], [0.7100000000000001, 0.85, 0.7100000000000001], [0.7100000000000001, 0.01, 0.43], [0.15, 0.43, 0.01], [0.43, 0.57, 0.01], [0.7100000000000001, 0.57, 0.29], [0.01, 0.85, 0.85], [0.01, 0.85, 0.7100000000000001], [0.01, 0.7100000000000001, 0.85], [0.43, 0.7100000000000001, 0.43], [0.43, 0.15, 0.01], [0.57, 0.85, 0.43], [0.85, 0.43, 0.15], [0.01, 0.15, 0.85], [0.85, 0.29, 0.57], [0.01, 0.01, 0.43], [0.57, 0.01, 0.7100000000000001], [0.29, 0.29, 0.01], [0.57, 0.43, 0.85], [0.43, 0.15, 0.85], [0.01, 0.7100000000000001, 0.43], [0.15, 0.57, 0.57], [0.15, 0.15, 0.57], [0.29, 0.43, 0.85], [0.43, 0.01, 0.01], [0.57, 0.57, 0.85], [0.15, 0.7100000000000001, 0.43], [0.43, 0.01, 0.85], [0.15, 0.01, 0.43], [0.43, 0.57, 0.7100000000000001], [0.29, 0.15, 0.85], [0.15, 0.85, 0.15], [0.7100000000000001, 0.43, 0.85], [0.01, 0.43, 0.15], [0.57, 0.57, 0.57]] 2 | -------------------------------------------------------------------------------- /meta/anno_paths.txt: -------------------------------------------------------------------------------- 1 | Area_1/conferenceRoom_1/Annotations 2 | Area_1/conferenceRoom_2/Annotations 3 | Area_1/copyRoom_1/Annotations 4 | Area_1/hallway_1/Annotations 5 | Area_1/hallway_2/Annotations 6 | Area_1/hallway_3/Annotations 7 | Area_1/hallway_4/Annotations 8 | Area_1/hallway_5/Annotations 9 | Area_1/hallway_6/Annotations 10 | Area_1/hallway_7/Annotations 11 | Area_1/hallway_8/Annotations 12 | Area_1/office_10/Annotations 13 | Area_1/office_11/Annotations 14 | Area_1/office_12/Annotations 15 | Area_1/office_13/Annotations 16 | Area_1/office_14/Annotations 17 | Area_1/office_15/Annotations 18 | Area_1/office_16/Annotations 19 | Area_1/office_17/Annotations 20 | Area_1/office_18/Annotations 21 | Area_1/office_19/Annotations 22 | Area_1/office_1/Annotations 23 | Area_1/office_20/Annotations 24 | Area_1/office_21/Annotations 25 | Area_1/office_22/Annotations 26 | Area_1/office_23/Annotations 27 | Area_1/office_24/Annotations 28 | Area_1/office_25/Annotations 29 | Area_1/office_26/Annotations 30 | Area_1/office_27/Annotations 31 | Area_1/office_28/Annotations 32 | Area_1/office_29/Annotations 33 | Area_1/office_2/Annotations 34 | Area_1/office_30/Annotations 35 | Area_1/office_31/Annotations 36 | Area_1/office_3/Annotations 37 | Area_1/office_4/Annotations 38 | Area_1/office_5/Annotations 39 | Area_1/office_6/Annotations 40 | Area_1/office_7/Annotations 41 | Area_1/office_8/Annotations 42 | Area_1/office_9/Annotations 43 | Area_1/pantry_1/Annotations 44 | Area_1/WC_1/Annotations 45 | Area_2/auditorium_1/Annotations 46 | Area_2/auditorium_2/Annotations 47 | Area_2/conferenceRoom_1/Annotations 48 | Area_2/hallway_10/Annotations 49 | Area_2/hallway_11/Annotations 50 | Area_2/hallway_12/Annotations 51 | Area_2/hallway_1/Annotations 52 | Area_2/hallway_2/Annotations 53 | Area_2/hallway_3/Annotations 54 | Area_2/hallway_4/Annotations 55 | Area_2/hallway_5/Annotations 56 | Area_2/hallway_6/Annotations 57 | Area_2/hallway_7/Annotations 58 | Area_2/hallway_8/Annotations 59 | Area_2/hallway_9/Annotations 60 | Area_2/office_10/Annotations 61 | Area_2/office_11/Annotations 62 | Area_2/office_12/Annotations 63 | Area_2/office_13/Annotations 64 | Area_2/office_14/Annotations 65 | Area_2/office_1/Annotations 66 | Area_2/office_2/Annotations 67 | Area_2/office_3/Annotations 68 | Area_2/office_4/Annotations 69 | Area_2/office_5/Annotations 70 | Area_2/office_6/Annotations 71 | Area_2/office_7/Annotations 72 | Area_2/office_8/Annotations 73 | Area_2/office_9/Annotations 74 | Area_2/storage_1/Annotations 75 | Area_2/storage_2/Annotations 76 | Area_2/storage_3/Annotations 77 | Area_2/storage_4/Annotations 78 | Area_2/storage_5/Annotations 79 | Area_2/storage_6/Annotations 80 | Area_2/storage_7/Annotations 81 | Area_2/storage_8/Annotations 82 | Area_2/storage_9/Annotations 83 | Area_2/WC_1/Annotations 84 | Area_2/WC_2/Annotations 85 | Area_3/conferenceRoom_1/Annotations 86 | Area_3/hallway_1/Annotations 87 | Area_3/hallway_2/Annotations 88 | Area_3/hallway_3/Annotations 89 | Area_3/hallway_4/Annotations 90 | Area_3/hallway_5/Annotations 91 | Area_3/hallway_6/Annotations 92 | Area_3/lounge_1/Annotations 93 | Area_3/lounge_2/Annotations 94 | Area_3/office_10/Annotations 95 | Area_3/office_1/Annotations 96 | Area_3/office_2/Annotations 97 | Area_3/office_3/Annotations 98 | Area_3/office_4/Annotations 99 | Area_3/office_5/Annotations 100 | Area_3/office_6/Annotations 101 | Area_3/office_7/Annotations 102 | Area_3/office_8/Annotations 103 | Area_3/office_9/Annotations 104 | Area_3/storage_1/Annotations 105 | Area_3/storage_2/Annotations 106 | Area_3/WC_1/Annotations 107 | Area_3/WC_2/Annotations 108 | Area_4/conferenceRoom_1/Annotations 109 | Area_4/conferenceRoom_2/Annotations 110 | Area_4/conferenceRoom_3/Annotations 111 | Area_4/hallway_10/Annotations 112 | Area_4/hallway_11/Annotations 113 | Area_4/hallway_12/Annotations 114 | Area_4/hallway_13/Annotations 115 | Area_4/hallway_14/Annotations 116 | Area_4/hallway_1/Annotations 117 | Area_4/hallway_2/Annotations 118 | Area_4/hallway_3/Annotations 119 | Area_4/hallway_4/Annotations 120 | Area_4/hallway_5/Annotations 121 | Area_4/hallway_6/Annotations 122 | Area_4/hallway_7/Annotations 123 | Area_4/hallway_8/Annotations 124 | Area_4/hallway_9/Annotations 125 | Area_4/lobby_1/Annotations 126 | Area_4/lobby_2/Annotations 127 | Area_4/office_10/Annotations 128 | Area_4/office_11/Annotations 129 | Area_4/office_12/Annotations 130 | Area_4/office_13/Annotations 131 | Area_4/office_14/Annotations 132 | Area_4/office_15/Annotations 133 | Area_4/office_16/Annotations 134 | Area_4/office_17/Annotations 135 | Area_4/office_18/Annotations 136 | Area_4/office_19/Annotations 137 | Area_4/office_1/Annotations 138 | Area_4/office_20/Annotations 139 | Area_4/office_21/Annotations 140 | Area_4/office_22/Annotations 141 | Area_4/office_2/Annotations 142 | Area_4/office_3/Annotations 143 | Area_4/office_4/Annotations 144 | Area_4/office_5/Annotations 145 | Area_4/office_6/Annotations 146 | Area_4/office_7/Annotations 147 | Area_4/office_8/Annotations 148 | Area_4/office_9/Annotations 149 | Area_4/storage_1/Annotations 150 | Area_4/storage_2/Annotations 151 | Area_4/storage_3/Annotations 152 | Area_4/storage_4/Annotations 153 | Area_4/WC_1/Annotations 154 | Area_4/WC_2/Annotations 155 | Area_4/WC_3/Annotations 156 | Area_4/WC_4/Annotations 157 | Area_5/conferenceRoom_1/Annotations 158 | Area_5/conferenceRoom_2/Annotations 159 | Area_5/conferenceRoom_3/Annotations 160 | Area_5/hallway_10/Annotations 161 | Area_5/hallway_11/Annotations 162 | Area_5/hallway_12/Annotations 163 | Area_5/hallway_13/Annotations 164 | Area_5/hallway_14/Annotations 165 | Area_5/hallway_15/Annotations 166 | Area_5/hallway_1/Annotations 167 | Area_5/hallway_2/Annotations 168 | Area_5/hallway_3/Annotations 169 | Area_5/hallway_4/Annotations 170 | Area_5/hallway_5/Annotations 171 | Area_5/hallway_6/Annotations 172 | Area_5/hallway_7/Annotations 173 | Area_5/hallway_8/Annotations 174 | Area_5/hallway_9/Annotations 175 | Area_5/lobby_1/Annotations 176 | Area_5/office_10/Annotations 177 | Area_5/office_11/Annotations 178 | Area_5/office_12/Annotations 179 | Area_5/office_13/Annotations 180 | Area_5/office_14/Annotations 181 | Area_5/office_15/Annotations 182 | Area_5/office_16/Annotations 183 | Area_5/office_17/Annotations 184 | Area_5/office_18/Annotations 185 | Area_5/office_19/Annotations 186 | Area_5/office_1/Annotations 187 | Area_5/office_20/Annotations 188 | Area_5/office_21/Annotations 189 | Area_5/office_22/Annotations 190 | Area_5/office_23/Annotations 191 | Area_5/office_24/Annotations 192 | Area_5/office_25/Annotations 193 | Area_5/office_26/Annotations 194 | Area_5/office_27/Annotations 195 | Area_5/office_28/Annotations 196 | Area_5/office_29/Annotations 197 | Area_5/office_2/Annotations 198 | Area_5/office_30/Annotations 199 | Area_5/office_31/Annotations 200 | Area_5/office_32/Annotations 201 | Area_5/office_33/Annotations 202 | Area_5/office_34/Annotations 203 | Area_5/office_35/Annotations 204 | Area_5/office_36/Annotations 205 | Area_5/office_37/Annotations 206 | Area_5/office_38/Annotations 207 | Area_5/office_39/Annotations 208 | Area_5/office_3/Annotations 209 | Area_5/office_40/Annotations 210 | Area_5/office_41/Annotations 211 | Area_5/office_42/Annotations 212 | Area_5/office_4/Annotations 213 | Area_5/office_5/Annotations 214 | Area_5/office_6/Annotations 215 | Area_5/office_7/Annotations 216 | Area_5/office_8/Annotations 217 | Area_5/office_9/Annotations 218 | Area_5/pantry_1/Annotations 219 | Area_5/storage_1/Annotations 220 | Area_5/storage_2/Annotations 221 | Area_5/storage_3/Annotations 222 | Area_5/storage_4/Annotations 223 | Area_5/WC_1/Annotations 224 | Area_5/WC_2/Annotations 225 | Area_6/conferenceRoom_1/Annotations 226 | Area_6/copyRoom_1/Annotations 227 | Area_6/hallway_1/Annotations 228 | Area_6/hallway_2/Annotations 229 | Area_6/hallway_3/Annotations 230 | Area_6/hallway_4/Annotations 231 | Area_6/hallway_5/Annotations 232 | Area_6/hallway_6/Annotations 233 | Area_6/lounge_1/Annotations 234 | Area_6/office_10/Annotations 235 | Area_6/office_11/Annotations 236 | Area_6/office_12/Annotations 237 | Area_6/office_13/Annotations 238 | Area_6/office_14/Annotations 239 | Area_6/office_15/Annotations 240 | Area_6/office_16/Annotations 241 | Area_6/office_17/Annotations 242 | Area_6/office_18/Annotations 243 | Area_6/office_19/Annotations 244 | Area_6/office_1/Annotations 245 | Area_6/office_20/Annotations 246 | Area_6/office_21/Annotations 247 | Area_6/office_22/Annotations 248 | Area_6/office_23/Annotations 249 | Area_6/office_24/Annotations 250 | Area_6/office_25/Annotations 251 | Area_6/office_26/Annotations 252 | Area_6/office_27/Annotations 253 | Area_6/office_28/Annotations 254 | Area_6/office_29/Annotations 255 | Area_6/office_2/Annotations 256 | Area_6/office_30/Annotations 257 | Area_6/office_31/Annotations 258 | Area_6/office_32/Annotations 259 | Area_6/office_33/Annotations 260 | Area_6/office_34/Annotations 261 | Area_6/office_35/Annotations 262 | Area_6/office_36/Annotations 263 | Area_6/office_37/Annotations 264 | Area_6/office_3/Annotations 265 | Area_6/office_4/Annotations 266 | Area_6/office_5/Annotations 267 | Area_6/office_6/Annotations 268 | Area_6/office_7/Annotations 269 | Area_6/office_8/Annotations 270 | Area_6/office_9/Annotations 271 | Area_6/openspace_1/Annotations 272 | Area_6/pantry_1/Annotations 273 | -------------------------------------------------------------------------------- /tf_ops/sampling/tf_sampling.cpp: -------------------------------------------------------------------------------- 1 | /* Furthest point sampling 2 | * Original author: Haoqiang Fan 3 | * Modified by Charles R. Qi 4 | * All Rights Reserved. 2017. 5 | */ 6 | #include "tensorflow/core/framework/op.h" 7 | #include "tensorflow/core/framework/op_kernel.h" 8 | #include "tensorflow/core/framework/shape_inference.h" 9 | #include "tensorflow/core/framework/common_shape_fns.h" 10 | #include 11 | 12 | using namespace tensorflow; 13 | 14 | REGISTER_OP("ProbSample") 15 | .Input("inp: float32") 16 | .Input("inpr: float32") 17 | .Output("out: int32") 18 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 19 | ::tensorflow::shape_inference::ShapeHandle dims1; // batch_size * ncategory 20 | c->WithRank(c->input(0), 2, &dims1); 21 | ::tensorflow::shape_inference::ShapeHandle dims2; // batch_size * npoints 22 | c->WithRank(c->input(1), 2, &dims2); 23 | // batch_size * npoints 24 | ::tensorflow::shape_inference::ShapeHandle output = c->MakeShape({c->Dim(dims2, 0), c->Dim(dims2, 1)}); 25 | c->set_output(0, output); 26 | return Status::OK(); 27 | }); 28 | REGISTER_OP("FarthestPointSample") 29 | .Attr("npoint: int") 30 | .Input("inp: float32") 31 | .Output("out: int32") 32 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 33 | ::tensorflow::shape_inference::ShapeHandle dims1; // batch_size * npoint * 3 34 | c->WithRank(c->input(0), 3, &dims1); 35 | int npoint; 36 | TF_RETURN_IF_ERROR(c->GetAttr("npoint", &npoint)); 37 | ::tensorflow::shape_inference::ShapeHandle output = c->MakeShape({c->Dim(dims1, 0), npoint}); 38 | c->set_output(0, output); 39 | return Status::OK(); 40 | }); 41 | REGISTER_OP("GatherPoint") 42 | .Input("inp: float32") 43 | .Input("idx: int32") 44 | .Output("out: float32") 45 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 46 | ::tensorflow::shape_inference::ShapeHandle dims1; // batch_size * ndataset * 3 47 | c->WithRank(c->input(0), 3, &dims1); 48 | ::tensorflow::shape_inference::ShapeHandle dims2; // batch_size * npoints 49 | c->WithRank(c->input(1), 2, &dims2); 50 | // batch_size * npoints * 3 51 | ::tensorflow::shape_inference::ShapeHandle output = c->MakeShape({c->Dim(dims1, 0), c->Dim(dims2, 1), c->Dim(dims1, 2)}); 52 | c->set_output(0, output); 53 | return Status::OK(); 54 | }); 55 | REGISTER_OP("GatherPointGrad") 56 | .Input("inp: float32") 57 | .Input("idx: int32") 58 | .Input("out_g: float32") 59 | .Output("inp_g: float32") 60 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 61 | c->set_output(0, c->input(0)); 62 | return Status::OK(); 63 | }); 64 | 65 | void probsampleLauncher(int b,int n,int m,const float * inp_p,const float * inp_r,float * temp,int * out); 66 | class ProbSampleGpuOp: public OpKernel{ 67 | public: 68 | explicit ProbSampleGpuOp(OpKernelConstruction* context):OpKernel(context){} 69 | void Compute(OpKernelContext * context)override{ 70 | const Tensor& inp_tensor=context->input(0); 71 | const Tensor& inpr_tensor=context->input(1); 72 | auto inp_flat=inp_tensor.flat(); 73 | auto inpr_flat=inpr_tensor.flat(); 74 | const float * inp=&(inp_flat(0)); 75 | const float * inpr=&(inpr_flat(0)); 76 | OP_REQUIRES(context,inp_tensor.dims()==2,errors::InvalidArgument("ProbSample expects (batch_size,num_choices) inp shape")); 77 | int b=inp_tensor.shape().dim_size(0); 78 | int n=inp_tensor.shape().dim_size(1); 79 | OP_REQUIRES(context,inpr_tensor.dims()==2 && inpr_tensor.shape().dim_size(0)==b,errors::InvalidArgument("ProbSample expects (batch_size,num_points) inpr shape")); 80 | int m=inpr_tensor.shape().dim_size(1); 81 | Tensor * out_tensor=NULL; 82 | OP_REQUIRES_OK(context,context->allocate_output(0,TensorShape{b,m},&out_tensor)); 83 | auto out_flat=out_tensor->flat(); 84 | int * out=&(out_flat(0)); 85 | Tensor temp_tensor; 86 | OP_REQUIRES_OK(context,context->allocate_temp(DataTypeToEnum::value,TensorShape{b,n},&temp_tensor)); 87 | auto temp_flat=temp_tensor.flat(); 88 | float * temp=&(temp_flat(0)); 89 | probsampleLauncher(b,n,m,inp,inpr,temp,out); 90 | } 91 | }; 92 | REGISTER_KERNEL_BUILDER(Name("ProbSample").Device(DEVICE_GPU), ProbSampleGpuOp); 93 | 94 | void farthestpointsamplingLauncher(int b,int n,int m,const float * inp,float * temp,int * out); 95 | class FarthestPointSampleGpuOp: public OpKernel{ 96 | public: 97 | explicit FarthestPointSampleGpuOp(OpKernelConstruction* context):OpKernel(context) { 98 | OP_REQUIRES_OK(context, context->GetAttr("npoint", &npoint_)); 99 | OP_REQUIRES(context, npoint_ > 0, errors::InvalidArgument("FarthestPointSample expects positive npoint")); 100 | } 101 | void Compute(OpKernelContext * context)override{ 102 | int m = npoint_; 103 | 104 | const Tensor& inp_tensor=context->input(0); 105 | OP_REQUIRES(context,inp_tensor.dims()==3 && inp_tensor.shape().dim_size(2)==3,errors::InvalidArgument("FarthestPointSample expects (batch_size,num_points,3) inp shape")); 106 | int b=inp_tensor.shape().dim_size(0); 107 | int n=inp_tensor.shape().dim_size(1); 108 | auto inp_flat=inp_tensor.flat(); 109 | const float * inp=&(inp_flat(0)); 110 | Tensor * out_tensor; 111 | OP_REQUIRES_OK(context,context->allocate_output(0,TensorShape{b,m},&out_tensor)); 112 | auto out_flat=out_tensor->flat(); 113 | int * out=&(out_flat(0)); 114 | Tensor temp_tensor; 115 | OP_REQUIRES_OK(context,context->allocate_temp(DataTypeToEnum::value,TensorShape{32,n},&temp_tensor)); 116 | auto temp_flat=temp_tensor.flat(); 117 | float * temp=&(temp_flat(0)); 118 | farthestpointsamplingLauncher(b,n,m,inp,temp,out); 119 | } 120 | private: 121 | int npoint_; 122 | }; 123 | REGISTER_KERNEL_BUILDER(Name("FarthestPointSample").Device(DEVICE_GPU),FarthestPointSampleGpuOp); 124 | 125 | void gatherpointLauncher(int b,int n,int m,const float * inp,const int * idx,float * out); 126 | class GatherPointGpuOp: public OpKernel{ 127 | public: 128 | explicit GatherPointGpuOp(OpKernelConstruction * context):OpKernel(context){} 129 | void Compute(OpKernelContext * context)override{ 130 | const Tensor& inp_tensor=context->input(0); 131 | OP_REQUIRES(context,inp_tensor.dims()==3 && inp_tensor.shape().dim_size(2)==3,errors::InvalidArgument("GatherPoint expects (batch_size,num_points,3) inp shape")); 132 | int b=inp_tensor.shape().dim_size(0); 133 | int n=inp_tensor.shape().dim_size(1); 134 | const Tensor& idx_tensor=context->input(1); 135 | OP_REQUIRES(context,idx_tensor.dims()==2 && idx_tensor.shape().dim_size(0)==b,errors::InvalidArgument("GatherPoint expects (batch_size,num_result) idx shape")); 136 | int m=idx_tensor.shape().dim_size(1); 137 | auto inp_flat=inp_tensor.flat(); 138 | const float * inp=&(inp_flat(0)); 139 | auto idx_flat=idx_tensor.flat(); 140 | const int * idx=&(idx_flat(0)); 141 | Tensor * out_tensor=NULL; 142 | OP_REQUIRES_OK(context,context->allocate_output(0,TensorShape{b,m,3},&out_tensor)); 143 | auto out_flat=out_tensor->flat(); 144 | float * out=&(out_flat(0)); 145 | gatherpointLauncher(b,n,m,inp,idx,out); 146 | } 147 | }; 148 | REGISTER_KERNEL_BUILDER(Name("GatherPoint").Device(DEVICE_GPU),GatherPointGpuOp); 149 | 150 | void scatteraddpointLauncher(int b,int n,int m,const float * out_g,const int * idx,float * inp_g); 151 | class GatherPointGradGpuOp: public OpKernel{ 152 | public: 153 | explicit GatherPointGradGpuOp(OpKernelConstruction * context):OpKernel(context){} 154 | void Compute(OpKernelContext * context)override{ 155 | const Tensor& inp_tensor=context->input(0); 156 | OP_REQUIRES(context,inp_tensor.dims()==3 && inp_tensor.shape().dim_size(2)==3,errors::InvalidArgument("GatherPointGradGpuOp expects (batch_size,num_points,3) inp")); 157 | int b=inp_tensor.shape().dim_size(0); 158 | int n=inp_tensor.shape().dim_size(1); 159 | const Tensor& idx_tensor=context->input(1); 160 | OP_REQUIRES(context,idx_tensor.dims()==2 && idx_tensor.shape().dim_size(0)==b,errors::InvalidArgument("GatherPointGradGpuOp expects (batch_size,num_result) idx shape")); 161 | int m=idx_tensor.shape().dim_size(1); 162 | auto inp_flat=inp_tensor.flat(); 163 | const float * inp=&(inp_flat(0)); 164 | auto idx_flat=idx_tensor.flat(); 165 | const int * idx=&(idx_flat(0)); 166 | const Tensor& out_g_tensor=context->input(2); 167 | OP_REQUIRES(context,out_g_tensor.dims()==3 && out_g_tensor.shape().dim_size(0)==b && out_g_tensor.shape().dim_size(1)==m && out_g_tensor.shape().dim_size(2)==3,errors::InvalidArgument("GatherPointGradGpuOp expects (batch_size,num_result,3) out_g shape")); 168 | auto out_g_flat=out_g_tensor.flat(); 169 | const float * out_g=&(out_g_flat(0)); 170 | Tensor * inp_g_tensor=NULL; 171 | OP_REQUIRES_OK(context,context->allocate_output(0,TensorShape{b,n,3},&inp_g_tensor)); 172 | auto inp_g_flat=inp_g_tensor->flat(); 173 | float * inp_g=&(inp_g_flat(0)); 174 | cudaMemset(inp_g,0,b*n*3*4); 175 | scatteraddpointLauncher(b,n,m,out_g,idx,inp_g); 176 | } 177 | }; 178 | REGISTER_KERNEL_BUILDER(Name("GatherPointGrad").Device(DEVICE_GPU),GatherPointGradGpuOp); 179 | 180 | -------------------------------------------------------------------------------- /tf_ops/grouping/tf_grouping.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include "tensorflow/core/framework/op.h" 7 | #include "tensorflow/core/framework/op_kernel.h" 8 | #include "tensorflow/core/framework/shape_inference.h" 9 | #include "tensorflow/core/framework/common_shape_fns.h" 10 | #include 11 | using namespace tensorflow; 12 | 13 | REGISTER_OP("QueryBallPoint") 14 | .Attr("radius: float") 15 | .Attr("nsample: int") 16 | .Input("xyz1: float32") 17 | .Input("xyz2: float32") 18 | .Output("idx: int32") 19 | .Output("pts_cnt: int32") 20 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 21 | ::tensorflow::shape_inference::ShapeHandle dims2; // batch_size * npoint * 3 22 | c->WithRank(c->input(1), 3, &dims2); 23 | int nsample; 24 | TF_RETURN_IF_ERROR(c->GetAttr("nsample", &nsample)); 25 | ::tensorflow::shape_inference::ShapeHandle output1 = c->MakeShape({c->Dim(dims2, 0), c->Dim(dims2, 1), nsample}); 26 | c->set_output(0, output1); 27 | ::tensorflow::shape_inference::ShapeHandle output2 = c->MakeShape({c->Dim(dims2, 0), c->Dim(dims2, 1)}); 28 | c->set_output(1, output2); 29 | return Status::OK(); 30 | }); 31 | REGISTER_OP("SelectionSort") 32 | .Attr("k: int") 33 | .Input("dist: float32") 34 | .Output("outi: int32") 35 | .Output("out: float32") 36 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 37 | c->set_output(0, c->input(0)); 38 | c->set_output(1, c->input(0)); 39 | return Status::OK(); 40 | }); 41 | REGISTER_OP("GroupPoint") 42 | .Input("points: float32") 43 | .Input("idx: int32") 44 | .Output("out: float32") 45 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 46 | ::tensorflow::shape_inference::ShapeHandle dims1; // batch_size * ndataset * channels 47 | c->WithRank(c->input(0), 3, &dims1); 48 | ::tensorflow::shape_inference::ShapeHandle dims2; // batch_size * npoints * nsample 49 | c->WithRank(c->input(1), 3, &dims2); 50 | // batch_size * npoints * nsample * channels 51 | ::tensorflow::shape_inference::ShapeHandle output = c->MakeShape({c->Dim(dims2, 0), c->Dim(dims2, 1), c->Dim(dims2, 2), c->Dim(dims1, 2)}); 52 | c->set_output(0, output); 53 | return Status::OK(); 54 | }); 55 | REGISTER_OP("GroupPointGrad") 56 | .Input("points: float32") 57 | .Input("idx: int32") 58 | .Input("grad_out: float32") 59 | .Output("grad_points: float32") 60 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 61 | c->set_output(0, c->input(0)); 62 | return Status::OK(); 63 | }); 64 | 65 | 66 | void queryBallPointLauncher(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx, int *pts_cnt); 67 | class QueryBallPointGpuOp : public OpKernel { 68 | public: 69 | explicit QueryBallPointGpuOp(OpKernelConstruction* context) : OpKernel(context) { 70 | OP_REQUIRES_OK(context, context->GetAttr("radius", &radius_)); 71 | OP_REQUIRES(context, radius_ > 0, errors::InvalidArgument("QueryBallPoint expects positive radius")); 72 | 73 | OP_REQUIRES_OK(context, context->GetAttr("nsample", &nsample_)); 74 | OP_REQUIRES(context, nsample_ > 0, errors::InvalidArgument("QueryBallPoint expects positive nsample")); 75 | } 76 | 77 | void Compute(OpKernelContext* context) override { 78 | const Tensor& xyz1_tensor = context->input(0); 79 | OP_REQUIRES(context, xyz1_tensor.dims()==3 && xyz1_tensor.shape().dim_size(2)==3, errors::InvalidArgument("QueryBallPoint expects (batch_size, ndataset, 3) xyz1 shape.")); 80 | int b = xyz1_tensor.shape().dim_size(0); 81 | int n = xyz1_tensor.shape().dim_size(1); 82 | 83 | const Tensor& xyz2_tensor = context->input(1); 84 | OP_REQUIRES(context, xyz2_tensor.dims()==3 && xyz2_tensor.shape().dim_size(2)==3, errors::InvalidArgument("QueryBallPoint expects (batch_size, npoint, 3) xyz2 shape.")); 85 | int m = xyz2_tensor.shape().dim_size(1); 86 | 87 | Tensor *idx_tensor = nullptr; 88 | OP_REQUIRES_OK(context, context->allocate_output(0, TensorShape{b,m,nsample_}, &idx_tensor)); 89 | Tensor *pts_cnt_tensor = nullptr; 90 | OP_REQUIRES_OK(context, context->allocate_output(1, TensorShape{b,m}, &pts_cnt_tensor)); 91 | 92 | auto xyz1_flat = xyz1_tensor.flat(); 93 | const float *xyz1 = &(xyz1_flat(0)); 94 | auto xyz2_flat = xyz2_tensor.flat(); 95 | const float *xyz2 = &(xyz2_flat(0)); 96 | auto idx_flat = idx_tensor->flat(); 97 | int *idx = &(idx_flat(0)); 98 | auto pts_cnt_flat = pts_cnt_tensor->flat(); 99 | int *pts_cnt = &(pts_cnt_flat(0)); 100 | queryBallPointLauncher(b,n,m,radius_,nsample_,xyz1,xyz2,idx,pts_cnt); 101 | } 102 | private: 103 | float radius_; 104 | int nsample_; 105 | }; 106 | REGISTER_KERNEL_BUILDER(Name("QueryBallPoint").Device(DEVICE_GPU), QueryBallPointGpuOp); 107 | 108 | void selectionSortLauncher(int b, int n, int m, int k, const float *dist, int *outi, float *out); 109 | class SelectionSortGpuOp : public OpKernel { 110 | public: 111 | explicit SelectionSortGpuOp(OpKernelConstruction* context) : OpKernel(context) { 112 | OP_REQUIRES_OK(context, context->GetAttr("k", &k_)); 113 | OP_REQUIRES(context, k_ > 0, errors::InvalidArgument("SelectionSort expects positive k")); 114 | } 115 | 116 | void Compute(OpKernelContext* context) override { 117 | const Tensor& dist_tensor = context->input(0); 118 | OP_REQUIRES(context, dist_tensor.dims()==3, errors::InvalidArgument("SelectionSort expects (b,m,n) dist shape.")); 119 | int b = dist_tensor.shape().dim_size(0); 120 | int m = dist_tensor.shape().dim_size(1); 121 | int n = dist_tensor.shape().dim_size(2); 122 | 123 | Tensor *outi_tensor = nullptr; 124 | OP_REQUIRES_OK(context, context->allocate_output(0, TensorShape{b,m,n}, &outi_tensor)); 125 | Tensor *out_tensor = nullptr; 126 | OP_REQUIRES_OK(context, context->allocate_output(1, TensorShape{b,m,n}, &out_tensor)); 127 | 128 | auto dist_flat = dist_tensor.flat(); 129 | const float *dist = &(dist_flat(0)); 130 | auto outi_flat = outi_tensor->flat(); 131 | int *outi = &(outi_flat(0)); 132 | auto out_flat = out_tensor->flat(); 133 | float *out = &(out_flat(0)); 134 | selectionSortLauncher(b,n,m,k_,dist,outi,out); 135 | } 136 | private: 137 | int k_; 138 | }; 139 | REGISTER_KERNEL_BUILDER(Name("SelectionSort").Device(DEVICE_GPU), SelectionSortGpuOp); 140 | 141 | 142 | void groupPointLauncher(int b, int n, int c, int m, int nsample, const float *points, const int *idx, float *out); 143 | class GroupPointGpuOp: public OpKernel{ 144 | public: 145 | explicit GroupPointGpuOp(OpKernelConstruction * context):OpKernel(context){} 146 | 147 | void Compute(OpKernelContext * context) override { 148 | const Tensor& points_tensor=context->input(0); 149 | OP_REQUIRES(context, points_tensor.dims()==3, errors::InvalidArgument("GroupPoint expects (batch_size, num_points, channel) points shape")); 150 | int b = points_tensor.shape().dim_size(0); 151 | int n = points_tensor.shape().dim_size(1); 152 | int c = points_tensor.shape().dim_size(2); 153 | 154 | const Tensor& idx_tensor=context->input(1); 155 | OP_REQUIRES(context,idx_tensor.dims()==3 && idx_tensor.shape().dim_size(0)==b, errors::InvalidArgument("GroupPoint expects (batch_size, npoints, nsample) idx shape")); 156 | int m = idx_tensor.shape().dim_size(1); 157 | int nsample = idx_tensor.shape().dim_size(2); 158 | 159 | Tensor * out_tensor = nullptr; 160 | OP_REQUIRES_OK(context, context->allocate_output(0,TensorShape{b,m,nsample,c}, &out_tensor)); 161 | 162 | auto points_flat = points_tensor.flat(); 163 | const float *points = &(points_flat(0)); 164 | auto idx_flat = idx_tensor.flat(); 165 | const int *idx = &(idx_flat(0)); 166 | auto out_flat = out_tensor->flat(); 167 | float *out = &(out_flat(0)); 168 | groupPointLauncher(b,n,c,m,nsample,points,idx,out); 169 | } 170 | }; 171 | REGISTER_KERNEL_BUILDER(Name("GroupPoint").Device(DEVICE_GPU),GroupPointGpuOp); 172 | 173 | void groupPointGradLauncher(int b, int n, int c, int m, int nsample, const float *grad_out, const int *idx, float *grad_points); 174 | class GroupPointGradGpuOp: public OpKernel{ 175 | public: 176 | explicit GroupPointGradGpuOp(OpKernelConstruction * context):OpKernel(context){} 177 | 178 | void Compute(OpKernelContext * context) override { 179 | const Tensor& points_tensor=context->input(0); 180 | OP_REQUIRES(context, points_tensor.dims()==3, errors::InvalidArgument("GroupPointGrad expects (batch_size, num_points, channel) points shape")); 181 | int b = points_tensor.shape().dim_size(0); 182 | int n = points_tensor.shape().dim_size(1); 183 | int c = points_tensor.shape().dim_size(2); 184 | 185 | const Tensor& idx_tensor=context->input(1); 186 | OP_REQUIRES(context,idx_tensor.dims()==3 && idx_tensor.shape().dim_size(0)==b, errors::InvalidArgument("GroupPointGrad expects (batch_size, npoints, nsample) idx shape")); 187 | int m = idx_tensor.shape().dim_size(1); 188 | int nsample = idx_tensor.shape().dim_size(2); 189 | 190 | const Tensor& grad_out_tensor=context->input(2); 191 | OP_REQUIRES(context,grad_out_tensor.dims()==4 && grad_out_tensor.shape().dim_size(0)==b && grad_out_tensor.shape().dim_size(1)==m && grad_out_tensor.shape().dim_size(2)==nsample && grad_out_tensor.shape().dim_size(3)==c, errors::InvalidArgument("GroupPointGrad expects (batch_size, npoints, nsample, channel) grad_out shape")); 192 | 193 | Tensor * grad_points_tensor = nullptr; 194 | OP_REQUIRES_OK(context, context->allocate_output(0,TensorShape{b,n,c}, &grad_points_tensor)); 195 | 196 | auto points_flat = points_tensor.flat(); 197 | const float *points = &(points_flat(0)); 198 | auto idx_flat = idx_tensor.flat(); 199 | const int *idx = &(idx_flat(0)); 200 | auto grad_out_flat = grad_out_tensor.flat(); 201 | const float *grad_out = &(grad_out_flat(0)); 202 | auto grad_points_flat = grad_points_tensor->flat(); 203 | float *grad_points = &(grad_points_flat(0)); 204 | cudaMemset(grad_points, 0, sizeof(float)*b*n*c); 205 | groupPointGradLauncher(b,n,c,m,nsample,grad_out,idx,grad_points); 206 | } 207 | }; 208 | REGISTER_KERNEL_BUILDER(Name("GroupPointGrad").Device(DEVICE_GPU),GroupPointGradGpuOp); 209 | 210 | 211 | -------------------------------------------------------------------------------- /models/ASIS/train.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import math 3 | import h5py 4 | import numpy as np 5 | import tensorflow as tf 6 | import socket 7 | 8 | import os 9 | import sys 10 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 11 | ROOT_DIR = os.path.dirname(os.path.dirname(BASE_DIR)) 12 | sys.path.append(BASE_DIR) 13 | #sys.path.append(os.path.join(ROOT_DIR, 'models')) 14 | sys.path.append(os.path.join(ROOT_DIR, 'utils')) 15 | import provider 16 | import tf_util 17 | from model import * 18 | 19 | parser = argparse.ArgumentParser() 20 | parser.add_argument('--gpu', type=int, default=0, help='GPU to use [default: GPU 0]') 21 | parser.add_argument('--log_dir', default='log', help='Log dir [default: log]') 22 | parser.add_argument('--num_point', type=int, default=4096, help='Point number [default: 4096]') 23 | parser.add_argument('--max_epoch', type=int, default=50, help='Epoch to run [default: 50]') 24 | parser.add_argument('--batch_size', type=int, default=24, help='Batch Size during training [default: 24]') 25 | parser.add_argument('--learning_rate', type=float, default=0.001, help='Initial learning rate [default: 0.001]') 26 | parser.add_argument('--momentum', type=float, default=0.9, help='Initial learning rate [default: 0.9]') 27 | parser.add_argument('--optimizer', default='adam', help='adam or momentum [default: adam]') 28 | parser.add_argument('--decay_step', type=int, default=300000, help='Decay step for lr decay [default: 300000]') 29 | parser.add_argument('--decay_rate', type=float, default=0.5, help='Decay rate for lr decay [default: 0.5]') 30 | parser.add_argument('--input_list', type=str, default='data/train_hdf5_file_list_woArea5.txt', help='Input data list file') 31 | parser.add_argument('--restore_model', type=str, default='log/', help='Pretrained model') 32 | FLAGS = parser.parse_args() 33 | 34 | 35 | BATCH_SIZE = FLAGS.batch_size 36 | NUM_POINT = FLAGS.num_point 37 | MAX_EPOCH = FLAGS.max_epoch 38 | BASE_LEARNING_RATE = FLAGS.learning_rate 39 | GPU_INDEX = FLAGS.gpu 40 | MOMENTUM = FLAGS.momentum 41 | OPTIMIZER = FLAGS.optimizer 42 | DECAY_STEP = FLAGS.decay_step 43 | DECAY_RATE = FLAGS.decay_rate 44 | 45 | TRAINING_FILE_LIST = FLAGS.input_list 46 | PRETRAINED_MODEL_PATH = FLAGS.restore_model 47 | 48 | LOG_DIR = FLAGS.log_dir 49 | if not os.path.exists(LOG_DIR): os.mkdir(LOG_DIR) 50 | #os.system('cp model.py %s' % (LOG_DIR)) # bkp of model def 51 | #os.system('cp train.py %s' % (LOG_DIR)) # bkp of train procedure 52 | LOG_FOUT = open(os.path.join(LOG_DIR, 'log_train.txt'), 'w') 53 | LOG_FOUT.write(str(FLAGS)+'\n') 54 | 55 | MAX_NUM_POINT = 4096 56 | NUM_CLASSES = 13 57 | 58 | BN_INIT_DECAY = 0.5 59 | BN_DECAY_DECAY_RATE = 0.5 60 | #BN_DECAY_DECAY_STEP = float(DECAY_STEP * 2) 61 | BN_DECAY_DECAY_STEP = float(DECAY_STEP) 62 | BN_DECAY_CLIP = 0.99 63 | 64 | HOSTNAME = socket.gethostname() 65 | 66 | 67 | # Load ALL data 68 | train_file_list = provider.getDataFiles(TRAINING_FILE_LIST) 69 | train_data = [] 70 | train_group = [] 71 | train_sem = [] 72 | for h5_filename in train_file_list: 73 | cur_data, cur_group, _, cur_sem = provider.loadDataFile_with_groupseglabel_stanfordindoor(h5_filename) 74 | train_data.append(cur_data) 75 | train_group.append(cur_group) 76 | train_sem.append(cur_sem) 77 | train_data = np.concatenate(train_data, axis=0) 78 | train_group = np.concatenate(train_group, axis=0) 79 | train_sem = np.concatenate(train_sem, axis=0) 80 | 81 | 82 | def log_string(out_str): 83 | LOG_FOUT.write(out_str+'\n') 84 | LOG_FOUT.flush() 85 | print(out_str) 86 | 87 | 88 | def get_learning_rate(batch): 89 | learning_rate = tf.train.exponential_decay( 90 | BASE_LEARNING_RATE, # Base learning rate. 91 | batch * BATCH_SIZE, # Current index into the dataset. 92 | DECAY_STEP, # Decay step. 93 | DECAY_RATE, # Decay rate. 94 | staircase=True) 95 | learning_rate = tf.maximum(learning_rate, 0.00001) # CLIP THE LEARNING RATE!! 96 | return learning_rate 97 | 98 | def get_bn_decay(batch): 99 | bn_momentum = tf.train.exponential_decay( 100 | BN_INIT_DECAY, 101 | batch*BATCH_SIZE, 102 | BN_DECAY_DECAY_STEP, 103 | BN_DECAY_DECAY_RATE, 104 | staircase=True) 105 | bn_decay = tf.minimum(BN_DECAY_CLIP, 1 - bn_momentum) 106 | return bn_decay 107 | 108 | def get_trainable_variables(): 109 | #trainables = [var for var in tf.trainable_variables() if 'bias' not in var.name]# and \ 110 | trainables = tf.trainable_variables() 111 | print("All {} trainable variables, {} variables to train".format(len(tf.trainable_variables()), len(trainables))) 112 | return trainables 113 | 114 | 115 | def train(): 116 | with tf.Graph().as_default(): 117 | with tf.device('/gpu:'+str(GPU_INDEX)): 118 | pointclouds_pl, labels_pl, sem_labels_pl = placeholder_inputs(BATCH_SIZE, NUM_POINT) 119 | is_training_pl = tf.placeholder(tf.bool, shape=()) 120 | 121 | # Note the global_step=batch parameter to minimize. 122 | # That tells the optimizer to helpfully increment the 'batch' parameter for you every time it trains. 123 | batch = tf.Variable(0) 124 | bn_decay = get_bn_decay(batch) 125 | tf.summary.scalar('bn_decay', bn_decay) 126 | 127 | # Get model and loss 128 | pred_sem, pred_ins = get_model(pointclouds_pl, is_training_pl, NUM_CLASSES, bn_decay=bn_decay) 129 | pred_sem_softmax = tf.nn.softmax(pred_sem) 130 | pred_sem_label = tf.argmax(pred_sem_softmax, axis=2) 131 | 132 | loss, sem_loss, disc_loss, l_var, l_dist, l_reg = get_loss(pred_ins, labels_pl, pred_sem_label, pred_sem, sem_labels_pl) 133 | tf.summary.scalar('loss', loss) 134 | tf.summary.scalar('sem_loss', sem_loss) 135 | tf.summary.scalar('disc_loss', disc_loss) 136 | tf.summary.scalar('l_var', l_var) 137 | tf.summary.scalar('l_dist', l_dist) 138 | tf.summary.scalar('l_reg', l_reg) 139 | 140 | 141 | trainables = get_trainable_variables() 142 | 143 | # Get training operator 144 | learning_rate = get_learning_rate(batch) 145 | tf.summary.scalar('learning_rate', learning_rate) 146 | if OPTIMIZER == 'momentum': 147 | optimizer = tf.train.MomentumOptimizer(learning_rate, momentum=MOMENTUM) 148 | elif OPTIMIZER == 'adam': 149 | optimizer = tf.train.AdamOptimizer(learning_rate) 150 | 151 | train_op = optimizer.minimize(loss, var_list=trainables, global_step=batch) 152 | 153 | 154 | load_var_list = [v for v in tf.all_variables() if ('sem_' not in v.name)] 155 | loader = tf.train.Saver(load_var_list, sharded=True) 156 | 157 | # Add ops to save and restore all the variables. 158 | saver = tf.train.Saver() 159 | 160 | # Create a session 161 | config = tf.ConfigProto() 162 | config.gpu_options.allow_growth = True 163 | config.allow_soft_placement = True 164 | config.log_device_placement = True 165 | sess = tf.Session(config=config) 166 | 167 | # Add summary writers 168 | merged = tf.summary.merge_all() 169 | train_writer = tf.summary.FileWriter(os.path.join(LOG_DIR, 'train'), 170 | sess.graph) 171 | test_writer = tf.summary.FileWriter(os.path.join(LOG_DIR, 'test')) 172 | 173 | # Init variables 174 | init = tf.global_variables_initializer() 175 | sess.run(init, {is_training_pl:True}) 176 | 177 | ckptstate = tf.train.get_checkpoint_state(PRETRAINED_MODEL_PATH) 178 | if ckptstate is not None: 179 | LOAD_MODEL_FILE = os.path.join(PRETRAINED_MODEL_PATH, os.path.basename(ckptstate.model_checkpoint_path)) 180 | loader.restore(sess, LOAD_MODEL_FILE) 181 | log_string("Model loaded in file: %s" % LOAD_MODEL_FILE) 182 | else: 183 | log_string("Fail to load modelfile: %s" % PRETRAINED_MODEL_PATH) 184 | 185 | 186 | #sess.run(tf.variables_initializer([var for var in tf.trainable_variables() if 'bias' in var.name and \ 187 | # 'conv1' not in var.name and \ 188 | # 'conv2' not in var.name]) 189 | # ) 190 | adam_initializers = [var.initializer for var in tf.global_variables() if 'Adam' in var.name] 191 | sess.run(adam_initializers) 192 | 193 | ops = {'pointclouds_pl': pointclouds_pl, 194 | 'labels_pl': labels_pl, 195 | 'sem_labels_pl': sem_labels_pl, 196 | 'is_training_pl': is_training_pl, 197 | 'loss': loss, 198 | 'sem_loss': sem_loss, 199 | 'disc_loss': disc_loss, 200 | 'l_var': l_var, 201 | 'l_dist': l_dist, 202 | 'l_reg': l_reg, 203 | 'train_op': train_op, 204 | 'merged': merged, 205 | 'step': batch} 206 | 207 | for epoch in range(MAX_EPOCH): 208 | log_string('**** EPOCH %03d ****' % (epoch)) 209 | sys.stdout.flush() 210 | 211 | train_one_epoch(sess, ops, train_writer) 212 | 213 | # Save the variables to disk. 214 | if epoch % 10 == 0 or epoch == (MAX_EPOCH - 1): 215 | save_path = saver.save(sess, os.path.join(LOG_DIR, 'epoch_' + str(epoch) + '.ckpt')) 216 | log_string("Model saved in file: %s" % save_path) 217 | 218 | 219 | def train_one_epoch(sess, ops, train_writer): 220 | """ ops: dict mapping from string to tf ops """ 221 | is_training = True 222 | 223 | log_string('----') 224 | current_data, current_label, shuffled_idx = provider.shuffle_data(train_data[:, 0:NUM_POINT, :], train_group) 225 | current_sem = train_sem[shuffled_idx] 226 | 227 | file_size = current_data.shape[0] 228 | num_batches = file_size // BATCH_SIZE 229 | 230 | loss_sum = 0 231 | 232 | for batch_idx in range(num_batches): 233 | if batch_idx % 100 == 0: 234 | print('Current batch/total batch num: %d/%d'%(batch_idx,num_batches)) 235 | start_idx = batch_idx * BATCH_SIZE 236 | end_idx = (batch_idx+1) * BATCH_SIZE 237 | 238 | feed_dict = {ops['pointclouds_pl']: current_data[start_idx:end_idx, :, :], 239 | ops['labels_pl']: current_label[start_idx:end_idx], 240 | ops['sem_labels_pl']: current_sem[start_idx:end_idx], 241 | ops['is_training_pl']: is_training,} 242 | summary, step, _, loss_val, sem_loss_val, disc_loss_val, l_var_val, l_dist_val, l_reg_val = sess.run([ops['merged'], ops['step'], ops['train_op'], ops['loss'], ops['sem_loss'], ops['disc_loss'], ops['l_var'], ops['l_dist'], ops['l_reg']], 243 | feed_dict=feed_dict) 244 | train_writer.add_summary(summary, step) 245 | loss_sum += loss_val 246 | 247 | if batch_idx % 50 == 0: 248 | log_string("loss: {:.2f}; sem_loss: {:.2f}; disc_loss: {:.2f}; l_var: {:.2f}; l_dist: {:.2f}; l_reg: {:.3f}.".format(loss_val, sem_loss_val, disc_loss_val, l_var_val, l_dist_val, l_reg_val)) 249 | 250 | log_string('mean loss: %f' % (loss_sum / float(num_batches))) 251 | 252 | 253 | 254 | 255 | if __name__ == "__main__": 256 | train() 257 | LOG_FOUT.close() 258 | -------------------------------------------------------------------------------- /models/ASIS/test.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import math 3 | import h5py 4 | import numpy as np 5 | import tensorflow as tf 6 | import socket 7 | from scipy import stats 8 | from IPython import embed 9 | 10 | import os 11 | import sys 12 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 13 | ROOT_DIR = os.path.dirname(os.path.dirname(BASE_DIR)) 14 | sys.path.append(BASE_DIR) 15 | sys.path.append(ROOT_DIR) 16 | sys.path.append(os.path.join(ROOT_DIR, 'utils')) 17 | import provider 18 | import tf_util 19 | from model import * 20 | from test_utils import * 21 | from clustering import cluster 22 | import indoor3d_util 23 | 24 | parser = argparse.ArgumentParser() 25 | parser.add_argument('--gpu', type=int, default=0, help='GPU to use [default: GPU 0]') 26 | parser.add_argument('--verbose', action='store_true', help='if specified, output color-coded seg obj files') 27 | parser.add_argument('--log_dir', default='log', help='Log dir [default: log]') 28 | parser.add_argument('--num_point', type=int, default=4096, help='Point number [default: 4096]') 29 | parser.add_argument('--bandwidth', type=float, default=1., help='Bandwidth for meanshift clustering [default: 1.]') 30 | parser.add_argument('--input_list', type=str, default='data/test_hdf5_file_list_Area5.txt', help='Input data list file') 31 | parser.add_argument('--model_path', type=str, default='log/model.ckpt', help='Path of model') 32 | FLAGS = parser.parse_args() 33 | 34 | 35 | BATCH_SIZE = 1 36 | NUM_POINT = FLAGS.num_point 37 | GPU_INDEX = FLAGS.gpu 38 | MODEL_PATH = FLAGS.model_path 39 | TEST_FILE_LIST = FLAGS.input_list 40 | BANDWIDTH = FLAGS.bandwidth 41 | 42 | mean_num_pts_in_group = np.loadtxt(os.path.join(MODEL_PATH.split('/')[0], 'mean_ins_size.txt')) 43 | 44 | output_verbose = FLAGS.verbose # If true, output all color-coded segmentation obj files 45 | 46 | LOG_DIR = FLAGS.log_dir 47 | if not os.path.exists(LOG_DIR): os.mkdir(LOG_DIR) 48 | 49 | OUTPUT_DIR = os.path.join(LOG_DIR, 'test_results') 50 | if not os.path.exists(OUTPUT_DIR): 51 | os.mkdir(OUTPUT_DIR) 52 | 53 | os.system('cp inference_merge.py %s' % (LOG_DIR)) # bkp of train procedure 54 | LOG_FOUT = open(os.path.join(LOG_DIR, 'log_inference.txt'), 'w') 55 | LOG_FOUT.write(str(FLAGS)+'\n') 56 | 57 | MAX_NUM_POINT = 4096 58 | NUM_CLASSES = 13 59 | NEW_NUM_CLASSES = 13 60 | 61 | HOSTNAME = socket.gethostname() 62 | 63 | ROOM_PATH_LIST = [os.path.join(ROOT_DIR,line.rstrip()) for line in open(os.path.join(ROOT_DIR, FLAGS.input_list))] 64 | len_pts_files = len(ROOM_PATH_LIST) 65 | 66 | def log_string(out_str): 67 | LOG_FOUT.write(out_str+'\n') 68 | LOG_FOUT.flush() 69 | print(out_str) 70 | 71 | 72 | def test(): 73 | with tf.Graph().as_default(): 74 | with tf.device('/gpu:' + str(GPU_INDEX)): 75 | pointclouds_pl, labels_pl, sem_labels_pl = placeholder_inputs(BATCH_SIZE, NUM_POINT) 76 | is_training_pl = tf.placeholder(tf.bool, shape=()) 77 | 78 | # Get model and loss 79 | pred_sem, pred_ins = get_model(pointclouds_pl, is_training_pl, NUM_CLASSES) 80 | pred_sem_softmax = tf.nn.softmax(pred_sem) 81 | pred_sem_label = tf.argmax(pred_sem_softmax, axis=2) 82 | 83 | loss, sem_loss, disc_loss, l_var, l_dist, l_reg = get_loss(pred_ins, labels_pl, pred_sem_label, pred_sem, sem_labels_pl) 84 | 85 | 86 | loader = tf.train.Saver() 87 | 88 | 89 | # Create a session 90 | config = tf.ConfigProto() 91 | config.gpu_options.allow_growth = True 92 | config.allow_soft_placement = True 93 | config.log_device_placement = True 94 | sess = tf.Session(config=config) 95 | 96 | is_training = False 97 | 98 | # Restore variables from disk. 99 | loader.restore(sess, MODEL_PATH) 100 | log_string("Model restored.") 101 | 102 | ops = {'pointclouds_pl': pointclouds_pl, 103 | 'labels_pl': labels_pl, 104 | 'sem_labels_pl': sem_labels_pl, 105 | 'is_training_pl': is_training_pl, 106 | 'pred_ins': pred_ins, 107 | 'pred_sem_label': pred_sem_label, 108 | 'pred_sem_softmax': pred_sem_softmax, 109 | 'loss': loss, 110 | 'l_var': l_var, 111 | 'l_dist': l_dist, 112 | 'l_reg': l_reg} 113 | 114 | total_acc = 0.0 115 | total_seen = 0 116 | 117 | ious = np.zeros(NEW_NUM_CLASSES) 118 | totalnums = np.zeros(NEW_NUM_CLASSES) 119 | 120 | total_gt_ins = np.zeros(NUM_CLASSES) 121 | at = 0.5 122 | tpsins = [[] for itmp in range(NUM_CLASSES)] 123 | fpsins = [[] for itmp in range(NUM_CLASSES)] 124 | all_mean_cov = [[] for itmp in range(NUM_CLASSES)] 125 | all_mean_weighted_cov = [[] for itmp in range(NUM_CLASSES)] 126 | 127 | output_filelist_f = os.path.join(LOG_DIR, 'output_filelist.txt') 128 | fout_out_filelist = open(output_filelist_f, 'w') 129 | for shape_idx in range(len_pts_files): 130 | room_path = ROOM_PATH_LIST[shape_idx] 131 | log_string('%d / %d ...' % (shape_idx, len_pts_files)) 132 | log_string('Loading train file ' + room_path) 133 | out_data_label_filename = os.path.basename(room_path)[:-4] + '_pred.txt' 134 | out_data_label_filename = os.path.join(OUTPUT_DIR, out_data_label_filename) 135 | out_gt_label_filename = os.path.basename(room_path)[:-4] + '_gt.txt' 136 | out_gt_label_filename = os.path.join(OUTPUT_DIR, out_gt_label_filename) 137 | fout_data_label = open(out_data_label_filename, 'w') 138 | fout_gt_label = open(out_gt_label_filename, 'w') 139 | 140 | fout_out_filelist.write(out_data_label_filename+'\n') 141 | 142 | cur_data, cur_sem, cur_group = indoor3d_util.room2blocks_wrapper_normalized(room_path, NUM_POINT, block_size=1.0, stride=0.5, 143 | random_sample=False, sample_num=None) 144 | cur_data = cur_data[:, 0:NUM_POINT, :] 145 | cur_sem = np.squeeze(cur_sem) 146 | cur_group = np.squeeze(cur_group) 147 | # Get room dimension.. 148 | data_label = np.load(room_path) 149 | data = data_label[:, 0:6] 150 | max_room_x = max(data[:, 0]) 151 | max_room_y = max(data[:, 1]) 152 | max_room_z = max(data[:, 2]) 153 | 154 | cur_pred_sem = np.zeros_like(cur_sem) 155 | cur_pred_sem_softmax = np.zeros([cur_sem.shape[0], cur_sem.shape[1], NUM_CLASSES]) 156 | group_output = np.zeros_like(cur_group) 157 | 158 | gap = 5e-3 159 | volume_num = int(1. / gap)+1 160 | volume = -1* np.ones([volume_num,volume_num,volume_num]).astype(np.int32) 161 | volume_seg = -1* np.ones([volume_num,volume_num,volume_num]).astype(np.int32) 162 | 163 | intersections = np.zeros(NEW_NUM_CLASSES) 164 | unions = np.zeros(NEW_NUM_CLASSES) 165 | 166 | num_data = cur_data.shape[0] 167 | for j in range(num_data): 168 | log_string("Processsing: Shape [%d] Block[%d]"%(shape_idx, j)) 169 | 170 | pts = cur_data[j,...] 171 | group = cur_group[j] 172 | sem = cur_sem[j] 173 | 174 | feed_dict = {ops['pointclouds_pl']: np.expand_dims(pts, 0), 175 | ops['labels_pl']: np.expand_dims(group, 0), 176 | ops['sem_labels_pl']: np.expand_dims(sem, 0), 177 | ops['is_training_pl']: is_training} 178 | 179 | loss_val, l_var_val, l_dist_val, l_reg_val, pred_ins_val, pred_sem_label_val, pred_sem_softmax_val = sess.run( 180 | [ops['loss'], ops['l_var'], ops['l_dist'], ops['l_reg'], ops['pred_ins'], ops['pred_sem_label'], ops['pred_sem_softmax']], 181 | feed_dict=feed_dict) 182 | 183 | pred_val = np.squeeze(pred_ins_val, axis=0) 184 | pred_sem = np.squeeze(pred_sem_label_val, axis=0) 185 | pred_sem_softmax = np.squeeze(pred_sem_softmax_val, axis=0) 186 | cur_pred_sem[j, :] = pred_sem 187 | cur_pred_sem_softmax[j, ...] = pred_sem_softmax 188 | 189 | # cluster 190 | group_seg = {} 191 | bandwidth = BANDWIDTH 192 | num_clusters, labels, cluster_centers = cluster(pred_val, bandwidth) 193 | for idx_cluster in range(num_clusters): 194 | tmp = (labels == idx_cluster) 195 | estimated_seg = int(stats.mode(pred_sem[tmp])[0]) 196 | group_seg[idx_cluster] = estimated_seg 197 | 198 | groupids_block = labels 199 | 200 | groupids = BlockMerging(volume, volume_seg, pts[:, 6:], 201 | groupids_block.astype(np.int32), group_seg, gap) 202 | 203 | group_output[j, :] = groupids 204 | total_acc += float(np.sum(pred_sem==sem))/pred_sem.shape[0] 205 | total_seen += 1 206 | 207 | group_pred = group_output.reshape(-1) 208 | seg_pred = cur_pred_sem.reshape(-1) 209 | seg_pred_softmax = cur_pred_sem_softmax.reshape([-1, NUM_CLASSES]) 210 | pts = cur_data.reshape([-1, 9]) 211 | 212 | # filtering 213 | x = (pts[:, 6] / gap).astype(np.int32) 214 | y = (pts[:, 7] / gap).astype(np.int32) 215 | z = (pts[:, 8] / gap).astype(np.int32) 216 | for i in range(group_pred.shape[0]): 217 | if volume[x[i], y[i], z[i]] != -1: 218 | group_pred[i] = volume[x[i], y[i], z[i]] 219 | 220 | seg_gt = cur_sem.reshape(-1) 221 | un = np.unique(group_pred) 222 | pts_in_pred = [[] for itmp in range(NUM_CLASSES)] 223 | group_pred_final = -1 * np.ones_like(group_pred) 224 | grouppred_cnt = 0 225 | for ig, g in enumerate(un): #each object in prediction 226 | if g == -1: 227 | continue 228 | tmp = (group_pred == g) 229 | sem_seg_g = int(stats.mode(seg_pred[tmp])[0]) 230 | #if np.sum(tmp) > 500: 231 | if np.sum(tmp) > 0.25 * mean_num_pts_in_group[sem_seg_g]: 232 | group_pred_final[tmp] = grouppred_cnt 233 | pts_in_pred[sem_seg_g] += [tmp] 234 | grouppred_cnt += 1 235 | 236 | if output_verbose: 237 | #output_color_point_cloud(pts[:, 6:], group_pred_final.astype(np.int32), 238 | # os.path.join(OUTPUT_DIR, '%d_grouppred.obj' % (shape_idx))) 239 | pts[:, 6] *= max_room_x 240 | pts[:, 7] *= max_room_y 241 | pts[:, 8] *= max_room_z 242 | pts[:, 3:6] *= 255.0 243 | ins = group_pred_final.astype(np.int32) 244 | sem = seg_pred.astype(np.int32) 245 | sem_softmax = seg_pred_softmax 246 | sem_gt = seg_gt 247 | ins_gt = cur_group.reshape(-1) 248 | for i in range(pts.shape[0]): 249 | fout_data_label.write('%f %f %f %d %d %d %f %d %d\n' % ( 250 | pts[i, 6], pts[i, 7], pts[i, 8], pts[i, 3], pts[i, 4], pts[i, 5], sem_softmax[i, sem[i]], sem[i], ins[i])) 251 | fout_gt_label.write('%d %d\n' % (sem_gt[i], ins_gt[i])) 252 | 253 | fout_data_label.close() 254 | fout_gt_label.close() 255 | 256 | 257 | fout_out_filelist.close() 258 | 259 | if __name__ == "__main__": 260 | test() 261 | LOG_FOUT.close() 262 | -------------------------------------------------------------------------------- /tf_ops/3d_interpolation/tf_interpolate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include "tensorflow/core/framework/op.h" 7 | #include "tensorflow/core/framework/op_kernel.h" 8 | #include "tensorflow/core/framework/shape_inference.h" 9 | #include "tensorflow/core/framework/common_shape_fns.h" 10 | using namespace tensorflow; 11 | 12 | REGISTER_OP("ThreeNN") 13 | .Input("xyz1: float32") 14 | .Input("xyz2: float32") 15 | .Output("dist: float32") 16 | .Output("idx: int32") 17 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 18 | c->set_output(0, c->input(0)); 19 | c->set_output(1, c->input(0)); 20 | return Status::OK(); 21 | }); 22 | REGISTER_OP("ThreeInterpolate") 23 | .Input("points: float32") 24 | .Input("idx: int32") 25 | .Input("weight: float32") 26 | .Output("out: float32") 27 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 28 | ::tensorflow::shape_inference::ShapeHandle dims1; // (b,m,c) 29 | c->WithRank(c->input(0), 3, &dims1); 30 | ::tensorflow::shape_inference::ShapeHandle dims2; // (b,n,3) 31 | c->WithRank(c->input(1), 3, &dims2); 32 | // (b,n,c) 33 | ::tensorflow::shape_inference::ShapeHandle output = c->MakeShape({c->Dim(dims1, 0), c->Dim(dims2, 1), c->Dim(dims1, 2)}); 34 | c->set_output(0, output); 35 | return Status::OK(); 36 | }); 37 | REGISTER_OP("ThreeInterpolateGrad") 38 | .Input("points: float32") 39 | .Input("idx: int32") 40 | .Input("weight: float32") 41 | .Input("grad_out: float32") 42 | .Output("grad_points: float32") 43 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 44 | c->set_output(0, c->input(0)); 45 | return Status::OK(); 46 | }); 47 | 48 | float randomf(){ 49 | return (rand()+0.5)/(RAND_MAX+1.0); 50 | } 51 | static double get_time(){ 52 | timespec tp; 53 | clock_gettime(CLOCK_MONOTONIC,&tp); 54 | return tp.tv_sec+tp.tv_nsec*1e-9; 55 | } 56 | 57 | // Find three nearest neigbors with square distance 58 | // input: xyz1 (b,n,3), xyz2(b,m,3) 59 | // output: dist (b,n,3), idx (b,n,3) 60 | void threenn_cpu(int b, int n, int m, const float *xyz1, const float *xyz2, float *dist, int *idx) { 61 | for (int i=0;iinput(0); 163 | OP_REQUIRES(context, xyz1_tensor.dims()==3 && xyz1_tensor.shape().dim_size(2)==3, errors::InvalidArgument("ThreeNN expects (b,n,3) xyz1 shape.")); 164 | int b = xyz1_tensor.shape().dim_size(0); 165 | int n = xyz1_tensor.shape().dim_size(1); 166 | 167 | const Tensor& xyz2_tensor = context->input(1); 168 | OP_REQUIRES(context, xyz2_tensor.dims()==3 && xyz2_tensor.shape().dim_size(2)==3, errors::InvalidArgument("ThreeNN expects (b,m,3) xyz2 shape.")); 169 | int m = xyz2_tensor.shape().dim_size(1); 170 | 171 | Tensor *dist_tensor = nullptr; 172 | OP_REQUIRES_OK(context, context->allocate_output(0, TensorShape{b,n,3}, &dist_tensor)); 173 | Tensor *idx_tensor = nullptr; 174 | OP_REQUIRES_OK(context, context->allocate_output(1, TensorShape{b,n,3}, &idx_tensor)); 175 | 176 | auto xyz1_flat = xyz1_tensor.flat(); 177 | const float *xyz1 = &(xyz1_flat(0)); 178 | auto xyz2_flat = xyz2_tensor.flat(); 179 | const float *xyz2 = &(xyz2_flat(0)); 180 | auto dist_flat = dist_tensor->flat(); 181 | float *dist = &(dist_flat(0)); 182 | auto idx_flat = idx_tensor->flat(); 183 | int *idx = &(idx_flat(0)); 184 | threenn_cpu(b,n,m,xyz1,xyz2,dist,idx); 185 | } 186 | }; 187 | REGISTER_KERNEL_BUILDER(Name("ThreeNN").Device(DEVICE_CPU), ThreeNNOp); 188 | 189 | 190 | 191 | class ThreeInterpolateOp: public OpKernel{ 192 | public: 193 | explicit ThreeInterpolateOp(OpKernelConstruction * context):OpKernel(context){} 194 | 195 | void Compute(OpKernelContext * context) override { 196 | const Tensor& points_tensor=context->input(0); 197 | OP_REQUIRES(context, points_tensor.dims()==3, errors::InvalidArgument("ThreeInterpolate expects (b,m,c) points shape")); 198 | int b = points_tensor.shape().dim_size(0); 199 | int m = points_tensor.shape().dim_size(1); 200 | int c = points_tensor.shape().dim_size(2); 201 | 202 | const Tensor& idx_tensor=context->input(1); 203 | OP_REQUIRES(context,idx_tensor.dims()==3 && idx_tensor.shape().dim_size(0)==b && idx_tensor.shape().dim_size(2)==3, errors::InvalidArgument("ThreeInterpolate expects (b,n,3) idx shape")); 204 | int n = idx_tensor.shape().dim_size(1); 205 | const Tensor& weight_tensor=context->input(2); 206 | OP_REQUIRES(context,weight_tensor.dims()==3 && weight_tensor.shape().dim_size(0)==b && weight_tensor.shape().dim_size(1)==n && weight_tensor.shape().dim_size(2)==3, errors::InvalidArgument("ThreeInterpolate expects (b,n,3) weight shape")); 207 | 208 | Tensor * out_tensor = nullptr; 209 | OP_REQUIRES_OK(context, context->allocate_output(0,TensorShape{b,n,c}, &out_tensor)); 210 | 211 | auto points_flat = points_tensor.flat(); 212 | const float *points = &(points_flat(0)); 213 | auto idx_flat = idx_tensor.flat(); 214 | const int *idx = &(idx_flat(0)); 215 | auto weight_flat = weight_tensor.flat(); 216 | const float *weight = &(weight_flat(0)); 217 | auto out_flat = out_tensor->flat(); 218 | float *out = &(out_flat(0)); 219 | threeinterpolate_cpu(b,m,c,n,points,idx,weight,out); 220 | } 221 | }; 222 | REGISTER_KERNEL_BUILDER(Name("ThreeInterpolate").Device(DEVICE_CPU),ThreeInterpolateOp); 223 | 224 | 225 | class ThreeInterpolateGradOp: public OpKernel{ 226 | public: 227 | explicit ThreeInterpolateGradOp(OpKernelConstruction * context):OpKernel(context){} 228 | 229 | void Compute(OpKernelContext * context) override { 230 | const Tensor& points_tensor=context->input(0); 231 | OP_REQUIRES(context, points_tensor.dims()==3, errors::InvalidArgument("ThreeInterpolateGrad expects (b,m,c) points shape")); 232 | int b = points_tensor.shape().dim_size(0); 233 | int m = points_tensor.shape().dim_size(1); 234 | int c = points_tensor.shape().dim_size(2); 235 | 236 | const Tensor& idx_tensor=context->input(1); 237 | OP_REQUIRES(context,idx_tensor.dims()==3 && idx_tensor.shape().dim_size(0)==b, errors::InvalidArgument("ThreeInterpolateGrad expects (b,n,3) idx shape")); 238 | int n = idx_tensor.shape().dim_size(1); 239 | const Tensor& weight_tensor=context->input(2); 240 | OP_REQUIRES(context,weight_tensor.dims()==3 && weight_tensor.shape().dim_size(0)==b && weight_tensor.shape().dim_size(1)==n && weight_tensor.shape().dim_size(2)==3, errors::InvalidArgument("ThreeInterpolateGrad expects (b,n,3) weight shape")); 241 | 242 | const Tensor& grad_out_tensor=context->input(3); 243 | OP_REQUIRES(context,grad_out_tensor.dims()==3 && grad_out_tensor.shape().dim_size(0)==b && grad_out_tensor.shape().dim_size(1)==n && grad_out_tensor.shape().dim_size(2)==c, errors::InvalidArgument("ThreeInterpolateGrad expects (b,n,c) grad_out shape")); 244 | 245 | Tensor * grad_points_tensor = nullptr; 246 | OP_REQUIRES_OK(context, context->allocate_output(0,TensorShape{b,m,c}, &grad_points_tensor)); 247 | 248 | auto points_flat = points_tensor.flat(); 249 | const float *points = &(points_flat(0)); 250 | auto idx_flat = idx_tensor.flat(); 251 | const int *idx = &(idx_flat(0)); 252 | auto weight_flat = weight_tensor.flat(); 253 | const float *weight = &(weight_flat(0)); 254 | auto grad_out_flat = grad_out_tensor.flat(); 255 | const float *grad_out = &(grad_out_flat(0)); 256 | auto grad_points_flat = grad_points_tensor->flat(); 257 | float *grad_points = &(grad_points_flat(0)); 258 | memset(grad_points, 0, sizeof(float)*b*m*c); 259 | threeinterpolate_grad_cpu(b,n,c,m,grad_out,idx,weight,grad_points); 260 | } 261 | }; 262 | REGISTER_KERNEL_BUILDER(Name("ThreeInterpolateGrad").Device(DEVICE_CPU),ThreeInterpolateGradOp); 263 | 264 | 265 | -------------------------------------------------------------------------------- /utils/test_utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy import stats 3 | import matplotlib as mpl 4 | import json 5 | mpl.use('Agg') 6 | 7 | 8 | ############################ 9 | ## Ths Statistics ## 10 | ############################ 11 | 12 | def Get_Ths(pts_corr, seg, ins, ths, ths_, cnt): 13 | 14 | pts_in_ins = {} 15 | for ip, pt in enumerate(pts_corr): 16 | if ins[ip] in pts_in_ins.keys(): 17 | pts_in_curins_ind = pts_in_ins[ins[ip]] 18 | pts_notin_curins_ind = (~(pts_in_ins[ins[ip]])) & (seg==seg[ip]) 19 | hist, bin = np.histogram(pt[pts_in_curins_ind], bins=20) 20 | 21 | if seg[ip]==8: 22 | print bin 23 | 24 | numpt_in_curins = np.sum(pts_in_curins_ind) 25 | numpt_notin_curins = np.sum(pts_notin_curins_ind) 26 | 27 | if numpt_notin_curins > 0: 28 | 29 | tp_over_fp = 0 30 | ib_opt = -2 31 | for ib, b in enumerate(bin): 32 | if b == 0: 33 | break 34 | tp = float(np.sum(pt[pts_in_curins_ind] < bin[ib])) / float(numpt_in_curins) 35 | fp = float(np.sum(pt[pts_notin_curins_ind] < bin[ib])) / float(numpt_notin_curins) 36 | 37 | if tp <= 0.5: 38 | continue 39 | 40 | if fp == 0. and tp > 0.5: 41 | ib_opt = ib 42 | break 43 | 44 | if tp/fp > tp_over_fp: 45 | tp_over_fp = tp / fp 46 | ib_opt = ib 47 | 48 | if tp_over_fp > 4.: 49 | ths[seg[ip]] += bin[ib_opt] 50 | ths_[seg[ip]] += bin[ib_opt] 51 | cnt[seg[ip]] += 1 52 | 53 | else: 54 | pts_in_curins_ind = (ins == ins[ip]) 55 | pts_in_ins[ins[ip]] = pts_in_curins_ind 56 | pts_notin_curins_ind = (~(pts_in_ins[ins[ip]])) & (seg==seg[ip]) 57 | hist, bin = np.histogram(pt[pts_in_curins_ind], bins=20) 58 | 59 | if seg[ip]==8: 60 | print bin 61 | 62 | numpt_in_curins = np.sum(pts_in_curins_ind) 63 | numpt_notin_curins = np.sum(pts_notin_curins_ind) 64 | 65 | if numpt_notin_curins > 0: 66 | 67 | tp_over_fp = 0 68 | ib_opt = -2 69 | for ib, b in enumerate(bin): 70 | 71 | if b == 0: 72 | break 73 | 74 | tp = float(np.sum(pt[pts_in_curins_ind] 0.5: 81 | ib_opt = ib 82 | break 83 | 84 | if tp / fp > tp_over_fp: 85 | tp_over_fp = tp / fp 86 | ib_opt = ib 87 | 88 | if tp_over_fp > 4.: 89 | ths[seg[ip]] += bin[ib_opt] 90 | ths_[seg[ip]] += bin[ib_opt] 91 | cnt[seg[ip]] += 1 92 | 93 | return ths, ths_, cnt 94 | 95 | 96 | ############################## 97 | ## Merging Algorithms ## 98 | ############################## 99 | 100 | def GroupMerging(pts_corr, confidence, seg, label_bin): 101 | 102 | confvalidpts = (confidence>0.4) 103 | un_seg = np.unique(seg) 104 | refineseg = -1* np.ones(pts_corr.shape[0]) 105 | groupid = -1* np.ones(pts_corr.shape[0]) 106 | numgroups = 0 107 | groupseg = {} 108 | for i_seg in un_seg: 109 | if i_seg==-1: 110 | continue 111 | pts_in_seg = (seg==i_seg) 112 | valid_seg_group = np.where(pts_in_seg & confvalidpts) 113 | proposals = [] 114 | if valid_seg_group[0].shape[0]==0: 115 | proposals += [pts_in_seg] 116 | else: 117 | for ip in valid_seg_group[0]: 118 | validpt = (pts_corr[ip] < label_bin[i_seg]) & pts_in_seg 119 | if np.sum(validpt)>5: 120 | flag = False 121 | for gp in range(len(proposals)): 122 | iou = float(np.sum(validpt & proposals[gp])) / np.sum(validpt|proposals[gp])#uniou 123 | validpt_in_gp = float(np.sum(validpt & proposals[gp])) / np.sum(validpt)#uniou 124 | if iou > 0.6 or validpt_in_gp > 0.8: 125 | flag = True 126 | if np.sum(validpt)>np.sum(proposals[gp]): 127 | proposals[gp] = validpt 128 | continue 129 | 130 | if not flag: 131 | proposals += [validpt] 132 | 133 | if len(proposals) == 0: 134 | proposals += [pts_in_seg] 135 | for gp in range(len(proposals)): 136 | if np.sum(proposals[gp])>50: 137 | groupid[proposals[gp]] = numgroups 138 | groupseg[numgroups] = i_seg 139 | numgroups += 1 140 | refineseg[proposals[gp]] = stats.mode(seg[proposals[gp]])[0] 141 | 142 | un, cnt = np.unique(groupid, return_counts=True) 143 | for ig, g in enumerate(un): 144 | if cnt[ig] < 50: 145 | groupid[groupid==g] = -1 146 | 147 | un, cnt = np.unique(groupid, return_counts=True) 148 | groupidnew = groupid.copy() 149 | for ig, g in enumerate(un): 150 | if g == -1: 151 | continue 152 | groupidnew[groupid==g] = (ig-1) 153 | groupseg[(ig-1)] = groupseg.pop(g) 154 | groupid = groupidnew 155 | 156 | for ip, gid in enumerate(groupid): 157 | if gid == -1: 158 | pts_in_gp_ind = (pts_corr[ip] < label_bin[seg[ip]]) 159 | pts_in_gp = groupid[pts_in_gp_ind] 160 | pts_in_gp_valid = pts_in_gp[pts_in_gp!=-1] 161 | if len(pts_in_gp_valid) != 0: 162 | groupid[ip] = stats.mode(pts_in_gp_valid)[0][0] 163 | 164 | return groupid, refineseg, groupseg 165 | 166 | def BlockMerging(volume, volume_seg, pts, grouplabel, groupseg, gap=1e-3): 167 | 168 | overlapgroupcounts = np.zeros([100,300]) 169 | groupcounts = np.ones(100) 170 | x=(pts[:,0]/gap).astype(np.int32) 171 | y=(pts[:,1]/gap).astype(np.int32) 172 | z=(pts[:,2]/gap).astype(np.int32) 173 | for i in range(pts.shape[0]): 174 | xx=x[i] 175 | yy=y[i] 176 | zz=z[i] 177 | if grouplabel[i] != -1: 178 | if volume[xx,yy,zz]!=-1 and volume_seg[xx,yy,zz]==groupseg[grouplabel[i]]: 179 | #overlapgroupcounts[grouplabel[i],volume[xx,yy,zz]] += 1 180 | try: 181 | overlapgroupcounts[grouplabel[i],volume[xx,yy,zz]] += 1 182 | except: 183 | pass 184 | groupcounts[grouplabel[i]] += 1 185 | 186 | groupcate = np.argmax(overlapgroupcounts,axis=1) 187 | maxoverlapgroupcounts = np.max(overlapgroupcounts,axis=1) 188 | 189 | curr_max = np.max(volume) 190 | for i in range(groupcate.shape[0]): 191 | if maxoverlapgroupcounts[i]<7 and groupcounts[i]>30: 192 | curr_max += 1 193 | groupcate[i] = curr_max 194 | 195 | 196 | finalgrouplabel = -1 * np.ones(pts.shape[0]) 197 | 198 | for i in range(pts.shape[0]): 199 | if grouplabel[i] != -1 and volume[x[i],y[i],z[i]]==-1: 200 | volume[x[i],y[i],z[i]] = groupcate[grouplabel[i]] 201 | volume_seg[x[i],y[i],z[i]] = groupseg[grouplabel[i]] 202 | finalgrouplabel[i] = groupcate[grouplabel[i]] 203 | return finalgrouplabel 204 | 205 | 206 | ############################ 207 | ## Evaluation Metrics ## 208 | ############################ 209 | 210 | def eval_3d_perclass(tp, fp, npos): 211 | 212 | tp = np.asarray(tp).astype(np.float) 213 | fp = np.asarray(fp).astype(np.float) 214 | tp = np.cumsum(tp) #?xinlongw: wrong order 215 | fp = np.cumsum(fp) 216 | rec = tp / npos 217 | prec = tp / (fp+tp) 218 | 219 | ap = 0. 220 | for t in np.arange(0, 1, 0.1): 221 | prec1 = prec[rec>=t] 222 | prec1 = prec1[~np.isnan(prec1)] 223 | if len(prec1) == 0: 224 | p = 0. 225 | else: 226 | p = max(prec1) 227 | if not p: 228 | p = 0. 229 | 230 | ap = ap + p / 10 231 | 232 | 233 | return ap, rec, prec 234 | 235 | ############################ 236 | ## Visualize Results ## 237 | ############################ 238 | 239 | color_map = json.load(open('part_color_mapping.json', 'r')) 240 | 241 | def output_bounding_box_withcorners(box_corners, seg, out_file): 242 | # ############## 0 1 2 3 4 5 6 7 243 | corner_indexes = [[0, 1, 2], [0, 1, 5], [0, 4, 2], [0, 4, 5], [3, 1, 2], [3, 1, 5], [3, 4, 2], [3, 4, 5]] 244 | line_indexes = [[0, 1], [0, 2], [0, 4], [1, 3], [1, 5], [2, 3], [2, 6], [3, 7], [4, 5], [4, 6], [5, 7], [6, 7]] 245 | with open(out_file, 'w') as f: 246 | l = box_corners.shape[0] 247 | for i in range(l): 248 | box = box_corners[i] 249 | color = color_map[seg[i]] 250 | for line_index in line_indexes: 251 | corner0 = box[line_index[0]] 252 | corner1 = box[line_index[1]] 253 | print corner0.shape 254 | dist = np.linalg.norm(corner0 - corner1) 255 | dot_num = int(dist / 0.005) 256 | delta = (corner1 - corner0) / dot_num 257 | for idot in range(dot_num): 258 | plotdot = corner0 + idot * delta 259 | f.write( 260 | 'v %f %f %f %f %f %f\n' % (plotdot[0], plotdot[1], plotdot[2], color[0], color[1], color[2])) 261 | 262 | 263 | def output_bounding_box(boxes, seg, out_file): 264 | # ############## 0 1 2 3 4 5 6 7 265 | #box:nx8x3 266 | corner_indexes = [[0, 1, 2], [0, 1, 5], [0, 4, 2], [0, 4, 5], [3, 1, 2], [3, 1, 5], [3, 4, 2], [3, 4, 5]] 267 | line_indexes = [[0, 1], [0, 2], [0, 4], [1, 3], [1, 5], [2, 3], [2, 6], [3, 7], [4, 5], [4, 6], [5, 7], [6, 7]] 268 | with open(out_file, 'w') as f: 269 | l = boxes.shape[0] 270 | for i in range(l): 271 | box = boxes[i] 272 | color = color_map[seg[i]] 273 | for line_index in line_indexes: 274 | corner0 = box[corner_indexes[line_index[0]]] 275 | corner1 = box[corner_indexes[line_index[1]]] 276 | dist = np.linalg.norm(corner0 - corner1) 277 | dot_num = int(dist / 0.005) 278 | delta = (corner1 - corner0) / dot_num 279 | for idot in range(dot_num): 280 | plotdot = corner0 + idot * delta 281 | f.write( 282 | 'v %f %f %f %f %f %f\n' % (plotdot[0], plotdot[1], plotdot[2], color[0], color[1], color[2])) 283 | 284 | 285 | def output_color_point_cloud(data, seg, out_file): 286 | with open(out_file, 'w') as f: 287 | l = len(seg) 288 | for i in range(l): 289 | color = color_map[seg[i]] 290 | f.write('v %f %f %f %f %f %f\n' % (data[i][0], data[i][1], data[i][2], color[0], color[1], color[2])) 291 | 292 | 293 | def output_point_cloud_rgb(data, rgb, out_file): 294 | with open(out_file, 'w') as f: 295 | l = len(data) 296 | for i in range(l): 297 | f.write('v %f %f %f %f %f %f\n' % (data[i][0], data[i][1], data[i][2], rgb[i][0], rgb[i][1], rgb[i][2])) 298 | 299 | 300 | def output_color_point_cloud_red_blue(data, seg, out_file): 301 | with open(out_file, 'w') as f: 302 | l = len(seg) 303 | for i in range(l): 304 | if seg[i] == 1: 305 | color = [0, 0, 1] 306 | elif seg[i] == 0: 307 | color = [1, 0, 0] 308 | else: 309 | color = [0, 0, 0] 310 | f.write('v %f %f %f %f %f %f\n' % (data[i][0], data[i][1], data[i][2], color[0], color[1], color[2])) 311 | 312 | import matplotlib.cm as cm 313 | ##define color heat map 314 | norm = mpl.colors.Normalize(vmin=0, vmax=255) 315 | magma_cmap = cm.get_cmap('magma') 316 | magma_rgb = [] 317 | for i in range(0, 255): 318 | k = mpl.colors.colorConverter.to_rgb(magma_cmap(norm(i))) 319 | magma_rgb.append(k) 320 | 321 | 322 | def output_scale_point_cloud(data, scales, out_file): 323 | with open(out_file, 'w') as f: 324 | l = len(scales) 325 | for i in range(l): 326 | scale = int(scales[i]*254) 327 | if scale > 254: 328 | scale = 254 329 | color = magma_rgb[scale] 330 | f.write('v %f %f %f %f %f %f\n' % (data[i][0], data[i][1], data[i][2], color[0], color[1], color[2])) 331 | 332 | --------------------------------------------------------------------------------