├── README.md ├── config └── spnet.yaml ├── dataset ├── s3dis │ └── s3dis_names.txt ├── scannet │ └── scannet_names.txt └── vkitti │ └── vkitti_names.txt ├── exp └── s3dis │ └── 20220121 │ └── saved_model │ └── train_epoch_850.pth ├── lib ├── __init__.py ├── ply_c │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.10.2 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── a.out │ │ │ └── CompilerIdCXX │ │ │ │ ├── CMakeCXXCompilerId.cpp │ │ │ │ └── a.out │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── CMakeOutput.log │ │ ├── Makefile.cmake │ │ ├── Makefile2 │ │ ├── TargetDirectories.txt │ │ ├── cmake.check_cache │ │ ├── feature_tests.bin │ │ ├── feature_tests.c │ │ ├── feature_tests.cxx │ │ ├── ply_c.dir │ │ │ ├── CXX.includecache │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── depend.internal │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ ├── ply_c.cpp.o │ │ │ └── progress.make │ │ └── progress.marks │ ├── CMakeLists.txt │ ├── Makefile │ ├── cmake_install.cmake │ ├── connected_components.cpp │ ├── libply_c.so │ ├── ply_c.cpp │ └── random_subgraph.cpp ├── pointops │ ├── __init__.py │ ├── functions │ │ ├── __init__.py │ │ └── pointops.py │ ├── setup.py │ └── src │ │ ├── __init__.py │ │ ├── assofixp2c │ │ ├── __init__.py │ │ ├── assofixp2c_cuda.cpp │ │ ├── assofixp2c_cuda_kernel.cu │ │ └── assofixp2c_cuda_kernel.h │ │ ├── assofixp2c_weight │ │ ├── __init__.py │ │ ├── assofixp2c_weight_cuda.cpp │ │ ├── assofixp2c_weight_cuda_kernel.cu │ │ └── assofixp2c_weight_cuda_kernel.h │ │ ├── assomatrix │ │ ├── __init__.py │ │ ├── assomatrix_cuda.cpp │ │ ├── assomatrix_cuda_kernel.cu │ │ └── assomatrix_cuda_kernel.h │ │ ├── assomatrix_float │ │ ├── __init__.py │ │ ├── assomatrix_float_cuda.cpp │ │ ├── assomatrix_float_cuda_kernel.cu │ │ └── assomatrix_float_cuda_kernel.h │ │ ├── assomatrix_label │ │ ├── __init__.py │ │ ├── assomatrix_label_cuda.cpp │ │ ├── assomatrix_label_cuda_kernel.cu │ │ └── assomatrix_label_cuda_kernel.h │ │ ├── ballquery │ │ ├── ballquery_cuda.cpp │ │ ├── ballquery_cuda_kernel.cu │ │ └── ballquery_cuda_kernel.h │ │ ├── cuda_utils.h │ │ ├── featuredistribute │ │ ├── featuredistribute_cuda.cpp │ │ ├── featuredistribute_cuda_kernel.cu │ │ └── featuredistribute_cuda_kernel.h │ │ ├── grouping │ │ ├── grouping_cuda.cpp │ │ ├── grouping_cuda_kernel.cu │ │ └── grouping_cuda_kernel.h │ │ ├── grouping_int │ │ ├── grouping_int_cuda.cpp │ │ ├── grouping_int_cuda_kernel.cu │ │ └── grouping_int_cuda_kernel.h │ │ ├── interpolation │ │ ├── interpolation_cuda.cpp │ │ ├── interpolation_cuda_kernel.cu │ │ └── interpolation_cuda_kernel.h │ │ ├── knnquery │ │ ├── __init__.py │ │ ├── knnquery_cuda.cpp │ │ ├── knnquery_cuda_kernel.cu │ │ └── knnquery_cuda_kernel.h │ │ ├── knnquerycluster │ │ ├── __init__.py │ │ ├── knnquerycluster_cuda.cpp │ │ ├── knnquerycluster_cuda_kernel.cu │ │ └── knnquerycluster_cuda_kernel.h │ │ ├── knnqueryclustergt │ │ ├── __init__.py │ │ ├── knnqueryclustergt_cuda.cpp │ │ ├── knnqueryclustergt_cuda_kernel.cu │ │ └── knnqueryclustergt_cuda_kernel.h │ │ ├── knnquerydilate │ │ ├── __init__.py │ │ ├── knnquerydilate_cuda.cpp │ │ ├── knnquerydilate_cuda_kernel.cu │ │ └── knnquerydilate_cuda_kernel.h │ │ ├── knnquerypoint │ │ ├── __init__.py │ │ ├── knnquerypoint_cuda.cpp │ │ ├── knnquerypoint_cuda_kernel.cu │ │ └── knnquerypoint_cuda_kernel.h │ │ ├── labelstat │ │ ├── labelstat_cuda.cpp │ │ ├── labelstat_cuda_kernel.cu │ │ └── labelstat_cuda_kernel.h │ │ ├── pointops_api.cpp │ │ └── sampling │ │ ├── sampling_cuda.cpp │ │ ├── sampling_cuda_kernel.cu │ │ └── sampling_cuda_kernel.h └── sync_bn │ ├── __init__.py │ ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── batchnorm.cpython-36.pyc │ ├── comm.cpython-36.pyc │ └── replicate.cpython-36.pyc │ ├── batchnorm.py │ ├── comm.py │ ├── replicate.py │ └── unittest.py ├── model ├── modules.py └── network.py ├── tool ├── sh_test.sh ├── sh_train.sh ├── test.py └── train.py └── util ├── S3DIS_dataset.py ├── SCANNET_dataset.py ├── SCANNET_dataset_v1.py ├── SEMANTICPOSS_dataset.py ├── VKITTI_dataset.py ├── __init__.py ├── compute_spg ├── calc_sp_metrics.py ├── calc_sp_metrics_v1.py ├── get_metric.py ├── log_reg0.8 └── metrics.py ├── config.py ├── dataset.py ├── graphs.py ├── losses.py ├── metrics.py ├── provider.py ├── pt_util.py ├── s3dis.py ├── transform.py └── util.py /README.md: -------------------------------------------------------------------------------- 1 | ## Superpoint Network for Point Cloud Oversegmentation 2 | 3 | by Le Hui, Jia Yuan, Mingmei Cheng, Jin Xie, Xiaoya Zhang, and Jian Yang 4 | 5 | 6 | 7 | ##### This is a rough README.md, and we'll work through it. !!! 8 | 9 | 10 | 11 | ### Project Code 12 | 13 | #### Requirements 14 | 15 | * basic environment 16 | ``` 17 | Python 3.6.6 18 | Pytorch 1.4.0 19 | CUDA 10.1 20 | ``` 21 | 22 | * compile the "libply_c" library (Please refer to [SPG](https://github.com/loicland/superpoint_graph)) 23 | 24 | ``` 25 | CONDAENV=YOUR_CONDA_ENVIRONMENT_LOCATION 26 | cd libs/ply_c 27 | cmake . -DPYTHON_LIBRARY=$CONDAENV/lib/libpython3.6m.so -DPYTHON_INCLUDE_DIR=$CONDAENV/include/python3.6m -DBOOST_INCLUDEDIR=$CONDAENV/include -DEIGEN3_INCLUDE_DIR=$CONDAENV/include/eigen3 28 | make 29 | cd ../../ 30 | ``` 31 | 32 | * build the ops 33 | 34 | ``` 35 | cd libs/pointops && python setup.py install && cd ../../ 36 | 37 | Note that this may take a long time. 38 | ``` 39 | 40 | 41 | #### Training and Evaluation 42 | 43 | * To train and evaluate SPNet, run the following command: 44 | 45 | ``` 46 | # Train & Eval 47 | # Note that you should change the paths in the yaml file. 48 | 49 | sh tool/sh_train.sh s3dis 20220121 config/spnet.yaml 50 | 51 | sh tool/sh_test.sh s3dis 20220121 config/spnet.yaml 850 52 | ``` 53 | 54 | 55 | #### Citation 56 | 57 | If you find the code or trained models useful, please consider citing: 58 | 59 | ``` 60 | @inproceedings{hui2021spnet, 61 | title={Superpoint Network for Point Cloud Oversegmentation}, 62 | author={Hui, Le and Yuan, Jia and Cheng, Mingmei and Xie, Jin and Yang, Jian}, 63 | booktitle={ICCV}, 64 | year={2021} 65 | } 66 | 67 | ``` 68 | 69 | #### Acknowledgement 70 | 71 | Our code refers to [SPG](https://github.com/loicland/superpoint_graph) and [PointWeb](https://github.com/hszhao/PointWeb). Many thanks to SPG for a great work. -------------------------------------------------------------------------------- /config/spnet.yaml: -------------------------------------------------------------------------------- 1 | # --------------CONFIG FILE----------------------- 2 | 3 | 4 | 5 | #------GPU setting ------------------------------- 6 | for_debug: False 7 | train_gpu: 8 | - 0 9 | test_gpu: 10 | - 0 11 | 12 | # ------------random seed ------------------------- 13 | manual_seed: 123 14 | sync_bn: False 15 | 16 | # ------------dataset setting---------------------- 17 | data_name: 's3dis' 18 | classes: 13 # 13 cateogries for S3DIS (13 labeled) 19 | data_root: "/test/dataset/3d_datasets/features_supervision/" 20 | names_path: "/test/work2020/superpoints/spnet/dataset/s3dis/s3dis_names.txt" 21 | 22 | num_point: 14999 # actually 14999+1=15000 23 | # very important!!!! 24 | # rate: 0.008 # 0.008 for training and 0.0069 for testing 25 | rate: 0.0069 26 | 27 | minpoints: 15000 28 | test_area: 5 29 | block_size: 3.0 # 1.5m 30 | sample_rate: 1.0 31 | stride_rate: 1.0 32 | fea_dim: 7 # feature dimension 33 | use_xyz: True 34 | 35 | global_feat: 'eXYrgb' 36 | ver_value: 'ptn' 37 | learned_embeddings: True 38 | pc_augm_rot: 1 39 | pc_augm_jitter: 1 40 | 41 | use_softmax: True 42 | use_norm: False 43 | 44 | use_rgb: True # whether to use RGB information, SemanticKITTI has no RGB, but remission 45 | nsample: 30 # knn 46 | 47 | near_clusters2point: 6 48 | near_points2cluster: 50 49 | 50 | k_nn_adj: 5 51 | k_nn_local: 20 52 | BR_tolerance: 1 53 | 54 | # -------------network setting--------------------- 55 | arch: 'model.network' # network architecture 56 | 57 | dropout: 0.3 58 | 59 | train_batch_size: 4 60 | test_batch_size: 1 61 | ignore_label: 255 62 | 63 | epochs: 5000 64 | start_epoch: 0 65 | 66 | train_workers: 8 67 | save_freq: 1 # save frequence 68 | print_freq: 1 # print frequence 69 | metric_freq: 1 70 | 71 | base_lr: 0.001 # sgd base_lr 72 | momentum: 0.9 # momentum 73 | weight_decay: 0.0001 # weight_decay 74 | 75 | re_xyz_loss: 'mse' 76 | re_label_loss: 'cel' 77 | re_sp_loss: 'cel' 78 | use_semantic_loss: 0 # 0: not use 1: seg 2: seal 79 | 80 | w_re_xyz_loss: 0.0001 81 | w_re_label_loss: 1.0 82 | w_re_sp_loss: 1.0 83 | w_semantic_loss: 0.0 84 | 85 | opts: 'adam' # optimizer: sgd or adam 86 | gamma: 0.5 87 | T_max: 10 88 | 89 | step_epoch: 25 # decay learning rate per/epoch 90 | 91 | multiplier: 0.1 # multiplier 92 | 93 | # ------------------evaluation---------------------------- 94 | evaluate: False # evaluate 95 | 96 | -------------------------------------------------------------------------------- /dataset/s3dis/s3dis_names.txt: -------------------------------------------------------------------------------- 1 | ceiling 2 | floor 3 | wall 4 | beam 5 | column 6 | window 7 | door 8 | chair 9 | table 10 | bookcase 11 | sofa 12 | board 13 | clutter 14 | -------------------------------------------------------------------------------- /dataset/scannet/scannet_names.txt: -------------------------------------------------------------------------------- 1 | bathtub 2 | bed 3 | bookshelf 4 | cabinet 5 | chair 6 | counter 7 | curtain 8 | desk 9 | door 10 | floor 11 | otherfurniture 12 | picture 13 | refrigerator 14 | showercurtain 15 | sink 16 | sofa 17 | table 18 | toilet 19 | wall 20 | window 21 | -------------------------------------------------------------------------------- /dataset/vkitti/vkitti_names.txt: -------------------------------------------------------------------------------- 1 | Terrain 2 | Tree 3 | Vegetation 4 | Building 5 | Road 6 | GuardRail 7 | TrafficSign 8 | TrafficLight 9 | Pole 10 | Misc 11 | Truck 12 | Car 13 | Van 14 | -------------------------------------------------------------------------------- /exp/s3dis/20220121/saved_model/train_epoch_850.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/exp/s3dis/20220121/saved_model/train_epoch_850.pth -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/__init__.py -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/3.10.2/CMakeCCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER "/usr/bin/cc") 2 | set(CMAKE_C_COMPILER_ARG1 "") 3 | set(CMAKE_C_COMPILER_ID "GNU") 4 | set(CMAKE_C_COMPILER_VERSION "7.5.0") 5 | set(CMAKE_C_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_C_COMPILER_WRAPPER "") 7 | set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") 8 | set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert") 9 | set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") 10 | set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") 11 | set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") 12 | 13 | set(CMAKE_C_PLATFORM_ID "Linux") 14 | set(CMAKE_C_SIMULATE_ID "") 15 | set(CMAKE_C_SIMULATE_VERSION "") 16 | 17 | 18 | 19 | set(CMAKE_AR "/usr/bin/ar") 20 | set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-7") 21 | set(CMAKE_RANLIB "/usr/bin/ranlib") 22 | set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-7") 23 | set(CMAKE_LINKER "/usr/bin/ld") 24 | set(CMAKE_COMPILER_IS_GNUCC 1) 25 | set(CMAKE_C_COMPILER_LOADED 1) 26 | set(CMAKE_C_COMPILER_WORKS TRUE) 27 | set(CMAKE_C_ABI_COMPILED TRUE) 28 | set(CMAKE_COMPILER_IS_MINGW ) 29 | set(CMAKE_COMPILER_IS_CYGWIN ) 30 | if(CMAKE_COMPILER_IS_CYGWIN) 31 | set(CYGWIN 1) 32 | set(UNIX 1) 33 | endif() 34 | 35 | set(CMAKE_C_COMPILER_ENV_VAR "CC") 36 | 37 | if(CMAKE_COMPILER_IS_MINGW) 38 | set(MINGW 1) 39 | endif() 40 | set(CMAKE_C_COMPILER_ID_RUN 1) 41 | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) 42 | set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) 43 | set(CMAKE_C_LINKER_PREFERENCE 10) 44 | 45 | # Save compiler ABI information. 46 | set(CMAKE_C_SIZEOF_DATA_PTR "8") 47 | set(CMAKE_C_COMPILER_ABI "ELF") 48 | set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 49 | 50 | if(CMAKE_C_SIZEOF_DATA_PTR) 51 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") 52 | endif() 53 | 54 | if(CMAKE_C_COMPILER_ABI) 55 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") 56 | endif() 57 | 58 | if(CMAKE_C_LIBRARY_ARCHITECTURE) 59 | set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 60 | endif() 61 | 62 | set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") 63 | if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) 64 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") 65 | endif() 66 | 67 | 68 | 69 | 70 | 71 | set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") 72 | set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib;/usr/local/cuda/lib64/stubs") 73 | set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") 74 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/3.10.2/CMakeCXXCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_COMPILER "/usr/bin/c++") 2 | set(CMAKE_CXX_COMPILER_ARG1 "") 3 | set(CMAKE_CXX_COMPILER_ID "GNU") 4 | set(CMAKE_CXX_COMPILER_VERSION "7.5.0") 5 | set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_CXX_COMPILER_WRAPPER "") 7 | set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") 8 | set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17") 9 | set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") 10 | set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") 11 | set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") 12 | set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") 13 | 14 | set(CMAKE_CXX_PLATFORM_ID "Linux") 15 | set(CMAKE_CXX_SIMULATE_ID "") 16 | set(CMAKE_CXX_SIMULATE_VERSION "") 17 | 18 | 19 | 20 | set(CMAKE_AR "/usr/bin/ar") 21 | set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-7") 22 | set(CMAKE_RANLIB "/usr/bin/ranlib") 23 | set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-7") 24 | set(CMAKE_LINKER "/usr/bin/ld") 25 | set(CMAKE_COMPILER_IS_GNUCXX 1) 26 | set(CMAKE_CXX_COMPILER_LOADED 1) 27 | set(CMAKE_CXX_COMPILER_WORKS TRUE) 28 | set(CMAKE_CXX_ABI_COMPILED TRUE) 29 | set(CMAKE_COMPILER_IS_MINGW ) 30 | set(CMAKE_COMPILER_IS_CYGWIN ) 31 | if(CMAKE_COMPILER_IS_CYGWIN) 32 | set(CYGWIN 1) 33 | set(UNIX 1) 34 | endif() 35 | 36 | set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") 37 | 38 | if(CMAKE_COMPILER_IS_MINGW) 39 | set(MINGW 1) 40 | endif() 41 | set(CMAKE_CXX_COMPILER_ID_RUN 1) 42 | set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) 43 | set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP) 44 | set(CMAKE_CXX_LINKER_PREFERENCE 30) 45 | set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) 46 | 47 | # Save compiler ABI information. 48 | set(CMAKE_CXX_SIZEOF_DATA_PTR "8") 49 | set(CMAKE_CXX_COMPILER_ABI "ELF") 50 | set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 51 | 52 | if(CMAKE_CXX_SIZEOF_DATA_PTR) 53 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") 54 | endif() 55 | 56 | if(CMAKE_CXX_COMPILER_ABI) 57 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") 58 | endif() 59 | 60 | if(CMAKE_CXX_LIBRARY_ARCHITECTURE) 61 | set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 62 | endif() 63 | 64 | set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") 65 | if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) 66 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") 67 | endif() 68 | 69 | 70 | 71 | 72 | 73 | set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") 74 | set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib;/usr/local/cuda/lib64/stubs") 75 | set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") 76 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_C.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/ply_c/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_C.bin -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_CXX.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/ply_c/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_CXX.bin -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/3.10.2/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Linux-4.4.0-190-generic") 2 | set(CMAKE_HOST_SYSTEM_NAME "Linux") 3 | set(CMAKE_HOST_SYSTEM_VERSION "4.4.0-190-generic") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Linux-4.4.0-190-generic") 9 | set(CMAKE_SYSTEM_NAME "Linux") 10 | set(CMAKE_SYSTEM_VERSION "4.4.0-190-generic") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/3.10.2/CompilerIdC/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/ply_c/CMakeFiles/3.10.2/CompilerIdC/a.out -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/3.10.2/CompilerIdCXX/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/ply_c/CMakeFiles/3.10.2/CompilerIdCXX/a.out -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/CMakeDirectoryInformation.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10 3 | 4 | # Relative path conversion top directories. 5 | set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/test/work2020/superpoints/spnet/lib/ply_c") 6 | set(CMAKE_RELATIVE_PATH_TOP_BINARY "/test/work2020/superpoints/spnet/lib/ply_c") 7 | 8 | # Force unix paths in dependencies. 9 | set(CMAKE_FORCE_UNIX_PATHS 1) 10 | 11 | 12 | # The C and CXX include file regular expressions for this directory. 13 | set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") 14 | set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") 15 | set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) 16 | set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) 17 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/Makefile2: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10 3 | 4 | # Default target executed when no arguments are given to make. 5 | default_target: all 6 | 7 | .PHONY : default_target 8 | 9 | # The main recursive all target 10 | all: 11 | 12 | .PHONY : all 13 | 14 | # The main recursive preinstall target 15 | preinstall: 16 | 17 | .PHONY : preinstall 18 | 19 | #============================================================================= 20 | # Special targets provided by cmake. 21 | 22 | # Disable implicit rules so canonical targets will work. 23 | .SUFFIXES: 24 | 25 | 26 | # Remove some rules from gmake that .SUFFIXES does not remove. 27 | SUFFIXES = 28 | 29 | .SUFFIXES: .hpux_make_needs_suffix_list 30 | 31 | 32 | # Suppress display of executed commands. 33 | $(VERBOSE).SILENT: 34 | 35 | 36 | # A target that is always out of date. 37 | cmake_force: 38 | 39 | .PHONY : cmake_force 40 | 41 | #============================================================================= 42 | # Set environment variables for the build. 43 | 44 | # The shell in which to execute make rules. 45 | SHELL = /bin/sh 46 | 47 | # The CMake executable. 48 | CMAKE_COMMAND = /usr/bin/cmake 49 | 50 | # The command to remove a file. 51 | RM = /usr/bin/cmake -E remove -f 52 | 53 | # Escaping for special characters. 54 | EQUALS = = 55 | 56 | # The top-level source directory on which CMake was run. 57 | CMAKE_SOURCE_DIR = /test/work2020/superpoints/spnet/lib/ply_c 58 | 59 | # The top-level build directory on which CMake was run. 60 | CMAKE_BINARY_DIR = /test/work2020/superpoints/spnet/lib/ply_c 61 | 62 | #============================================================================= 63 | # Target rules for target CMakeFiles/ply_c.dir 64 | 65 | # All Build rule for target. 66 | CMakeFiles/ply_c.dir/all: 67 | $(MAKE) -f CMakeFiles/ply_c.dir/build.make CMakeFiles/ply_c.dir/depend 68 | $(MAKE) -f CMakeFiles/ply_c.dir/build.make CMakeFiles/ply_c.dir/build 69 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles --progress-num=1,2 "Built target ply_c" 70 | .PHONY : CMakeFiles/ply_c.dir/all 71 | 72 | # Include target in all. 73 | all: CMakeFiles/ply_c.dir/all 74 | 75 | .PHONY : all 76 | 77 | # Build rule for subdir invocation for target. 78 | CMakeFiles/ply_c.dir/rule: cmake_check_build_system 79 | $(CMAKE_COMMAND) -E cmake_progress_start /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles 2 80 | $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/ply_c.dir/all 81 | $(CMAKE_COMMAND) -E cmake_progress_start /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles 0 82 | .PHONY : CMakeFiles/ply_c.dir/rule 83 | 84 | # Convenience name for target. 85 | ply_c: CMakeFiles/ply_c.dir/rule 86 | 87 | .PHONY : ply_c 88 | 89 | # clean rule for target. 90 | CMakeFiles/ply_c.dir/clean: 91 | $(MAKE) -f CMakeFiles/ply_c.dir/build.make CMakeFiles/ply_c.dir/clean 92 | .PHONY : CMakeFiles/ply_c.dir/clean 93 | 94 | # clean rule for target. 95 | clean: CMakeFiles/ply_c.dir/clean 96 | 97 | .PHONY : clean 98 | 99 | #============================================================================= 100 | # Special targets to cleanup operation of make. 101 | 102 | # Special rule to run CMake to check the build system integrity. 103 | # No rule that depends on this can have commands that come from listfiles 104 | # because they might be regenerated. 105 | cmake_check_build_system: 106 | $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 107 | .PHONY : cmake_check_build_system 108 | 109 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/TargetDirectories.txt: -------------------------------------------------------------------------------- 1 | /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles/rebuild_cache.dir 2 | /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles/ply_c.dir 3 | /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles/edit_cache.dir 4 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/cmake.check_cache: -------------------------------------------------------------------------------- 1 | # This file is generated by cmake for dependency checking of the CMakeCache.txt file 2 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/feature_tests.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/ply_c/CMakeFiles/feature_tests.bin -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/feature_tests.c: -------------------------------------------------------------------------------- 1 | 2 | const char features[] = {"\n" 3 | "C_FEATURE:" 4 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 5 | "1" 6 | #else 7 | "0" 8 | #endif 9 | "c_function_prototypes\n" 10 | "C_FEATURE:" 11 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 12 | "1" 13 | #else 14 | "0" 15 | #endif 16 | "c_restrict\n" 17 | "C_FEATURE:" 18 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L 19 | "1" 20 | #else 21 | "0" 22 | #endif 23 | "c_static_assert\n" 24 | "C_FEATURE:" 25 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 26 | "1" 27 | #else 28 | "0" 29 | #endif 30 | "c_variadic_macros\n" 31 | 32 | }; 33 | 34 | int main(int argc, char** argv) { (void)argv; return features[argc]; } 35 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/ply_c.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "CXX" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_CXX 7 | "/test/work2020/superpoints/spnet/lib/ply_c/ply_c.cpp" "/test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles/ply_c.dir/ply_c.cpp.o" 8 | ) 9 | set(CMAKE_CXX_COMPILER_ID "GNU") 10 | 11 | # Preprocessor definitions for this target. 12 | set(CMAKE_TARGET_DEFINITIONS_CXX 13 | "BOOST_ALL_NO_LIB" 14 | "BOOST_NUMPY_DYN_LINK" 15 | "BOOST_PYTHON_DYN_LINK" 16 | ) 17 | 18 | # The include file search paths: 19 | set(CMAKE_CXX_TARGET_INCLUDE_PATH 20 | "/root/anaconda3/include" 21 | "/root/anaconda3/include/eigen3" 22 | "/root/anaconda3/include/python3.6m" 23 | ) 24 | 25 | # Targets to which this target links. 26 | set(CMAKE_TARGET_LINKED_INFO_FILES 27 | ) 28 | 29 | # Fortran module output directory. 30 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 31 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/ply_c.dir/build.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10 3 | 4 | # Delete rule output on recipe failure. 5 | .DELETE_ON_ERROR: 6 | 7 | 8 | #============================================================================= 9 | # Special targets provided by cmake. 10 | 11 | # Disable implicit rules so canonical targets will work. 12 | .SUFFIXES: 13 | 14 | 15 | # Remove some rules from gmake that .SUFFIXES does not remove. 16 | SUFFIXES = 17 | 18 | .SUFFIXES: .hpux_make_needs_suffix_list 19 | 20 | 21 | # Suppress display of executed commands. 22 | $(VERBOSE).SILENT: 23 | 24 | 25 | # A target that is always out of date. 26 | cmake_force: 27 | 28 | .PHONY : cmake_force 29 | 30 | #============================================================================= 31 | # Set environment variables for the build. 32 | 33 | # The shell in which to execute make rules. 34 | SHELL = /bin/sh 35 | 36 | # The CMake executable. 37 | CMAKE_COMMAND = /usr/bin/cmake 38 | 39 | # The command to remove a file. 40 | RM = /usr/bin/cmake -E remove -f 41 | 42 | # Escaping for special characters. 43 | EQUALS = = 44 | 45 | # The top-level source directory on which CMake was run. 46 | CMAKE_SOURCE_DIR = /test/work2020/superpoints/spnet/lib/ply_c 47 | 48 | # The top-level build directory on which CMake was run. 49 | CMAKE_BINARY_DIR = /test/work2020/superpoints/spnet/lib/ply_c 50 | 51 | # Include any dependencies generated for this target. 52 | include CMakeFiles/ply_c.dir/depend.make 53 | 54 | # Include the progress variables for this target. 55 | include CMakeFiles/ply_c.dir/progress.make 56 | 57 | # Include the compile flags for this target's objects. 58 | include CMakeFiles/ply_c.dir/flags.make 59 | 60 | CMakeFiles/ply_c.dir/ply_c.cpp.o: CMakeFiles/ply_c.dir/flags.make 61 | CMakeFiles/ply_c.dir/ply_c.cpp.o: ply_c.cpp 62 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/ply_c.dir/ply_c.cpp.o" 63 | /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/ply_c.dir/ply_c.cpp.o -c /test/work2020/superpoints/spnet/lib/ply_c/ply_c.cpp 64 | 65 | CMakeFiles/ply_c.dir/ply_c.cpp.i: cmake_force 66 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/ply_c.dir/ply_c.cpp.i" 67 | /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /test/work2020/superpoints/spnet/lib/ply_c/ply_c.cpp > CMakeFiles/ply_c.dir/ply_c.cpp.i 68 | 69 | CMakeFiles/ply_c.dir/ply_c.cpp.s: cmake_force 70 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/ply_c.dir/ply_c.cpp.s" 71 | /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /test/work2020/superpoints/spnet/lib/ply_c/ply_c.cpp -o CMakeFiles/ply_c.dir/ply_c.cpp.s 72 | 73 | CMakeFiles/ply_c.dir/ply_c.cpp.o.requires: 74 | 75 | .PHONY : CMakeFiles/ply_c.dir/ply_c.cpp.o.requires 76 | 77 | CMakeFiles/ply_c.dir/ply_c.cpp.o.provides: CMakeFiles/ply_c.dir/ply_c.cpp.o.requires 78 | $(MAKE) -f CMakeFiles/ply_c.dir/build.make CMakeFiles/ply_c.dir/ply_c.cpp.o.provides.build 79 | .PHONY : CMakeFiles/ply_c.dir/ply_c.cpp.o.provides 80 | 81 | CMakeFiles/ply_c.dir/ply_c.cpp.o.provides.build: CMakeFiles/ply_c.dir/ply_c.cpp.o 82 | 83 | 84 | # Object files for target ply_c 85 | ply_c_OBJECTS = \ 86 | "CMakeFiles/ply_c.dir/ply_c.cpp.o" 87 | 88 | # External object files for target ply_c 89 | ply_c_EXTERNAL_OBJECTS = 90 | 91 | libply_c.so: CMakeFiles/ply_c.dir/ply_c.cpp.o 92 | libply_c.so: CMakeFiles/ply_c.dir/build.make 93 | libply_c.so: /root/anaconda3/lib/libboost_python36.so.1.71.0 94 | libply_c.so: /root/anaconda3/lib/libboost_numpy36.so.1.71.0 95 | libply_c.so: /root/anaconda3/lib/libpython3.6m.so 96 | libply_c.so: /root/anaconda3/lib/libboost_python36.so.1.71.0 97 | libply_c.so: CMakeFiles/ply_c.dir/link.txt 98 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking CXX shared library libply_c.so" 99 | $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/ply_c.dir/link.txt --verbose=$(VERBOSE) 100 | 101 | # Rule to build all files generated by this target. 102 | CMakeFiles/ply_c.dir/build: libply_c.so 103 | 104 | .PHONY : CMakeFiles/ply_c.dir/build 105 | 106 | CMakeFiles/ply_c.dir/requires: CMakeFiles/ply_c.dir/ply_c.cpp.o.requires 107 | 108 | .PHONY : CMakeFiles/ply_c.dir/requires 109 | 110 | CMakeFiles/ply_c.dir/clean: 111 | $(CMAKE_COMMAND) -P CMakeFiles/ply_c.dir/cmake_clean.cmake 112 | .PHONY : CMakeFiles/ply_c.dir/clean 113 | 114 | CMakeFiles/ply_c.dir/depend: 115 | cd /test/work2020/superpoints/spnet/lib/ply_c && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /test/work2020/superpoints/spnet/lib/ply_c /test/work2020/superpoints/spnet/lib/ply_c /test/work2020/superpoints/spnet/lib/ply_c /test/work2020/superpoints/spnet/lib/ply_c /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles/ply_c.dir/DependInfo.cmake --color=$(COLOR) 116 | .PHONY : CMakeFiles/ply_c.dir/depend 117 | 118 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/ply_c.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/ply_c.dir/ply_c.cpp.o" 3 | "libply_c.pdb" 4 | "libply_c.so" 5 | ) 6 | 7 | # Per-language clean rules from dependency scanning. 8 | foreach(lang CXX) 9 | include(CMakeFiles/ply_c.dir/cmake_clean_${lang}.cmake OPTIONAL) 10 | endforeach() 11 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/ply_c.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10 3 | 4 | # compile CXX with /usr/bin/c++ 5 | CXX_FLAGS = -Wall -std=c++11 -fopenmp -O3 -fPIC 6 | 7 | CXX_DEFINES = -DBOOST_ALL_NO_LIB -DBOOST_NUMPY_DYN_LINK -DBOOST_PYTHON_DYN_LINK -Dply_c_EXPORTS 8 | 9 | CXX_INCLUDES = -isystem /root/anaconda3/include -I/root/anaconda3/include/eigen3 -I/root/anaconda3/include/python3.6m 10 | 11 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/ply_c.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/c++ -fPIC -Wall -std=c++11 -fopenmp -O3 -shared -Wl,-soname,libply_c.so -o libply_c.so CMakeFiles/ply_c.dir/ply_c.cpp.o -Wl,-rpath,/root/anaconda3/lib /root/anaconda3/lib/libboost_python36.so.1.71.0 /root/anaconda3/lib/libboost_numpy36.so.1.71.0 /root/anaconda3/lib/libpython3.6m.so /root/anaconda3/lib/libboost_python36.so.1.71.0 2 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/ply_c.dir/ply_c.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/ply_c/CMakeFiles/ply_c.dir/ply_c.cpp.o -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/ply_c.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 1 2 | CMAKE_PROGRESS_2 = 2 3 | 4 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeFiles/progress.marks: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /lib/ply_c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Graph for Cut Pursuit 2 | # author: Loic Landrieu 3 | # date: 2017 4 | 5 | CMAKE_MINIMUM_REQUIRED(VERSION 3.5) 6 | 7 | PROJECT(LIBGEOF) 8 | 9 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -fopenmp -O3") 10 | 11 | 12 | ############################## 13 | ### Find required packages ### 14 | ############################## 15 | 16 | find_package(Boost 1.65.1 COMPONENTS python numpy REQUIRED) 17 | 18 | include_directories(${Boost_INCLUDE_DIRS}) 19 | link_directories(${Boost_LIBRARY_DIRS}) 20 | 21 | message("Boost includes ARE " ${Boost_INCLUDE_DIRS}) 22 | message("Boost LIBRARIES ARE " ${Boost_LIBRARY_DIRS}) 23 | 24 | #find_package(Eigen3 REQUIRED NO_MODULE) 25 | INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR}) 26 | #LINK_DIRECTORIES(${EIGEN3_LIBRARY_DIRS}) 27 | 28 | 29 | #SET(PYTHON_LIBRARIES /root/anaconda3/envs/Pytorch_1.0.0/lib/libpython3.6m.so) 30 | #SET(PYTHON_INCLUDE_DIRS /root/anaconda3/envs/Pytorch_1.0.0/lib/python3.6/site-packages/) 31 | find_package(PythonLibs) 32 | message("PYTHON LIBRARIES ARE " ${PYTHON_LIBRARIES}) 33 | INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS}) 34 | LINK_DIRECTORIES(${PYTHON_LIBRARY_DIRS}) 35 | ############################## 36 | ### Build target library ### 37 | ############################## 38 | 39 | set(CMAKE_LD_FLAG "${CMAKE_LD_FLAGS} -shared -Wl -fPIC --export-dynamic -fopenmp -O3 -Wall") 40 | 41 | add_library(ply_c SHARED ply_c.cpp) 42 | target_link_libraries(ply_c 43 | ${Boost_LIBRARIES} 44 | ${PYTHON_LIBRARIES} 45 | ) 46 | -------------------------------------------------------------------------------- /lib/ply_c/Makefile: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10 3 | 4 | # Default target executed when no arguments are given to make. 5 | default_target: all 6 | 7 | .PHONY : default_target 8 | 9 | # Allow only one "make -f Makefile2" at a time, but pass parallelism. 10 | .NOTPARALLEL: 11 | 12 | 13 | #============================================================================= 14 | # Special targets provided by cmake. 15 | 16 | # Disable implicit rules so canonical targets will work. 17 | .SUFFIXES: 18 | 19 | 20 | # Remove some rules from gmake that .SUFFIXES does not remove. 21 | SUFFIXES = 22 | 23 | .SUFFIXES: .hpux_make_needs_suffix_list 24 | 25 | 26 | # Suppress display of executed commands. 27 | $(VERBOSE).SILENT: 28 | 29 | 30 | # A target that is always out of date. 31 | cmake_force: 32 | 33 | .PHONY : cmake_force 34 | 35 | #============================================================================= 36 | # Set environment variables for the build. 37 | 38 | # The shell in which to execute make rules. 39 | SHELL = /bin/sh 40 | 41 | # The CMake executable. 42 | CMAKE_COMMAND = /usr/bin/cmake 43 | 44 | # The command to remove a file. 45 | RM = /usr/bin/cmake -E remove -f 46 | 47 | # Escaping for special characters. 48 | EQUALS = = 49 | 50 | # The top-level source directory on which CMake was run. 51 | CMAKE_SOURCE_DIR = /test/work2020/superpoints/spnet/lib/ply_c 52 | 53 | # The top-level build directory on which CMake was run. 54 | CMAKE_BINARY_DIR = /test/work2020/superpoints/spnet/lib/ply_c 55 | 56 | #============================================================================= 57 | # Targets provided globally by CMake. 58 | 59 | # Special rule for the target rebuild_cache 60 | rebuild_cache: 61 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." 62 | /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) 63 | .PHONY : rebuild_cache 64 | 65 | # Special rule for the target rebuild_cache 66 | rebuild_cache/fast: rebuild_cache 67 | 68 | .PHONY : rebuild_cache/fast 69 | 70 | # Special rule for the target edit_cache 71 | edit_cache: 72 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." 73 | /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. 74 | .PHONY : edit_cache 75 | 76 | # Special rule for the target edit_cache 77 | edit_cache/fast: edit_cache 78 | 79 | .PHONY : edit_cache/fast 80 | 81 | # The main all target 82 | all: cmake_check_build_system 83 | $(CMAKE_COMMAND) -E cmake_progress_start /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles/progress.marks 84 | $(MAKE) -f CMakeFiles/Makefile2 all 85 | $(CMAKE_COMMAND) -E cmake_progress_start /test/work2020/superpoints/spnet/lib/ply_c/CMakeFiles 0 86 | .PHONY : all 87 | 88 | # The main clean target 89 | clean: 90 | $(MAKE) -f CMakeFiles/Makefile2 clean 91 | .PHONY : clean 92 | 93 | # The main clean target 94 | clean/fast: clean 95 | 96 | .PHONY : clean/fast 97 | 98 | # Prepare targets for installation. 99 | preinstall: all 100 | $(MAKE) -f CMakeFiles/Makefile2 preinstall 101 | .PHONY : preinstall 102 | 103 | # Prepare targets for installation. 104 | preinstall/fast: 105 | $(MAKE) -f CMakeFiles/Makefile2 preinstall 106 | .PHONY : preinstall/fast 107 | 108 | # clear depends 109 | depend: 110 | $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 111 | .PHONY : depend 112 | 113 | #============================================================================= 114 | # Target rules for targets named ply_c 115 | 116 | # Build rule for target. 117 | ply_c: cmake_check_build_system 118 | $(MAKE) -f CMakeFiles/Makefile2 ply_c 119 | .PHONY : ply_c 120 | 121 | # fast build rule for target. 122 | ply_c/fast: 123 | $(MAKE) -f CMakeFiles/ply_c.dir/build.make CMakeFiles/ply_c.dir/build 124 | .PHONY : ply_c/fast 125 | 126 | ply_c.o: ply_c.cpp.o 127 | 128 | .PHONY : ply_c.o 129 | 130 | # target to build an object file 131 | ply_c.cpp.o: 132 | $(MAKE) -f CMakeFiles/ply_c.dir/build.make CMakeFiles/ply_c.dir/ply_c.cpp.o 133 | .PHONY : ply_c.cpp.o 134 | 135 | ply_c.i: ply_c.cpp.i 136 | 137 | .PHONY : ply_c.i 138 | 139 | # target to preprocess a source file 140 | ply_c.cpp.i: 141 | $(MAKE) -f CMakeFiles/ply_c.dir/build.make CMakeFiles/ply_c.dir/ply_c.cpp.i 142 | .PHONY : ply_c.cpp.i 143 | 144 | ply_c.s: ply_c.cpp.s 145 | 146 | .PHONY : ply_c.s 147 | 148 | # target to generate assembly for a file 149 | ply_c.cpp.s: 150 | $(MAKE) -f CMakeFiles/ply_c.dir/build.make CMakeFiles/ply_c.dir/ply_c.cpp.s 151 | .PHONY : ply_c.cpp.s 152 | 153 | # Help Target 154 | help: 155 | @echo "The following are some of the valid targets for this Makefile:" 156 | @echo "... all (the default if no target is provided)" 157 | @echo "... clean" 158 | @echo "... depend" 159 | @echo "... rebuild_cache" 160 | @echo "... ply_c" 161 | @echo "... edit_cache" 162 | @echo "... ply_c.o" 163 | @echo "... ply_c.i" 164 | @echo "... ply_c.s" 165 | .PHONY : help 166 | 167 | 168 | 169 | #============================================================================= 170 | # Special targets to cleanup operation of make. 171 | 172 | # Special rule to run CMake to check the build system integrity. 173 | # No rule that depends on this can have commands that come from listfiles 174 | # because they might be regenerated. 175 | cmake_check_build_system: 176 | $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 177 | .PHONY : cmake_check_build_system 178 | 179 | -------------------------------------------------------------------------------- /lib/ply_c/cmake_install.cmake: -------------------------------------------------------------------------------- 1 | # Install script for directory: /test/work2020/superpoints/spnet/lib/ply_c 2 | 3 | # Set the install prefix 4 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 5 | set(CMAKE_INSTALL_PREFIX "/usr/local") 6 | endif() 7 | string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 8 | 9 | # Set the install configuration name. 10 | if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) 11 | if(BUILD_TYPE) 12 | string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" 13 | CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") 14 | else() 15 | set(CMAKE_INSTALL_CONFIG_NAME "") 16 | endif() 17 | message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") 18 | endif() 19 | 20 | # Set the component getting installed. 21 | if(NOT CMAKE_INSTALL_COMPONENT) 22 | if(COMPONENT) 23 | message(STATUS "Install component: \"${COMPONENT}\"") 24 | set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") 25 | else() 26 | set(CMAKE_INSTALL_COMPONENT) 27 | endif() 28 | endif() 29 | 30 | # Install shared libraries without execute permission? 31 | if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) 32 | set(CMAKE_INSTALL_SO_NO_EXE "1") 33 | endif() 34 | 35 | # Is this installation the result of a crosscompile? 36 | if(NOT DEFINED CMAKE_CROSSCOMPILING) 37 | set(CMAKE_CROSSCOMPILING "FALSE") 38 | endif() 39 | 40 | if(CMAKE_INSTALL_COMPONENT) 41 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") 42 | else() 43 | set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") 44 | endif() 45 | 46 | string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT 47 | "${CMAKE_INSTALL_MANIFEST_FILES}") 48 | file(WRITE "/test/work2020/superpoints/spnet/lib/ply_c/${CMAKE_INSTALL_MANIFEST}" 49 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 50 | -------------------------------------------------------------------------------- /lib/ply_c/connected_components.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | using namespace std; 12 | using namespace boost; 13 | 14 | typedef adjacency_list Graph; 15 | typedef typename graph_traits< Graph >::adjacency_iterator adjacency_iterator; 16 | 17 | void connected_components(const uint32_t n_ver, const uint32_t n_edg 18 | , const uint32_t * Eu, const uint32_t * Ev, const char * active_edge 19 | , std::vector & in_component, std::vector< std::vector > & components, const uint32_t cutoff) 20 | { //C-style interface 21 | 22 | Graph G(n_ver); 23 | for (uint32_t i_edg = 0; i_edg < n_edg; i_edg++) 24 | { 25 | if (active_edge[i_edg] > 0) 26 | { 27 | add_edge(Eu[i_edg], Ev[i_edg], G); 28 | } 29 | } 30 | 31 | int n_com = connected_components(G, &in_component[0]); 32 | 33 | //cout << "Total number of components: " << n_com << endl; 34 | 35 | std::vector< std::vector > components_tmp(n_com); 36 | for (uint32_t i_ver = 0; i_ver < n_ver; i_ver++) 37 | { 38 | components_tmp[in_component[i_ver]].push_back(i_ver); 39 | } 40 | 41 | //fuse components to preserve cutoff 42 | 43 | G = Graph(n_ver); 44 | for (uint32_t i_edg = 0; i_edg < n_edg; i_edg++) 45 | { 46 | if (active_edge[i_edg] == 0) 47 | { 48 | add_edge(Eu[i_edg], Ev[i_edg], G); 49 | } 50 | } 51 | 52 | typename graph_traits < Graph >::adjacency_iterator nei_ini, nei_end; 53 | boost::property_map::type vertex_index_map = get(boost::vertex_index, G); 54 | std::vector is_fused(n_ver, 0); 55 | 56 | int n_com_final = n_com; 57 | for (int i_com = 0; i_com < n_com; i_com++) 58 | { 59 | if (components_tmp[i_com].size() < cutoff) 60 | {//components is too small 61 | //std::cout << i_com << " of size " << components_tmp[i_com].size() << " / " << cutoff << std::endl; 62 | int largest_neigh_comp_value = 0; 63 | int largest_neigh_comp_index = -1; 64 | for (int i_ver_com = 0; i_ver_com < components_tmp[i_com].size(); i_ver_com++) 65 | { //std::cout << " considering node" << components_tmp[i_com][i_ver_com] << std::endl; 66 | boost::tie(nei_ini, nei_end) = adjacent_vertices(vertex(components_tmp[i_com][i_ver_com], G), G); 67 | for (graph_traits < Graph >::adjacency_iterator nei_ite = nei_ini; nei_ite != nei_end; nei_ite++) 68 | { 69 | int candidate_comp = in_component[vertex_index_map(*nei_ite)]; 70 | if ((candidate_comp == i_com) || (is_fused[candidate_comp])) 71 | { 72 | continue; 73 | } 74 | //std::cout << " neighbors " << vertex_index_map(*nei_ite) << " in comp " << candidate_comp << "of size " << components_tmp[candidate_comp].size() << std::endl; 75 | if (components_tmp[candidate_comp].size() > largest_neigh_comp_value) 76 | { 77 | largest_neigh_comp_value = components_tmp[candidate_comp].size() ; 78 | largest_neigh_comp_index = candidate_comp; 79 | } 80 | } 81 | } 82 | if (largest_neigh_comp_index>0) 83 | { 84 | //std::cout << "best comp = " << largest_neigh_comp_index << " of size " << largest_neigh_comp_value << std::endl; 85 | //we now fuse the two connected components 86 | components_tmp[largest_neigh_comp_index].insert(components_tmp[largest_neigh_comp_index].end(), components_tmp[i_com].begin(), components_tmp[i_com].end()); 87 | is_fused[i_com] = 1; 88 | n_com_final--; 89 | } 90 | } 91 | } 92 | 93 | components.resize(n_com_final); 94 | int i_com_index = 0; 95 | for (int i_com = 0; i_com < n_com; i_com++) 96 | { 97 | if (!is_fused[i_com]) 98 | { 99 | components[i_com_index] = components_tmp[i_com]; 100 | for (uint32_t i_ver_com = 0; i_ver_com < components_tmp[i_com].size(); i_ver_com++) 101 | { 102 | in_component[components_tmp[i_com][i_ver_com]] = i_com_index; 103 | } 104 | i_com_index++; 105 | } 106 | } 107 | 108 | 109 | return; 110 | } 111 | -------------------------------------------------------------------------------- /lib/ply_c/libply_c.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/ply_c/libply_c.so -------------------------------------------------------------------------------- /lib/ply_c/random_subgraph.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | using namespace boost; 13 | 14 | namespace subgraph { 15 | 16 | typedef adjacency_list Graph; 17 | 18 | typedef typename boost::graph_traits< Graph >::vertex_descriptor VertexDescriptor; 19 | 20 | typedef typename boost::property_map< Graph, boost::vertex_index_t>::type VertexIndexMap; 21 | 22 | typedef typename graph_traits < Graph >::adjacency_iterator Adjacency_iterator; 23 | 24 | 25 | void random_subgraph(const int n_ver, const int n_edg, const uint32_t * Eu, const uint32_t * Ev, int subgraph_size 26 | , uint8_t * selected_edges, uint8_t * selected_vertices) 27 | 28 | { //C-style interface 29 | 30 | srand((unsigned) time(NULL)); 31 | //srand((int) time(0)); 32 | if (n_ver < subgraph_size) 33 | { 34 | for (uint32_t i_edg = 0; i_edg < n_edg; i_edg++) 35 | { 36 | selected_edges[i_edg] = 1; 37 | } 38 | for (uint32_t i_ver = 0; i_ver < n_ver; i_ver++) 39 | { 40 | selected_vertices[n_ver] = 1; 41 | } 42 | return; 43 | } 44 | 45 | Graph G(n_ver); 46 | 47 | VertexIndexMap vertex_index_map = get(boost::vertex_index, G); 48 | VertexDescriptor ver_current; 49 | Adjacency_iterator ite_ver_adj,ite_ver_adj_end; 50 | int node_seen = 0, seed_index; 51 | queue ver_queue; 52 | 53 | for (uint32_t i_edg = 0; i_edg < n_edg; i_edg++) 54 | { //building graph 55 | add_edge(vertex(Eu[i_edg],G), vertex(Ev[i_edg],G), G); 56 | } 57 | 58 | //while(node_seen < subgraph_size) 59 | while(node_seen <= subgraph_size) 60 | { 61 | //add seed vertex 62 | seed_index = rand() % n_ver; 63 | if (selected_vertices[seed_index]) 64 | { 65 | continue; 66 | } 67 | ver_queue.push(vertex(seed_index,G)); 68 | selected_vertices[vertex_index_map(ver_queue.front())] = 1; 69 | node_seen = node_seen + 1; 70 | if (node_seen > subgraph_size) break; 71 | while(!ver_queue.empty()) 72 | { 73 | //pop the top of the queue and mark it as seen 74 | ver_current = ver_queue.front(); 75 | ver_queue.pop(); 76 | 77 | //add the neighbors of that vertex 78 | for (tie(ite_ver_adj, ite_ver_adj_end) = adjacent_vertices(ver_current, G); ite_ver_adj != ite_ver_adj_end; ite_ver_adj++) 79 | { 80 | int i_ver_adj = vertex_index_map(*ite_ver_adj); 81 | if ((selected_vertices[i_ver_adj]==0) && (node_seen <= subgraph_size)) 82 | {//vertex not already seen 83 | node_seen = node_seen + 1; 84 | selected_vertices[i_ver_adj] = 1; 85 | if (node_seen > subgraph_size) 86 | {//enough vertices 87 | break; 88 | } 89 | ver_queue.push(*ite_ver_adj); 90 | } 91 | 92 | } 93 | } 94 | } 95 | 96 | for (int i_edg = 0; i_edg < n_edg; i_edg++) 97 | { //add edges between selected vertices 98 | selected_edges[i_edg] = selected_vertices[vertex_index_map(vertex(Eu[i_edg],G))] 99 | * selected_vertices[vertex_index_map(vertex(Ev[i_edg],G))]; 100 | } 101 | return; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /lib/pointops/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/__init__.py -------------------------------------------------------------------------------- /lib/pointops/functions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/functions/__init__.py -------------------------------------------------------------------------------- /lib/pointops/setup.py: -------------------------------------------------------------------------------- 1 | #python3 setup.py install 2 | from setuptools import setup 3 | from torch.utils.cpp_extension import BuildExtension, CUDAExtension 4 | 5 | setup( 6 | name='pointops', 7 | ext_modules=[ 8 | CUDAExtension('pointops_cuda', [ 9 | 'src/pointops_api.cpp', 10 | 11 | 'src/ballquery/ballquery_cuda.cpp', 12 | 'src/ballquery/ballquery_cuda_kernel.cu', 13 | 14 | 'src/knnquery/knnquery_cuda.cpp', 15 | 'src/knnquery/knnquery_cuda_kernel.cu', 16 | 17 | 'src/knnquerycluster/knnquerycluster_cuda.cpp', 18 | 'src/knnquerycluster/knnquerycluster_cuda_kernel.cu', 19 | 20 | 'src/knnqueryclustergt/knnqueryclustergt_cuda.cpp', 21 | 'src/knnqueryclustergt/knnqueryclustergt_cuda_kernel.cu', 22 | 23 | 'src/knnquerypoint/knnquerypoint_cuda.cpp', 24 | 'src/knnquerypoint/knnquerypoint_cuda_kernel.cu', 25 | 26 | 'src/assofixp2c/assofixp2c_cuda.cpp', 27 | 'src/assofixp2c/assofixp2c_cuda_kernel.cu', 28 | 29 | 'src/assofixp2c_weight/assofixp2c_weight_cuda.cpp', 30 | 'src/assofixp2c_weight/assofixp2c_weight_cuda_kernel.cu', 31 | 32 | 'src/assomatrix/assomatrix_cuda.cpp', 33 | 'src/assomatrix/assomatrix_cuda_kernel.cu', 34 | 35 | 'src/assomatrix_label/assomatrix_label_cuda.cpp', 36 | 'src/assomatrix_label/assomatrix_label_cuda_kernel.cu', 37 | 38 | 'src/assomatrix_float/assomatrix_float_cuda.cpp', 39 | 'src/assomatrix_float/assomatrix_float_cuda_kernel.cu', 40 | 41 | #'src/knnquerydilate/knnquerydilate_cuda.cpp', 42 | #'src/knnquerydilate/knnquerydilate_cuda_kernel.cu', 43 | 44 | 'src/grouping/grouping_cuda.cpp', 45 | 'src/grouping/grouping_cuda_kernel.cu', 46 | 'src/grouping_int/grouping_int_cuda.cpp', 47 | 'src/grouping_int/grouping_int_cuda_kernel.cu', 48 | 'src/interpolation/interpolation_cuda.cpp', 49 | 'src/interpolation/interpolation_cuda_kernel.cu', 50 | 'src/sampling/sampling_cuda.cpp', 51 | 'src/sampling/sampling_cuda_kernel.cu', 52 | 53 | 'src/labelstat/labelstat_cuda.cpp', 54 | 'src/labelstat/labelstat_cuda_kernel.cu', 55 | 56 | 'src/featuredistribute/featuredistribute_cuda.cpp', 57 | 'src/featuredistribute/featuredistribute_cuda_kernel.cu' 58 | ], 59 | extra_compile_args={'cxx': ['-g'], 60 | 'nvcc': ['-O2']}) 61 | ], 62 | cmdclass={'build_ext': BuildExtension}) 63 | -------------------------------------------------------------------------------- /lib/pointops/src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/assofixp2c/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/assofixp2c/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/assofixp2c/assofixp2c_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "assofixp2c_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void assofixp2c_cuda(int b, int n, int m, int ks, int nsample, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor) // 16 | { 17 | CHECK_INPUT(idx_c_tensor); 18 | CHECK_INPUT(cid_tensor); 19 | CHECK_INPUT(idx_tensor); 20 | 21 | const int *idx_c = idx_c_tensor.data(); 22 | const int *cid = cid_tensor.data(); 23 | int *idx = idx_tensor.data(); 24 | 25 | cudaStream_t stream = THCState_getCurrentStream(state); 26 | 27 | assofixp2c_cuda_launcher(b, n, m, ks, nsample, idx_c, cid, idx, stream); 28 | } 29 | -------------------------------------------------------------------------------- /lib/pointops/src/assofixp2c/assofixp2c_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "assofixp2c_cuda_kernel.h" 3 | 4 | // input: xyz (b, n, 3) new_xyz (b, m, 3) 5 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 6 | 7 | // Note: n is the number of points, m is the number of clusters 8 | // Note: nsample <= 1000 9 | 10 | // input: idx_c (b, n, ks) cid (b, m, 1) 11 | // output: idx (b, m, nsample) 12 | __global__ void assofixp2c_cuda_kernel(int b, int n, int m, int ks, int nsample, const int *__restrict__ idx_c, const int *__restrict__ cid, int *__restrict__ idx) { 13 | int bs_idx = blockIdx.y; 14 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 15 | if (bs_idx >= b || pt_idx >= m) return; 16 | 17 | //new_xyz += bs_idx * m * 3 + pt_idx * 3; 18 | //cid += bs_idx * m * 1 + pt_idx * 1; 19 | // cid += bs_idx * m; 20 | cid += bs_idx * m * 1 + pt_idx * 1; 21 | //xyz += bs_idx * n * 3; 22 | idx_c += bs_idx * n * ks; // add 23 | idx += bs_idx * m * nsample + pt_idx * nsample; 24 | 25 | //float new_x = new_xyz[0]; 26 | //float new_y = new_xyz[1]; 27 | //float new_z = new_xyz[2]; 28 | int cluster_id = cid[0]; 29 | 30 | //double* best = new double[nsample]; 31 | //int* besti = new int[nsample]; 32 | // int tmpi[1000]; 33 | // for(int i = 0; i < nsample; i++){ 34 | // tmpi[i] = 0; 35 | // } 36 | for (int i = 0; i < nsample; i++) { 37 | idx[i] = cluster_id; 38 | } 39 | int last = 0; 40 | for(int k = 0; k < n && last < nsample; k++) { 41 | for (int j = 0; j < ks && last < nsample; j++) { 42 | int id = idx_c[k * ks + j]; // cluster id of i-th point 43 | if (id == cluster_id) { 44 | // tmpi[last] = k; 45 | idx[last] = k; 46 | last++; 47 | } 48 | } 49 | } 50 | // for(int i = 0; i < last; i++){ 51 | // idx[i] = tmpi[i]; 52 | // } 53 | // for(int i = last; i < nsample; i++){ 54 | // idx[i] = cluster_id; 55 | // } 56 | //delete []best; 57 | //delete []besti; 58 | } 59 | 60 | 61 | void assofixp2c_cuda_launcher(int b, int n, int m, int ks, int nsample, const int *idx_c, const int *cid, int *idx, cudaStream_t stream) { 62 | // param idx_c: (b, n, ks) 63 | // param cid: (b, m, 1) 64 | // param idx: (b, m, nsample) 65 | 66 | cudaError_t err; 67 | 68 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 69 | dim3 threads(THREADS_PER_BLOCK); 70 | 71 | assofixp2c_cuda_kernel<<>>(b, n, m, ks, nsample, idx_c, cid, idx); 72 | // cudaDeviceSynchronize(); // for using printf in kernel function 73 | 74 | err = cudaGetLastError(); 75 | if (cudaSuccess != err) { 76 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 77 | exit(-1); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /lib/pointops/src/assofixp2c/assofixp2c_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASSOFIXP2C_CUDA_KERNEL 2 | #define _ASSOFIXP2C_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void assofixp2c_cuda(int b, int n, int m, int ks, int nsample, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor); 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void assofixp2c_cuda_launcher(int b, int n, int m, int ks, int nsample, const int *idx_c, const int *cid, int *idx, cudaStream_t stream); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/pointops/src/assofixp2c_weight/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/assofixp2c_weight/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/assofixp2c_weight/assofixp2c_weight_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "assofixp2c_weight_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void assofixp2c_weight_cuda(int b, int n, int m, int ks, int nsample, at::Tensor val_c_tensor, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor) // 16 | { 17 | CHECK_INPUT(val_c_tensor); 18 | CHECK_INPUT(idx_c_tensor); 19 | CHECK_INPUT(cid_tensor); 20 | 21 | const float *val_c = val_c_tensor.data(); 22 | const int *idx_c = idx_c_tensor.data(); 23 | const int *cid = cid_tensor.data(); 24 | float *idx = idx_tensor.data(); 25 | 26 | cudaStream_t stream = THCState_getCurrentStream(state); 27 | 28 | assofixp2c_weight_cuda_launcher(b, n, m, ks, nsample, val_c, idx_c, cid, idx, stream); 29 | } 30 | -------------------------------------------------------------------------------- /lib/pointops/src/assofixp2c_weight/assofixp2c_weight_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "assofixp2c_weight_cuda_kernel.h" 3 | 4 | // input: xyz (b, n, 3) new_xyz (b, m, 3) 5 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 6 | 7 | // Note: n is the number of points, m is the number of clusters 8 | // Note: nsample <= 1000 9 | 10 | // input: val_c (b, n, ks) idx_c (b, n, ks) cid (b, m, 1) 11 | // output: idx (b, m, nsample) 12 | __global__ void assofixp2c_weight_cuda_kernel(int b, int n, int m, int ks, int nsample, const float *__restrict__ val_c, const int *__restrict__ idx_c, const int *__restrict__ cid, float *__restrict__ idx) { 13 | int bs_idx = blockIdx.y; 14 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 15 | if (bs_idx >= b || pt_idx >= m) return; 16 | 17 | //new_xyz += bs_idx * m * 3 + pt_idx * 3; 18 | //cid += bs_idx * m * 1 + pt_idx * 1; 19 | cid += bs_idx * m * 1 + pt_idx * 1; 20 | //xyz += bs_idx * n * 3; 21 | val_c += bs_idx * n * ks; // add 22 | idx_c += bs_idx * n * ks; // add 23 | idx += bs_idx * m * nsample + pt_idx * nsample; 24 | 25 | //float new_x = new_xyz[0]; 26 | //float new_y = new_xyz[1]; 27 | //float new_z = new_xyz[2]; 28 | int cluster_id = cid[0]; 29 | 30 | //double* best = new double[nsample]; 31 | //int* besti = new int[nsample]; 32 | //float tmpi[20]; 33 | //for(int i = 0; i < n; i++){ 34 | // tmpi[i] = 0.0; 35 | //} 36 | for (int i = 0; i < nsample; i++) { 37 | idx[i] = 1.0; 38 | } 39 | int num = 0; 40 | for(int k = 0; k < n && num < nsample; k++) { 41 | for (int j = 0; j < ks && num < nsample; j++) { 42 | int id = idx_c[k * ks + j]; // cluster id of i-th point 43 | float val = val_c[k * ks + j]; 44 | if (id == cluster_id) { 45 | //tmpi[k] = val; 46 | idx[num] = val; 47 | num++; 48 | } 49 | } 50 | } 51 | //for(int i = 0; i < n; i++){ 52 | // idx[i] = tmpi[i]; 53 | //} 54 | //delete []best; 55 | //delete []besti; 56 | } 57 | 58 | 59 | void assofixp2c_weight_cuda_launcher(int b, int n, int m, int ks, int nsample, const float *val_c, const int *idx_c, const int *cid, float *idx, cudaStream_t stream) { 60 | // param val_c: (B, n, ks) 61 | // param idx_c: (B, n, ks) 62 | // param cid: (B, m, 1) 63 | // param idx: (B, m, n) 64 | 65 | cudaError_t err; 66 | 67 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 68 | dim3 threads(THREADS_PER_BLOCK); 69 | 70 | assofixp2c_weight_cuda_kernel<<>>(b, n, m, ks, nsample, val_c, idx_c, cid, idx); 71 | // cudaDeviceSynchronize(); // for using printf in kernel function 72 | 73 | err = cudaGetLastError(); 74 | if (cudaSuccess != err) { 75 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 76 | exit(-1); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/pointops/src/assofixp2c_weight/assofixp2c_weight_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASSOFIXP2C_WEIGHT_CUDA_KERNEL 2 | #define _ASSOFIXP2C_WEIGHT_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void assofixp2c_weight_cuda(int b, int n, int m, int ks, int nsample, at::Tensor val_c_tensor, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor); 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void assofixp2c_weight_cuda_launcher(int b, int n, int m, int ks, int nsample, const float *val_c, const int *idx_c, const int *cid, float *idx, cudaStream_t stream); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/assomatrix/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix/assomatrix_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "assomatrix_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void assomatrix_cuda(int b, int n, int m, int ks, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor, at::Tensor cnt_tensor) // 16 | { 17 | CHECK_INPUT(idx_c_tensor); 18 | CHECK_INPUT(cid_tensor); 19 | 20 | const int *idx_c = idx_c_tensor.data(); 21 | const int *cid = cid_tensor.data(); 22 | int *idx = idx_tensor.data(); 23 | int *cnt = cnt_tensor.data(); 24 | 25 | cudaStream_t stream = THCState_getCurrentStream(state); 26 | 27 | assomatrix_cuda_launcher(b, n, m, ks, idx_c, cid, idx, cnt, stream); 28 | } 29 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix/assomatrix_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "assomatrix_cuda_kernel.h" 3 | 4 | // input: xyz (b, n, 3) new_xyz (b, m, 3) 5 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 6 | 7 | // Note: n is the number of points, m is the number of clusters 8 | // Note: nsample <= 1000 9 | 10 | // input: idx_c (b, n, ks) cid (b, m, 1) 11 | // output: idx (b, m, n) cnt (b, m, 1) 12 | __global__ void assomatrix_cuda_kernel(int b, int n, int m, int ks, const int *__restrict__ idx_c, const int *__restrict__ cid, int *__restrict__ idx, int *__restrict__ cnt) { 13 | int bs_idx = blockIdx.y; 14 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 15 | if (bs_idx >= b || pt_idx >= m) return; 16 | 17 | //new_xyz += bs_idx * m * 3 + pt_idx * 3; 18 | //cid += bs_idx * m * 1 + pt_idx * 1; 19 | cid += bs_idx * m * 1 + pt_idx * 1; 20 | //xyz += bs_idx * n * 3; 21 | idx_c += bs_idx * n * ks; // add 22 | idx += bs_idx * m * n + pt_idx * n; 23 | cnt += bs_idx * m * 1 + pt_idx * 1; // count number of points located in one superpoint 24 | 25 | //float new_x = new_xyz[0]; 26 | //float new_y = new_xyz[1]; 27 | //float new_z = new_xyz[2]; 28 | int cluster_id = cid[0]; 29 | 30 | //double* best = new double[nsample]; 31 | //int* besti = new int[nsample]; 32 | //int tmpi[20000]; 33 | //for(int i = 0; i < n; i++){ 34 | // tmpi[i] = 0; 35 | //} 36 | int num = 0; 37 | for(int k = 0; k < n; k++){ 38 | for (int j = 0; j < ks; j++) { 39 | int id = idx_c[k * ks + j]; // cluster id of i-th point 40 | if (id == cluster_id) { 41 | //tmpi[k] = 1; 42 | idx[k] = 1; 43 | num++; 44 | } 45 | } 46 | } 47 | //for(int i = 0; i < n; i++){ 48 | // idx[i] = tmpi[i]; 49 | //} 50 | cnt[0] = num; 51 | //delete []best; 52 | //delete []besti; 53 | } 54 | 55 | 56 | void assomatrix_cuda_launcher(int b, int n, int m, int ks, const int *idx_c, const int *cid, int *idx, int *cnt, cudaStream_t stream) { 57 | // param new_xyz: (B, m, 3) 58 | // param xyz: (B, n, 3) 59 | // param idx: (B, m, n) 60 | // param cnt: (B, m, 1) 61 | 62 | cudaError_t err; 63 | 64 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 65 | dim3 threads(THREADS_PER_BLOCK); 66 | 67 | assomatrix_cuda_kernel<<>>(b, n, m, ks, idx_c, cid, idx, cnt); 68 | // cudaDeviceSynchronize(); // for using printf in kernel function 69 | 70 | err = cudaGetLastError(); 71 | if (cudaSuccess != err) { 72 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 73 | exit(-1); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix/assomatrix_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASSOMATRIX_CUDA_KERNEL 2 | #define _ASSOMATRIX_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void assomatrix_cuda(int b, int n, int m, int ks, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor, at::Tensor cnt_tensor); 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void assomatrix_cuda_launcher(int b, int n, int m, int ks, const int *idx_c, const int *cid, int *idx, int *cnt, cudaStream_t stream); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix_float/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/assomatrix_float/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix_float/assomatrix_float_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "assomatrix_float_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void assomatrix_float_cuda(int b, int n, int m, int ks, at::Tensor val_c_tensor, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor, at::Tensor cnt_tensor) // 16 | { 17 | CHECK_INPUT(idx_c_tensor); 18 | CHECK_INPUT(cid_tensor); 19 | 20 | const float *val_c = val_c_tensor.data(); 21 | const int *idx_c = idx_c_tensor.data(); 22 | const int *cid = cid_tensor.data(); 23 | float *idx = idx_tensor.data(); 24 | int *cnt = cnt_tensor.data(); 25 | 26 | cudaStream_t stream = THCState_getCurrentStream(state); 27 | 28 | assomatrix_float_cuda_launcher(b, n, m, ks, val_c, idx_c, cid, idx, cnt, stream); 29 | } 30 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix_float/assomatrix_float_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "assomatrix_float_cuda_kernel.h" 3 | 4 | // input: xyz (b, n, 3) new_xyz (b, m, 3) 5 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 6 | 7 | // Note: n is the number of points, m is the number of clusters 8 | // Note: nsample <= 1000 9 | 10 | // input: val_c (b, n, ks) idx_c (b, n, ks) cid (b, m, 1) 11 | // output: idx (b, m, n) cnt (b, m, 1) 12 | __global__ void assomatrix_float_cuda_kernel(int b, int n, int m, int ks, const float *__restrict__ val_c, const int *__restrict__ idx_c, const int *__restrict__ cid, float *__restrict__ idx, int *__restrict__ cnt) { 13 | int bs_idx = blockIdx.y; 14 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 15 | if (bs_idx >= b || pt_idx >= m) return; 16 | 17 | //new_xyz += bs_idx * m * 3 + pt_idx * 3; 18 | //cid += bs_idx * m * 1 + pt_idx * 1; 19 | cid += bs_idx * m * 1 + pt_idx * 1; 20 | //xyz += bs_idx * n * 3; 21 | val_c += bs_idx * n * ks; // add 22 | idx_c += bs_idx * n * ks; // add 23 | idx += bs_idx * m * n + pt_idx * n; 24 | cnt += bs_idx * m * 1 + pt_idx * 1; // count number of points located in one superpoint 25 | 26 | //float new_x = new_xyz[0]; 27 | //float new_y = new_xyz[1]; 28 | //float new_z = new_xyz[2]; 29 | int cluster_id = cid[0]; 30 | 31 | //double* best = new double[nsample]; 32 | //int* besti = new int[nsample]; 33 | //float tmpi[20]; 34 | //for(int i = 0; i < n; i++){ 35 | // tmpi[i] = 0.0; 36 | //} 37 | int num = 0; 38 | for(int k = 0; k < n; k++){ 39 | for (int j = 0; j < ks; j++) { 40 | int id = idx_c[k * ks + j]; // cluster id of i-th point 41 | float val = val_c[k * ks + j]; 42 | if (id == cluster_id) { 43 | //tmpi[k] = val; 44 | idx[k] = val; 45 | num++; 46 | } 47 | } 48 | } 49 | //for(int i = 0; i < n; i++){ 50 | // idx[i] = tmpi[i]; 51 | //} 52 | cnt[0] = num; 53 | //delete []best; 54 | //delete []besti; 55 | } 56 | 57 | 58 | void assomatrix_float_cuda_launcher(int b, int n, int m, int ks, const float *val_c, const int *idx_c, const int *cid, float *idx, int *cnt, cudaStream_t stream) { 59 | // param val_c: (B, n, ks) 60 | // param idx_c: (B, n, ks) 61 | // param cid: (B, m, 1) 62 | // param idx: (B, m, n) 63 | // param cnt: (B, m, 1) 64 | 65 | cudaError_t err; 66 | 67 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 68 | dim3 threads(THREADS_PER_BLOCK); 69 | 70 | assomatrix_float_cuda_kernel<<>>(b, n, m, ks, val_c, idx_c, cid, idx, cnt); 71 | // cudaDeviceSynchronize(); // for using printf in kernel function 72 | 73 | err = cudaGetLastError(); 74 | if (cudaSuccess != err) { 75 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 76 | exit(-1); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix_float/assomatrix_float_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASSOMATRIX_FLOAT_CUDA_KERNEL 2 | #define _ASSOMATRIX_FLOAT_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void assomatrix_float_cuda(int b, int n, int m, int ks, at::Tensor val_c_tensor, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor, at::Tensor cnt_tensor); 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void assomatrix_float_cuda_launcher(int b, int n, int m, int ks, const float *val_c, const int *idx_c, const int *cid, float *idx, int *cnt, cudaStream_t stream); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix_label/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/assomatrix_label/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix_label/assomatrix_label_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "assomatrix_label_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void assomatrix_label_cuda(int b, int n, int m, int ks, int category, at::Tensor idx_c_tensor, at::Tensor lab_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor, at::Tensor cnt_tensor, at::Tensor clab_tensor) // 16 | { 17 | CHECK_INPUT(idx_c_tensor); 18 | CHECK_INPUT(cid_tensor); 19 | 20 | const int *idx_c = idx_c_tensor.data(); 21 | const int *lab = lab_tensor.data(); 22 | const int *cid = cid_tensor.data(); 23 | int *idx = idx_tensor.data(); 24 | int *cnt = cnt_tensor.data(); 25 | int *clab = clab_tensor.data(); 26 | 27 | cudaStream_t stream = THCState_getCurrentStream(state); 28 | 29 | assomatrix_label_cuda_launcher(b, n, m, ks, category, idx_c, lab, cid, idx, cnt, clab, stream); 30 | } 31 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix_label/assomatrix_label_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "assomatrix_label_cuda_kernel.h" 3 | 4 | // input: xyz (b, n, 3) new_xyz (b, m, 3) 5 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 6 | 7 | // Note: n is the number of points, m is the number of clusters 8 | // Note: nsample <= 1000 9 | 10 | // input: idx_c (b, n, ks) lab (b, n, 1) cid (b, m, 1) 11 | // output: idx (b, m, n) cnt (b, m, 1) clab (b, m, class) 12 | __global__ void assomatrix_label_cuda_kernel(int b, int n, int m, int ks, int category, const int *__restrict__ idx_c, const int *__restrict__ lab, const int *__restrict__ cid, int *__restrict__ idx, int *__restrict__ cnt, int *__restrict__ clab) { 13 | int bs_idx = blockIdx.y; 14 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 15 | if (bs_idx >= b || pt_idx >= m) return; 16 | 17 | //new_xyz += bs_idx * m * 3 + pt_idx * 3; 18 | //cid += bs_idx * m * 1 + pt_idx * 1; 19 | cid += bs_idx * m * 1 + pt_idx * 1; 20 | //xyz += bs_idx * n * 3; 21 | idx_c += bs_idx * n * ks; // add 22 | lab += bs_idx * n * 1; // add 23 | 24 | idx += bs_idx * m * n + pt_idx * n; 25 | cnt += bs_idx * m * 1 + pt_idx * 1; // count number of points located in one superpoint 26 | clab += bs_idx * m * category + pt_idx * category; 27 | 28 | //float new_x = new_xyz[0]; 29 | //float new_y = new_xyz[1]; 30 | //float new_z = new_xyz[2]; 31 | int cluster_id = cid[0]; 32 | 33 | //double* best = new double[nsample]; 34 | //int* besti = new int[nsample]; 35 | //int tmpi[20000]; 36 | //for(int i = 0; i < n; i++){ 37 | // tmpi[i] = 0; 38 | //} 39 | int num = 0; 40 | for(int k = 0; k < n; k++){ 41 | int k_lab = lab[k]; 42 | for (int j = 0; j < ks; j++) { 43 | int id = idx_c[k * ks + j]; // cluster id of i-th point 44 | if (id == cluster_id) { 45 | //tmpi[k] = 1; 46 | idx[k] = 1; 47 | clab[k_lab]++; 48 | num++; 49 | } 50 | } 51 | } 52 | //for(int i = 0; i < n; i++){ 53 | // idx[i] = tmpi[i]; 54 | //} 55 | cnt[0] = num; 56 | //delete []best; 57 | //delete []besti; 58 | } 59 | 60 | 61 | void assomatrix_label_cuda_launcher(int b, int n, int m, int ks, int category, const int *idx_c, const int *lab, const int *cid, int *idx, int *cnt, int *clab, cudaStream_t stream) { 62 | // param new_xyz: (B, m, 3) 63 | // param xyz: (B, n, 3) 64 | // param idx: (B, m, n) 65 | // param cnt: (B, m, 1) 66 | // param clab: (B, m, class) 67 | 68 | cudaError_t err; 69 | 70 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 71 | dim3 threads(THREADS_PER_BLOCK); 72 | 73 | assomatrix_label_cuda_kernel<<>>(b, n, m, ks, category, idx_c, lab, cid, idx, cnt, clab); 74 | // cudaDeviceSynchronize(); // for using printf in kernel function 75 | 76 | err = cudaGetLastError(); 77 | if (cudaSuccess != err) { 78 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 79 | exit(-1); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/pointops/src/assomatrix_label/assomatrix_label_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASSOMATRIX_LABEL_CUDA_KERNEL 2 | #define _ASSOMATRIX_LABEL_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void assomatrix_label_cuda(int b, int n, int m, int ks, int category, at::Tensor idx_c_tensor, at::Tensor lab_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor, at::Tensor cnt_tensor, at::Tensor clab_tensor); 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void assomatrix_label_cuda_launcher(int b, int n, int m, int ks, int category, const int *idx_c, const int *lab, const int *cid, int *idx, int *cnt, int *clab, cudaStream_t stream); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/pointops/src/ballquery/ballquery_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "ballquery_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | void ballquery_cuda(int b, int n, int m, float radius, int nsample, at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor idx_tensor) 15 | { 16 | const float *new_xyz = new_xyz_tensor.data(); 17 | const float *xyz = xyz_tensor.data(); 18 | int *idx = idx_tensor.data(); 19 | 20 | ballquery_cuda_launcher(b, n, m, radius, nsample, new_xyz, xyz, idx); 21 | } 22 | 23 | 24 | void ballquery_cuda_fast(int b, int n, int m, float radius, int nsample, at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor idx_tensor) 25 | { 26 | CHECK_INPUT(new_xyz_tensor); 27 | CHECK_INPUT(xyz_tensor); 28 | 29 | const float *new_xyz = new_xyz_tensor.data(); 30 | const float *xyz = xyz_tensor.data(); 31 | int *idx = idx_tensor.data(); 32 | 33 | cudaStream_t stream = THCState_getCurrentStream(state); 34 | 35 | ballquery_cuda_launcher_fast(b, n, m, radius, nsample, new_xyz, xyz, idx, stream); 36 | } 37 | -------------------------------------------------------------------------------- /lib/pointops/src/ballquery/ballquery_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "ballquery_cuda_kernel.h" 3 | 4 | // input: new_xyz(b, m, 3) xyz(b, n, 3) 5 | // output: idx(b, m, nsample) 6 | __global__ void ballquery_cuda_kernel(int b, int n, int m, float radius, int nsample, const float *new_xyz, const float *xyz, int *idx) 7 | { 8 | int batch_index = blockIdx.x; 9 | xyz += batch_index * n * 3; 10 | new_xyz += batch_index * m * 3; 11 | idx += m * nsample * batch_index; 12 | int index = threadIdx.x; 13 | int stride = blockDim.x; 14 | 15 | float radius2 = radius * radius; 16 | for (int j = index; j < m; j += stride) 17 | { 18 | float new_x = new_xyz[j * 3 + 0]; 19 | float new_y = new_xyz[j * 3 + 1]; 20 | float new_z = new_xyz[j * 3 + 2]; 21 | for (int k = 0, cnt = 0; k < n && cnt < nsample; ++k) 22 | { 23 | float x = xyz[k * 3 + 0]; 24 | float y = xyz[k * 3 + 1]; 25 | float z = xyz[k * 3 + 2]; 26 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z); 27 | if (d2 < radius2) 28 | { 29 | if (cnt == 0) 30 | { 31 | for (int l = 0; l < nsample; ++l) 32 | idx[j * nsample + l] = k; 33 | } 34 | idx[j * nsample + cnt] = k; 35 | ++cnt; 36 | } 37 | } 38 | } 39 | } 40 | 41 | void ballquery_cuda_launcher(int b, int n, int m, float radius, int nsample, const float *new_xyz, const float *xyz, int *idx) 42 | { 43 | ballquery_cuda_kernel<<>>(b, n, m, radius, nsample, new_xyz, xyz, idx); 44 | } 45 | 46 | 47 | __global__ void ballquery_cuda_kernel_fast(int b, int n, int m, float radius, int nsample, const float *__restrict__ new_xyz, const float *__restrict__ xyz, int *__restrict__ idx) { 48 | int bs_idx = blockIdx.y; 49 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 50 | if (bs_idx >= b || pt_idx >= m) return; 51 | 52 | new_xyz += bs_idx * m * 3 + pt_idx * 3; 53 | xyz += bs_idx * n * 3; 54 | idx += bs_idx * m * nsample + pt_idx * nsample; 55 | 56 | float radius2 = radius * radius; 57 | float new_x = new_xyz[0]; 58 | float new_y = new_xyz[1]; 59 | float new_z = new_xyz[2]; 60 | 61 | int cnt = 0; 62 | for (int k = 0; k < n; ++k) { 63 | float x = xyz[k * 3 + 0]; 64 | float y = xyz[k * 3 + 1]; 65 | float z = xyz[k * 3 + 2]; 66 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z); 67 | if (d2 < radius2){ 68 | if (cnt == 0){ 69 | for (int l = 0; l < nsample; ++l) { 70 | idx[l] = k; 71 | } 72 | } 73 | idx[cnt] = k; 74 | ++cnt; 75 | if (cnt >= nsample){ 76 | break; 77 | } 78 | } 79 | } 80 | } 81 | 82 | 83 | void ballquery_cuda_launcher_fast(int b, int n, int m, float radius, int nsample, const float *new_xyz, const float *xyz, int *idx, cudaStream_t stream) { 84 | // param new_xyz: (B, m, 3) 85 | // param xyz: (B, n, 3) 86 | // param idx: (B, m, nsample) 87 | 88 | cudaError_t err; 89 | 90 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 91 | dim3 threads(THREADS_PER_BLOCK); 92 | 93 | ballquery_cuda_kernel_fast<<>>(b, n, m, radius, nsample, new_xyz, xyz, idx); 94 | // cudaDeviceSynchronize(); // for using printf in kernel function 95 | 96 | err = cudaGetLastError(); 97 | if (cudaSuccess != err) { 98 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 99 | exit(-1); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /lib/pointops/src/ballquery/ballquery_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _BALLQUERY_CUDA_KERNEL 2 | #define _BALLQUERY_CUDA_KERNEL 3 | #include 4 | #include 5 | #include 6 | 7 | void ballquery_cuda(int b, int n, int m, float radius, int nsample, at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor idx_tensor); 8 | 9 | void ballquery_cuda_fast(int b, int n, int m, float radius, int nsample, at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor idx_tensor); 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | void ballquery_cuda_launcher(int b, int n, int m, float radius, int nsample, const float *xyz, const float *new_xyz, int *idx); 16 | 17 | void ballquery_cuda_launcher_fast(int b, int n, int m, float radius, int nsample, const float *new_xyz, const float *xyz, int *idx, cudaStream_t stream); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /lib/pointops/src/cuda_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_UTILS_H 2 | #define _CUDA_UTILS_H 3 | 4 | #include 5 | 6 | #define TOTAL_THREADS 1024 7 | 8 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 9 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 10 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 11 | 12 | #define THREADS_PER_BLOCK 256 13 | #define DIVUP(m,n) ((m) / (n) + ((m) % (n) > 0)) 14 | 15 | inline int opt_n_threads(int work_size) { 16 | const int pow_2 = std::log(static_cast(work_size)) / std::log(2.0); 17 | return max(min(1 << pow_2, TOTAL_THREADS), 1); 18 | } 19 | 20 | inline dim3 opt_block_config(int x, int y) { 21 | const int x_threads = opt_n_threads(x); 22 | const int y_threads = max(min(opt_n_threads(y), TOTAL_THREADS / x_threads), 1); 23 | dim3 block_config(x_threads, y_threads, 1); 24 | return block_config; 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /lib/pointops/src/featuredistribute/featuredistribute_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "featuredistribute_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void featuredistribute_cuda(int b, int n, int m, at::Tensor max_xyz_tensor, at::Tensor xyz_tensor, at::Tensor distribute_idx_tensor) 16 | { 17 | CHECK_INPUT(max_xyz_tensor); 18 | CHECK_INPUT(xyz_tensor); 19 | 20 | const float *max_xyz = max_xyz_tensor.data(); 21 | const float *xyz = xyz_tensor.data(); 22 | int *distribute_idx = distribute_idx_tensor.data(); 23 | 24 | cudaStream_t stream = THCState_getCurrentStream(state); 25 | 26 | featuredistribute_cuda_launcher(b, n, m, max_xyz, xyz, distribute_idx, stream); 27 | } 28 | 29 | 30 | void featuregather_forward_cuda(int b, int n, int m, int c, at::Tensor max_feature_tensor, at::Tensor distribute_idx_tensor, at::Tensor distribute_feature_tensor) 31 | { 32 | CHECK_INPUT(max_feature_tensor); 33 | CHECK_INPUT(distribute_idx_tensor); 34 | 35 | const float *max_feature = max_feature_tensor.data(); 36 | const int *distribute_idx = distribute_idx_tensor.data(); 37 | float *distribute_feature = distribute_feature_tensor.data(); 38 | 39 | cudaStream_t stream = THCState_getCurrentStream(state); 40 | 41 | featuregather_forward_cuda_launcher(b, n, m, c, max_feature, distribute_idx, distribute_feature, stream); 42 | } 43 | 44 | 45 | void featuregather_backward_cuda(int b, int n, int m, int c, at::Tensor grad_distribute_feature_tensor, at::Tensor distribute_idx_tensor, at::Tensor grad_max_feature_tensor) 46 | { 47 | CHECK_INPUT(grad_distribute_feature_tensor); 48 | CHECK_INPUT(distribute_idx_tensor); 49 | 50 | const float *grad_distribute_feature = grad_distribute_feature_tensor.data(); 51 | const int *distribute_idx = distribute_idx_tensor.data(); 52 | float *grad_max_feature = grad_max_feature_tensor.data(); 53 | 54 | cudaStream_t stream = THCState_getCurrentStream(state); 55 | 56 | featuregather_backward_cuda_launcher(b, n, m, c, grad_distribute_feature, distribute_idx, grad_max_feature, stream); 57 | } -------------------------------------------------------------------------------- /lib/pointops/src/featuredistribute/featuredistribute_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "featuredistribute_cuda_kernel.h" 3 | 4 | __global__ void featuredistribute_cuda_kernel(int b, int n, int m, const float *max_xyz, const float *xyz, int *distribute_idx) { 5 | int bs_idx = blockIdx.y; 6 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 7 | if (bs_idx >= b || pt_idx >= m) return; 8 | 9 | max_xyz += bs_idx * n * 3; 10 | xyz += bs_idx * m * 3 + pt_idx * 3; 11 | distribute_idx += bs_idx * m + pt_idx; 12 | 13 | float x = xyz[0]; 14 | float y = xyz[1]; 15 | float z = xyz[2]; 16 | 17 | float min_dist2 = 100000; 18 | int min_dist_idx = -1; 19 | for (int k = 0; k < n; ++k) { 20 | float max_x = max_xyz[k * 3 + 0]; 21 | float max_y = max_xyz[k * 3 + 1]; 22 | float max_z = max_xyz[k * 3 + 2]; 23 | float d2 = (max_x - x) * (max_x - x) + (max_y - y) * (max_y - y) + (max_z - z) * (max_z - z); 24 | if (d2 < min_dist2){ 25 | min_dist_idx = k; 26 | min_dist2 = d2; 27 | } 28 | } 29 | distribute_idx[0] = min_dist_idx; 30 | } 31 | 32 | 33 | void featuredistribute_cuda_launcher(int b, int n, int m, const float *max_xyz, const float *xyz, int *distribute_idx, cudaStream_t stream) { 34 | // param max_xyz: (b, n, 3) 35 | // param xyz: (b, m, 3) 36 | // return distribute_idx: (b, m) 37 | 38 | cudaError_t err; 39 | 40 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 41 | dim3 threads(THREADS_PER_BLOCK); 42 | 43 | featuredistribute_cuda_kernel<<>>(b, n, m, max_xyz, xyz, distribute_idx); 44 | // cudaDeviceSynchronize(); // for using printf in kernel function 45 | 46 | err = cudaGetLastError(); 47 | if (cudaSuccess != err) { 48 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 49 | exit(-1); 50 | } 51 | } 52 | 53 | __global__ void featuregather_forward_cuda_kernel(int b, int n, int m, int c, const float *max_feature, const int *distribute_idx, float *distribute_feature) { 54 | int bs_idx = blockIdx.z; 55 | int c_idx = blockIdx.y; 56 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 57 | if (bs_idx >= b || c_idx >= c || pt_idx >= m) return; 58 | 59 | max_feature += bs_idx * c * n + c_idx * n; 60 | distribute_idx += bs_idx * m + pt_idx; 61 | distribute_feature += bs_idx * c * m + c_idx * m + pt_idx; 62 | 63 | int idx = distribute_idx[0]; 64 | distribute_feature[0] = max_feature[idx]; 65 | } 66 | 67 | 68 | void featuregather_forward_cuda_launcher(int b, int n, int m, int c, const float *max_feature, const int *distribute_idx, float *distribute_feature, cudaStream_t stream){ 69 | // param max_feature: (b, c, n) 70 | // param distribute_idx: (b, m) 71 | // return distribute_feature: (b, c, m) 72 | 73 | cudaError_t err; 74 | 75 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), c, b); // blockIdx.x(col), blockIdx.y(row) 76 | dim3 threads(THREADS_PER_BLOCK); 77 | 78 | featuregather_forward_cuda_kernel<<>>(b, n, m, c, max_feature, distribute_idx, distribute_feature); 79 | // cudaDeviceSynchronize(); // for using printf in kernel function 80 | 81 | err = cudaGetLastError(); 82 | if (cudaSuccess != err) { 83 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 84 | exit(-1); 85 | } 86 | } 87 | 88 | 89 | __global__ void featuregather_backward_cuda_kernel(int b, int n, int m, int c, const float *grad_distribute_feature, const int *distribute_idx, float *grad_max_feature){ 90 | int bs_idx = blockIdx.z; 91 | int c_idx = blockIdx.y; 92 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 93 | if(bs_idx >= b || c_idx >= c || pt_idx >= m) return; 94 | 95 | grad_distribute_feature += bs_idx * c * m + c_idx * m + pt_idx; 96 | distribute_idx += bs_idx * m + pt_idx; 97 | grad_max_feature += bs_idx * c * n + c_idx * n; 98 | 99 | int idx = distribute_idx[0]; 100 | atomicAdd(grad_max_feature + idx, grad_distribute_feature[0]); 101 | } 102 | 103 | 104 | void featuregather_backward_cuda_launcher(int b, int n, int m, int c, const float *grad_distribute_feature, const int *distribute_idx, float *grad_max_feature, cudaStream_t stream){ 105 | // param grad_distribute_feature: (b, c, m) 106 | // param distribute_idx: (b, m) 107 | // return grad_max_feature: (b, c, n) 108 | 109 | cudaError_t err; 110 | 111 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), c, b); // blockIdx.x(col), blockIdx.y(row) 112 | dim3 threads(THREADS_PER_BLOCK); 113 | 114 | featuregather_backward_cuda_kernel<<>>(b, n, m, c, grad_distribute_feature, distribute_idx, grad_max_feature); 115 | // cudaDeviceSynchronize(); // for using printf in kernel function 116 | 117 | err = cudaGetLastError(); 118 | if (cudaSuccess != err) { 119 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 120 | exit(-1); 121 | } 122 | } -------------------------------------------------------------------------------- /lib/pointops/src/featuredistribute/featuredistribute_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _FEATUREDISTRIBUTE_CUDA_KERNEL 2 | #define _FEATUREDISTRIBUTE_CUDA_KERNEL 3 | #include 4 | #include 5 | #include 6 | 7 | void featuredistribute_cuda(int b, int n, int m, at::Tensor max_xyz_tensor, at::Tensor xyz_tensor, at::Tensor distribute_idx_tensor); 8 | void featuregather_forward_cuda(int b, int n, int m, int c, at::Tensor max_feature_tensor, at::Tensor distribute_idx_tensor, at::Tensor distribute_feature_tensor); 9 | void featuregather_backward_cuda(int b, int n, int m, int c, at::Tensor grad_distribute_feature_tensor, at::Tensor distribute_idx_tensor, at::Tensor grad_max_feature_tensor); 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | void featuredistribute_cuda_launcher(int b, int n, int m, const float *max_xyz, const float *xyz, int *distribute_idx, cudaStream_t stream); 16 | void featuregather_forward_cuda_launcher(int b, int n, int m, int c, const float *max_feature, const int *distribute_idx, float *distribute_feature, cudaStream_t stream); 17 | void featuregather_backward_cuda_launcher(int b, int n, int m, int c, const float *grad_distribute_feature, const int *distribute_idx, float *grad_max_feature, cudaStream_t stream); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /lib/pointops/src/grouping/grouping_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "grouping_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | void grouping_forward_cuda(int b, int c, int n, int m, int nsample, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor) 11 | { 12 | const float *points = points_tensor.data(); 13 | const int *idx = idx_tensor.data(); 14 | float *out = out_tensor.data(); 15 | grouping_forward_cuda_launcher(b, c, n, m, nsample, points, idx, out); 16 | } 17 | 18 | void grouping_backward_cuda(int b, int c, int n, int m, int nsample, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor) 19 | { 20 | float *grad_points = grad_points_tensor.data(); 21 | const int *idx = idx_tensor.data(); 22 | const float *grad_out = grad_out_tensor.data(); 23 | grouping_backward_cuda_launcher(b, c, n, m, nsample, grad_out, idx, grad_points); 24 | } 25 | 26 | void grouping_forward_cuda_fast(int b, int c, int n, int npoints, int nsample, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor) { 27 | 28 | const float *points = points_tensor.data(); 29 | const int *idx = idx_tensor.data(); 30 | float *out = out_tensor.data(); 31 | grouping_forward_cuda_launcher_fast(b, c, n, npoints, nsample, points, idx, out); 32 | } -------------------------------------------------------------------------------- /lib/pointops/src/grouping/grouping_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "grouping_cuda_kernel.h" 3 | 4 | // input: points(b, c, n) idx(b, m, nsample) 5 | // output: out(b, c, m, nsample) 6 | __global__ void grouping_forward_cuda_kernel(int b, int c, int n, int m, int nsample, const float *points, const int *idx, float *out) 7 | { 8 | int batch_index = blockIdx.x; 9 | points += batch_index * n * c; 10 | idx += batch_index * m * nsample; 11 | out += batch_index * m * nsample * c; 12 | const int index = threadIdx.y * blockDim.x + threadIdx.x; 13 | const int stride = blockDim.y * blockDim.x; 14 | for (int i = index; i < c * m; i += stride) 15 | { 16 | const int l = i / m; 17 | const int j = i % m; 18 | for (int k = 0; k < nsample; ++k) 19 | { 20 | int ii = idx[j * nsample + k]; 21 | out[(l * m + j) * nsample + k] = points[l * n + ii]; 22 | } 23 | } 24 | } 25 | 26 | // input: grad_out(b, c, m, nsample), idx(b, m, nsample) 27 | // output: grad_points(b, c, n) 28 | __global__ void grouping_backward_cuda_kernel(int b, int c, int n, int m, int nsample, const float *grad_out, const int *idx, float *grad_points) 29 | { 30 | int batch_index = blockIdx.x; 31 | grad_out += batch_index * m * nsample * c; 32 | idx += batch_index * m * nsample; 33 | grad_points += batch_index * n * c; 34 | const int index = threadIdx.y * blockDim.x + threadIdx.x; 35 | const int stride = blockDim.y * blockDim.x; 36 | for (int i = index; i < c * m; i += stride) 37 | { 38 | const int l = i / m; 39 | const int j = i % m; 40 | for (int k = 0; k < nsample; ++k) 41 | { 42 | int ii = idx[j * nsample + k]; 43 | atomicAdd(grad_points + l * n + ii, grad_out[(l * m + j) * nsample + k]); 44 | } 45 | } 46 | } 47 | 48 | void grouping_forward_cuda_launcher(int b, int c, int n, int m, int nsample, const float *points, const int *idx, float *out) 49 | { 50 | grouping_forward_cuda_kernel<<>>(b, c, n, m, nsample, points, idx, out); 51 | } 52 | 53 | void grouping_backward_cuda_launcher(int b, int c, int n, int m, int nsample, const float *grad_out, const int *idx, float *grad_points) 54 | { 55 | grouping_backward_cuda_kernel<<>>(b, c, n, m, nsample, grad_out, idx, grad_points); 56 | } 57 | 58 | // input: points(b, c, n) idx(b, npoints, nsample) 59 | // output: out(b, c, npoints, nsample) 60 | __global__ void grouping_forward_cuda_kernel_fast(int b, int c, int n, int npoints, int nsample, const float *__restrict__ points, const int *__restrict__ idx, float *__restrict__ out) { 61 | int bs_idx = blockIdx.z; 62 | int c_idx = blockIdx.y; 63 | int index = blockIdx.x * blockDim.x + threadIdx.x; 64 | int pt_idx = index / nsample; 65 | if (bs_idx >= b || c_idx >= c || pt_idx >= npoints) return; 66 | 67 | int sample_idx = index % nsample; 68 | 69 | idx += bs_idx * npoints * nsample + pt_idx * nsample + sample_idx; 70 | int in_idx = bs_idx * c * n + c_idx * n + idx[0]; 71 | int out_idx = bs_idx * c * npoints * nsample + c_idx * npoints * nsample + pt_idx * nsample + sample_idx; 72 | 73 | out[out_idx] = points[in_idx]; 74 | } 75 | 76 | // input: points(b, c, n) idx(b, npoints, nsample) 77 | // output: out(b, c, npoints, nsample) 78 | void grouping_forward_cuda_launcher_fast(int b, int c, int n, int npoints, int nsample, const float *points, const int *idx, float *out) { 79 | 80 | cudaError_t err; 81 | 82 | dim3 blocks(DIVUP(npoints * nsample, THREADS_PER_BLOCK), c, b); // blockIdx.x(col), blockIdx.y(row) 83 | dim3 threads(THREADS_PER_BLOCK); 84 | 85 | grouping_forward_cuda_kernel_fast<<>>(b, c, n, npoints, nsample, points, idx, out); 86 | // cudaDeviceSynchronize(); // for using printf in kernel function 87 | err = cudaGetLastError(); 88 | if (cudaSuccess != err) { 89 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 90 | exit(-1); 91 | } 92 | } 93 | 94 | 95 | -------------------------------------------------------------------------------- /lib/pointops/src/grouping/grouping_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _GROUPING_CUDA_KERNEL 2 | #define _GROUPING_CUDA_KERNEL 3 | #include 4 | #include 5 | #include 6 | 7 | void grouping_forward_cuda(int b, int c, int n, int m, int nsample, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out); 8 | void grouping_backward_cuda(int b, int c, int n, int m, int nsample, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor); 9 | 10 | void grouping_forward_cuda_fast(int b, int c, int n, int npoints, int nsample, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor); 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void grouping_forward_cuda_launcher(int b, int c, int n, int m, int nsample, const float *points, const int *idx, float *out); 17 | void grouping_backward_cuda_launcher(int b, int c, int n, int m, int nsample, const float *grad_out, const int *idx, float *grad_points); 18 | 19 | void grouping_forward_cuda_launcher_fast(int b, int c, int n, int npoints, int nsample, const float *points, const int *idx, float *out); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | #endif 25 | -------------------------------------------------------------------------------- /lib/pointops/src/grouping_int/grouping_int_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "grouping_int_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | void grouping_int_forward_cuda(int b, int c, int n, int m, int nsample, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor) 11 | { 12 | const long int *points = points_tensor.data(); 13 | const int *idx = idx_tensor.data(); 14 | long int *out = out_tensor.data(); 15 | grouping_int_forward_cuda_launcher(b, c, n, m, nsample, points, idx, out); 16 | } 17 | 18 | void grouping_int_forward_cuda_fast(int b, int c, int n, int m, int nsample, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor) 19 | { 20 | const long int *points = points_tensor.data(); 21 | const int *idx = idx_tensor.data(); 22 | long int *out = out_tensor.data(); 23 | grouping_int_forward_cuda_launcher_fast(b, c, n, m, nsample, points, idx, out); 24 | } -------------------------------------------------------------------------------- /lib/pointops/src/grouping_int/grouping_int_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "grouping_int_cuda_kernel.h" 3 | 4 | // input: points(b, c, n) idx(b, m, nsample) 5 | // output: out(b, c, m, nsample) 6 | __global__ void grouping_int_forward_cuda_kernel(int b, int c, int n, int m, int nsample, const long int *points, const int *idx, long int *out) 7 | { 8 | int batch_index = blockIdx.x; 9 | points += batch_index * n * c; 10 | idx += batch_index * m * nsample; 11 | out += batch_index * m * nsample * c; 12 | const int index = threadIdx.y * blockDim.x + threadIdx.x; 13 | const int stride = blockDim.y * blockDim.x; 14 | for (int i = index; i < c * m; i += stride) 15 | { 16 | const int l = i / m; 17 | const int j = i % m; 18 | for (int k = 0; k < nsample; ++k) 19 | { 20 | int ii = idx[j * nsample + k]; 21 | out[(l * m + j) * nsample + k] = points[l * n + ii]; 22 | } 23 | } 24 | } 25 | 26 | 27 | void grouping_int_forward_cuda_launcher(int b, int c, int n, int m, int nsample, const long int *points, const int *idx, long int *out) 28 | { 29 | grouping_int_forward_cuda_kernel<<>>(b, c, n, m, nsample, points, idx, out); 30 | } 31 | 32 | 33 | __global__ void grouping_int_forward_cuda_kernel_fast(int b, int c, int n, int npoints, int nsample, const long int *__restrict__ points, const int *__restrict__ idx, long int *__restrict__ out) 34 | { 35 | int bs_idx = blockIdx.z; 36 | int c_idx = blockIdx.y; 37 | int index = blockIdx.x * blockDim.x + threadIdx.x; 38 | int pt_idx = index / nsample; 39 | if (bs_idx >= b || c_idx >= c || pt_idx >= npoints) return; 40 | 41 | int sample_idx = index % nsample; 42 | 43 | idx += bs_idx * npoints * nsample + pt_idx * nsample + sample_idx; 44 | int in_idx = bs_idx * c * n + c_idx * n + idx[0]; 45 | int out_idx = bs_idx * c * npoints * nsample + c_idx * npoints * nsample + pt_idx * nsample + sample_idx; 46 | 47 | out[out_idx] = points[in_idx]; 48 | } 49 | 50 | 51 | void grouping_int_forward_cuda_launcher_fast(int b, int c, int n, int npoints, int nsample, const long int *points, const int *idx, long int *out) 52 | { 53 | cudaError_t err; 54 | 55 | dim3 blocks(DIVUP(npoints * nsample, THREADS_PER_BLOCK), c, b); // blockIdx.x(col), blockIdx.y(row) 56 | dim3 threads(THREADS_PER_BLOCK); 57 | 58 | grouping_int_forward_cuda_kernel_fast<<>>(b, c, n, npoints, nsample, points, idx, out); 59 | // cudaDeviceSynchronize(); // for using printf in kernel function 60 | err = cudaGetLastError(); 61 | if (cudaSuccess != err) { 62 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 63 | exit(-1); 64 | } 65 | } -------------------------------------------------------------------------------- /lib/pointops/src/grouping_int/grouping_int_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _GROUPING_INT_CUDA_KERNEL 2 | #define _GROUPING_INT_CUDA_KERNEL 3 | #include 4 | #include 5 | #include 6 | 7 | void grouping_int_forward_cuda(int b, int c, int n, int m, int nsample, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out); 8 | 9 | void grouping_int_forward_cuda_fast(int b, int c, int n, int m, int nsample, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor); 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | void grouping_int_forward_cuda_launcher(int b, int c, int n, int m, int nsample, const long int *points, const int *idx, long int *out); 16 | 17 | void grouping_int_forward_cuda_launcher_fast(int b, int c, int n, int npoints, int nsample, const long int *points, const int *idx, long int *out); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | #endif 23 | -------------------------------------------------------------------------------- /lib/pointops/src/interpolation/interpolation_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "interpolation_cuda_kernel.h" 6 | 7 | extern THCState *state; 8 | 9 | void nearestneighbor_cuda(int b, int n, int m, at::Tensor unknown_tensor, at::Tensor known_tensor, at::Tensor dist2_tensor, at::Tensor idx_tensor) 10 | { 11 | const float *unknown = unknown_tensor.data(); 12 | const float *known = known_tensor.data(); 13 | float *dist2 = dist2_tensor.data(); 14 | int *idx = idx_tensor.data(); 15 | nearestneighbor_cuda_launcher(b, n, m, unknown, known, dist2, idx); 16 | } 17 | 18 | void interpolation_forward_cuda(int b, int c, int m, int n, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor out_tensor) 19 | { 20 | const float *points = points_tensor.data(); 21 | const float *weight = weight_tensor.data(); 22 | float *out = out_tensor.data(); 23 | const int *idx = idx_tensor.data(); 24 | interpolation_forward_cuda_launcher(b, c, m, n, points, idx, weight, out); 25 | } 26 | 27 | void interpolation_backward_cuda(int b, int c, int n, int m, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor grad_points_tensor) 28 | { 29 | const float *grad_out = grad_out_tensor.data(); 30 | const float *weight = weight_tensor.data(); 31 | float *grad_points = grad_points_tensor.data(); 32 | const int *idx = idx_tensor.data(); 33 | interpolation_backward_cuda_launcher(b, c, n, m, grad_out, idx, weight, grad_points); 34 | } 35 | 36 | void nearestneighbor_cuda_fast(int b, int n, int m, at::Tensor unknown_tensor, at::Tensor known_tensor, at::Tensor dist2_tensor, at::Tensor idx_tensor) { 37 | const float *unknown = unknown_tensor.data(); 38 | const float *known = known_tensor.data(); 39 | float *dist2 = dist2_tensor.data(); 40 | int *idx = idx_tensor.data(); 41 | nearestneighbor_cuda_launcher_fast(b, n, m, unknown, known, dist2, idx); 42 | } 43 | 44 | void interpolation_forward_cuda_fast(int b, int c, int m, int n, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor out_tensor) { 45 | 46 | const float *points = points_tensor.data(); 47 | const float *weight = weight_tensor.data(); 48 | float *out = out_tensor.data(); 49 | const int *idx = idx_tensor.data(); 50 | interpolation_forward_cuda_launcher_fast(b, c, m, n, points, idx, weight, out); 51 | } -------------------------------------------------------------------------------- /lib/pointops/src/interpolation/interpolation_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "interpolation_cuda_kernel.h" 3 | 4 | // input: unknown(b, n, 3) known(b, m, 3) 5 | // output: dist2(b, n, 3), idx(b, n, 3) 6 | __global__ void nearestneighbor_cuda_kernel(int b, int n, int m, const float *unknown, const float *known, float *dist2, int *idx) 7 | { 8 | int batch_index = blockIdx.x; 9 | unknown += batch_index * n * 3; 10 | known += batch_index * m * 3; 11 | dist2 += batch_index * n * 3; 12 | idx += batch_index * n * 3; 13 | 14 | int index = threadIdx.x; 15 | int stride = blockDim.x; 16 | for (int j = index; j < n; j += stride) 17 | { 18 | float ux = unknown[j * 3 + 0]; 19 | float uy = unknown[j * 3 + 1]; 20 | float uz = unknown[j * 3 + 2]; 21 | 22 | double best1 = 1e40, best2 = 1e40, best3 = 1e40; 23 | int besti1 = 0, besti2 = 0, besti3 = 0; 24 | for (int k = 0; k < m; ++k) 25 | { 26 | float x = known[k * 3 + 0]; 27 | float y = known[k * 3 + 1]; 28 | float z = known[k * 3 + 2]; 29 | float d = 30 | (ux - x) * (ux - x) + (uy - y) * (uy - y) + (uz - z) * (uz - z); 31 | if (d < best1) 32 | { 33 | best3 = best2; 34 | besti3 = besti2; 35 | best2 = best1; 36 | besti2 = besti1; 37 | best1 = d; 38 | besti1 = k; 39 | } 40 | else if (d < best2) 41 | { 42 | best3 = best2; 43 | besti3 = besti2; 44 | best2 = d; 45 | besti2 = k; 46 | } 47 | else if (d < best3) 48 | { 49 | best3 = d; 50 | besti3 = k; 51 | } 52 | } 53 | dist2[j * 3 + 0] = best1; 54 | dist2[j * 3 + 1] = best2; 55 | dist2[j * 3 + 2] = best3; 56 | idx[j * 3 + 0] = besti1; 57 | idx[j * 3 + 1] = besti2; 58 | idx[j * 3 + 2] = besti3; 59 | } 60 | } 61 | 62 | // input: points(b, c, m), idx(b, n, 3), weight(b, n, 3) 63 | // output: out(b, c, n) 64 | __global__ void interpolation_forward_cuda_kernel(int b, int c, int m, int n, const float *points, const int *idx, const float *weight, float *out) 65 | { 66 | int batch_index = blockIdx.x; 67 | points += batch_index * m * c; 68 | idx += batch_index * n * 3; 69 | weight += batch_index * n * 3; 70 | out += batch_index * n * c; 71 | 72 | const int index = threadIdx.y * blockDim.x + threadIdx.x; 73 | const int stride = blockDim.y * blockDim.x; 74 | for (int i = index; i < c * n; i += stride) 75 | { 76 | const int l = i / n; 77 | const int j = i % n; 78 | float w1 = weight[j * 3 + 0]; 79 | float w2 = weight[j * 3 + 1]; 80 | float w3 = weight[j * 3 + 2]; 81 | int i1 = idx[j * 3 + 0]; 82 | int i2 = idx[j * 3 + 1]; 83 | int i3 = idx[j * 3 + 2]; 84 | out[i] = points[l * m + i1] * w1 + points[l * m + i2] * w2 + points[l * m + i3] * w3; 85 | } 86 | } 87 | 88 | // input: grad_out(b, c, n), idx(b, n, 3), weight(b, n, 3) 89 | // output: grad_points(b, c, m) 90 | __global__ void interpolation_backward_cuda_kernel( int b, int c, int n, int m, const float *grad_out, const int *idx, const float *weight, float *grad_points) 91 | { 92 | int batch_index = blockIdx.x; 93 | grad_out += batch_index * n * c; 94 | idx += batch_index * n * 3; 95 | weight += batch_index * n * 3; 96 | grad_points += batch_index * m * c; 97 | 98 | const int index = threadIdx.y * blockDim.x + threadIdx.x; 99 | const int stride = blockDim.y * blockDim.x; 100 | for (int i = index; i < c * n; i += stride) 101 | { 102 | const int l = i / n; 103 | const int j = i % n; 104 | float w1 = weight[j * 3 + 0]; 105 | float w2 = weight[j * 3 + 1]; 106 | float w3 = weight[j * 3 + 2]; 107 | int i1 = idx[j * 3 + 0]; 108 | int i2 = idx[j * 3 + 1]; 109 | int i3 = idx[j * 3 + 2]; 110 | atomicAdd(grad_points + l * m + i1, grad_out[i] * w1); 111 | atomicAdd(grad_points + l * m + i2, grad_out[i] * w2); 112 | atomicAdd(grad_points + l * m + i3, grad_out[i] * w3); 113 | } 114 | } 115 | 116 | void nearestneighbor_cuda_launcher(int b, int n, int m, const float *unknown, const float *known, float *dist2, int *idx) 117 | { 118 | nearestneighbor_cuda_kernel<<>>(b, n, m, unknown, known, dist2, idx); 119 | } 120 | 121 | void interpolation_forward_cuda_launcher(int b, int c, int m, int n, const float *points, const int *idx, const float *weight, float *out) 122 | { 123 | interpolation_forward_cuda_kernel<<>>(b, c, m, n, points, idx, weight, out); 124 | } 125 | 126 | void interpolation_backward_cuda_launcher(int b, int n, int c, int m, const float *grad_out, const int *idx, const float *weight, float *grad_points) 127 | { 128 | interpolation_backward_cuda_kernel<<>>(b, n, c, m, grad_out, idx, weight, grad_points); 129 | } 130 | 131 | 132 | // input: unknown(b, n, 3) known(b, m, 3) 133 | // output: dist2(b, n, 3), idx(b, n, 3) 134 | __global__ void nearestneighbor_cuda_kernel_fast(int b, int n, int m, const float *__restrict__ unknown, const float *__restrict__ known, float *__restrict__ dist2, int *__restrict__ idx) { 135 | 136 | int bs_idx = blockIdx.y; 137 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 138 | if (bs_idx >= b || pt_idx >= n) return; 139 | 140 | unknown += bs_idx * n * 3 + pt_idx * 3; 141 | known += bs_idx * m * 3; 142 | dist2 += bs_idx * n * 3 + pt_idx * 3; 143 | idx += bs_idx * n * 3 + pt_idx * 3; 144 | 145 | float ux = unknown[0]; 146 | float uy = unknown[1]; 147 | float uz = unknown[2]; 148 | 149 | double best1 = 1e40, best2 = 1e40, best3 = 1e40; 150 | int besti1 = 0, besti2 = 0, besti3 = 0; 151 | for (int k = 0; k < m; ++k) { 152 | float x = known[k * 3 + 0]; 153 | float y = known[k * 3 + 1]; 154 | float z = known[k * 3 + 2]; 155 | float d = (ux - x) * (ux - x) + (uy - y) * (uy - y) + (uz - z) * (uz - z); 156 | if (d < best1) { 157 | best3 = best2; besti3 = besti2; 158 | best2 = best1; besti2 = besti1; 159 | best1 = d; besti1 = k; 160 | } 161 | else if (d < best2) { 162 | best3 = best2; besti3 = besti2; 163 | best2 = d; besti2 = k; 164 | } 165 | else if (d < best3) { 166 | best3 = d; besti3 = k; 167 | } 168 | } 169 | dist2[0] = best1; 170 | dist2[1] = best2; 171 | dist2[2] = best3; 172 | 173 | idx[0] = besti1; 174 | idx[1] = besti2; 175 | idx[2] = besti3; 176 | } 177 | 178 | 179 | // input: points(b, c, m), idx(b, n, 3), weight(b, n, 3) 180 | // output: out(b, c, n) 181 | __global__ void interpolation_forward_cuda_kernel_fast(int b, int c, int m, int n, const float *__restrict__ points, const int *__restrict__ idx, const float *__restrict__ weight, float *__restrict__ out) { 182 | 183 | int bs_idx = blockIdx.z; 184 | int c_idx = blockIdx.y; 185 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 186 | 187 | if (bs_idx >= b || c_idx >= c || pt_idx >= n) return; 188 | 189 | weight += bs_idx * n * 3 + pt_idx * 3; 190 | points += bs_idx * c * m + c_idx * m; 191 | idx += bs_idx * n * 3 + pt_idx * 3; 192 | out += bs_idx * c * n + c_idx * n; 193 | 194 | out[pt_idx] = weight[0] * points[idx[0]] + weight[1] * points[idx[1]] + weight[2] * points[idx[2]]; 195 | } 196 | 197 | 198 | void nearestneighbor_cuda_launcher_fast(int b, int n, int m, const float *unknown, const float *known, float *dist2, int *idx) 199 | { 200 | cudaError_t err; 201 | 202 | dim3 blocks(DIVUP(n, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 203 | dim3 threads(THREADS_PER_BLOCK); 204 | 205 | nearestneighbor_cuda_kernel_fast<<>>(b, n, m, unknown, known, dist2, idx); 206 | 207 | err = cudaGetLastError(); 208 | if (cudaSuccess != err) { 209 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 210 | exit(-1); 211 | } 212 | } 213 | 214 | void interpolation_forward_cuda_launcher_fast(int b, int c, int m, int n, const float *points, const int *idx, const float *weight, float *out) { 215 | 216 | cudaError_t err; 217 | 218 | dim3 blocks(DIVUP(n, THREADS_PER_BLOCK), c, b); // blockIdx.x(col), blockIdx.y(row) 219 | dim3 threads(THREADS_PER_BLOCK); 220 | interpolation_forward_cuda_kernel_fast<<>>(b, c, m, n, points, idx, weight, out); 221 | 222 | err = cudaGetLastError(); 223 | if (cudaSuccess != err) { 224 | fprintf(stderr, "CUDA kernel failed : %s\n", 225 | cudaGetErrorString(err)); 226 | exit(-1); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /lib/pointops/src/interpolation/interpolation_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _INTERPOLATION_CUDA_KERNEL 2 | #define _INTERPOLATION_CUDA_KERNEL 3 | #include 4 | #include 5 | #include 6 | 7 | void nearestneighbor_cuda(int b, int n, int m, at::Tensor unknown_tensor, at::Tensor known_tensor, at::Tensor dist2_tensor, at::Tensor idx_tensor); 8 | void interpolation_forward_cuda(int b, int c, int m, int n, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor out_tensor); 9 | void interpolation_backward_cuda(int b, int c, int n, int m, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor grad_points_tensor); 10 | 11 | void nearestneighbor_cuda_fast(int b, int n, int m, at::Tensor unknown_tensor, at::Tensor known_tensor, at::Tensor dist2_tensor, at::Tensor idx_tensor); 12 | void interpolation_forward_cuda_fast(int b, int c, int m, int n, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor out_tensor); 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | void nearestneighbor_cuda_launcher(int b, int n, int m, const float *unknown, const float *known, float *dist2, int *idx); 19 | void interpolation_forward_cuda_launcher(int b, int c, int m, int n, const float *points, const int *idx, const float *weight, float *out); 20 | void interpolation_backward_cuda_launcher(int b, int c, int n, int m, const float *grad_out, const int *idx, const float *weight, float *grad_points); 21 | 22 | void nearestneighbor_cuda_launcher_fast(int b, int n, int m, const float *unknown, const float *known, float *dist2, int *idx); 23 | void interpolation_forward_cuda_launcher_fast(int b, int c, int m, int n, const float *points, const int *idx, const float *weight, float *out); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | #endif 29 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquery/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/knnquery/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/knnquery/knnquery_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "knnquery_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void knnquery_cuda(int b, int n, int m, int nsample, at::Tensor xyz_tensor, at::Tensor new_xyz_tensor, at::Tensor idx_tensor, at::Tensor dist2_tensor) 16 | { 17 | CHECK_INPUT(new_xyz_tensor); 18 | CHECK_INPUT(xyz_tensor); 19 | 20 | const float *new_xyz = new_xyz_tensor.data(); 21 | const float *xyz = xyz_tensor.data(); 22 | int *idx = idx_tensor.data(); 23 | float *dist2 = dist2_tensor.data(); 24 | 25 | cudaStream_t stream = THCState_getCurrentStream(state); 26 | 27 | knnquery_cuda_launcher(b, n, m, nsample, xyz, new_xyz, idx, dist2, stream); 28 | } 29 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquery/knnquery_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "knnquery_cuda_kernel.h" 3 | 4 | // input: xyz (b, n, 3) new_xyz (b, m, 3) 5 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 6 | __global__ void knnquery_cuda_kernel(int b, int n, int m, int nsample, const float *__restrict__ xyz, const float *__restrict__ new_xyz, int *__restrict__ idx, float *__restrict__ dist2) { 7 | int bs_idx = blockIdx.y; 8 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 9 | if (bs_idx >= b || pt_idx >= m) return; 10 | 11 | new_xyz += bs_idx * m * 3 + pt_idx * 3; 12 | xyz += bs_idx * n * 3; 13 | idx += bs_idx * m * nsample + pt_idx * nsample; 14 | 15 | float new_x = new_xyz[0]; 16 | float new_y = new_xyz[1]; 17 | float new_z = new_xyz[2]; 18 | 19 | //double* best = new double[nsample]; 20 | //int* besti = new int[nsample]; 21 | double best[200]; 22 | int besti[200]; 23 | for(int i = 0; i < nsample; i++){ 24 | best[i] = 1e40; 25 | besti[i] = 0; 26 | } 27 | for(int k = 0; k < n; k++){ 28 | float x = xyz[k * 3 + 0]; 29 | float y = xyz[k * 3 + 1]; 30 | float z = xyz[k * 3 + 2]; 31 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z); 32 | for(int j = 0; j < nsample; j++){ 33 | if(d2 < best[j]){ 34 | for(int i = nsample - 1; i > j; i--){ 35 | best[i] = best[i - 1]; 36 | besti[i] = besti[i - 1]; 37 | } 38 | best[j] = d2; 39 | besti[j] = k; 40 | break; 41 | } 42 | } 43 | } 44 | for(int i = 0; i < nsample; i++){ 45 | idx[i] = besti[i]; 46 | dist2[i] = best[i]; 47 | } 48 | //delete []best; 49 | //delete []besti; 50 | } 51 | 52 | 53 | void knnquery_cuda_launcher(int b, int n, int m, int nsample, const float *xyz, const float *new_xyz, int *idx, float *dist2, cudaStream_t stream) { 54 | // param new_xyz: (B, m, 3) 55 | // param xyz: (B, n, 3) 56 | // param idx: (B, m, nsample) 57 | 58 | cudaError_t err; 59 | 60 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 61 | dim3 threads(THREADS_PER_BLOCK); 62 | 63 | knnquery_cuda_kernel<<>>(b, n, m, nsample, xyz, new_xyz, idx, dist2); 64 | // cudaDeviceSynchronize(); // for using printf in kernel function 65 | 66 | err = cudaGetLastError(); 67 | if (cudaSuccess != err) { 68 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 69 | exit(-1); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquery/knnquery_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _KNNQUERY_CUDA_KERNEL 2 | #define _KNNQUERY_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void knnquery_cuda(int b, int n, int m, int nsample, at::Tensor xyz_tensor, at::Tensor new_xyz_tensor, at::Tensor idx_tensor, at::Tensor dist2_tensor); 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void knnquery_cuda_launcher(int b, int n, int m, int nsample, const float *xyz, const float *new_xyz, int *idx, float *dist2, cudaStream_t stream); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif -------------------------------------------------------------------------------- /lib/pointops/src/knnquerycluster/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/knnquerycluster/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/knnquerycluster/knnquerycluster_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "knnquerycluster_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | // add xyz_idx_tensor 16 | void knnquerycluster_cuda(int b, int n, int m, int nsample, at::Tensor xyz_tensor, at::Tensor xyz_idx_tensor, at::Tensor new_xyz_tensor, at::Tensor idx_tensor, at::Tensor idx_abs_tensor, at::Tensor dist2_tensor) 17 | { 18 | CHECK_INPUT(new_xyz_tensor); 19 | CHECK_INPUT(xyz_tensor); 20 | CHECK_INPUT(xyz_idx_tensor); // add CHECK_INPUT of xyz_idx_tensor 21 | 22 | const float *new_xyz = new_xyz_tensor.data(); 23 | const float *xyz = xyz_tensor.data(); 24 | int *xyz_idx = xyz_idx_tensor.data(); // add *xyz_idx 25 | int *idx = idx_tensor.data(); 26 | int *idx_abs = idx_abs_tensor.data(); 27 | float *dist2 = dist2_tensor.data(); 28 | 29 | cudaStream_t stream = THCState_getCurrentStream(state); 30 | 31 | knnquerycluster_cuda_launcher(b, n, m, nsample, xyz, xyz_idx, new_xyz, idx, idx_abs, dist2, stream); // add xyz_idx 32 | } 33 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquerycluster/knnquerycluster_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "knnquerycluster_cuda_kernel.h" 3 | 4 | // Note: n is the clusters, m is the points 5 | // Note: m >> n 6 | // Note: nsample <= 200 7 | 8 | // input: xyz (b, n, 3) xyz_idx (b, n) new_xyz (b, m, 3) 9 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 10 | __global__ void knnquerycluster_cuda_kernel(int b, int n, int m, int nsample, const float *__restrict__ xyz, const int *__restrict__ xyz_idx, const float *__restrict__ new_xyz, int *__restrict__ idx, int *__restrict__ idx_abs, float *__restrict__ dist2) { 11 | int bs_idx = blockIdx.y; 12 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 13 | if (bs_idx >= b || pt_idx >= m) return; 14 | 15 | new_xyz += bs_idx * m * 3 + pt_idx * 3; 16 | xyz += bs_idx * n * 3; 17 | xyz_idx += bs_idx * n * 1; // add xyz_idx initial position 18 | idx += bs_idx * m * nsample + pt_idx * nsample; 19 | idx_abs += bs_idx * m * nsample + pt_idx * nsample; 20 | 21 | float new_x = new_xyz[0]; 22 | float new_y = new_xyz[1]; 23 | float new_z = new_xyz[2]; 24 | 25 | //double* best = new double[nsample]; 26 | //int* besti = new int[nsample]; 27 | double best[200]; 28 | int besti[200]; 29 | for(int i = 0; i < nsample; i++) { 30 | best[i] = 1e40; 31 | besti[i] = 0; 32 | } 33 | for(int k = 0; k < n; k++){ 34 | float x = xyz[k * 3 + 0]; 35 | float y = xyz[k * 3 + 1]; 36 | float z = xyz[k * 3 + 2]; 37 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z); 38 | for(int j = 0; j < nsample; j++){ 39 | if(d2 < best[j]){ 40 | for(int i = nsample - 1; i > j; i--){ 41 | best[i] = best[i - 1]; 42 | besti[i] = besti[i - 1]; 43 | } 44 | best[j] = d2; 45 | besti[j] = k; 46 | break; 47 | } 48 | } 49 | } 50 | for(int i = 0; i < nsample; i++){ 51 | //idx[i] = besti[i]; 52 | idx[i] = xyz_idx[besti[i]]; 53 | idx_abs[i] = besti[i]; 54 | dist2[i] = best[i]; 55 | } 56 | //delete []best; 57 | //delete []besti; 58 | } 59 | 60 | 61 | void knnquerycluster_cuda_launcher(int b, int n, int m, int nsample, const float *xyz, const int *xyz_idx, const float *new_xyz, int *idx, int *idx_abs, float *dist2, cudaStream_t stream) { // add xyz_idx 62 | // param new_xyz: (B, m, 3) 63 | // param xyz: (B, n, 3) 64 | // param xyz_idx: (B, n) // add 65 | // param idx: (B, m, nsample) 66 | // param idx_abs: (B, m, nsample) 67 | 68 | cudaError_t err; 69 | 70 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 71 | dim3 threads(THREADS_PER_BLOCK); 72 | 73 | knnquerycluster_cuda_kernel<<>>(b, n, m, nsample, xyz, xyz_idx, new_xyz, idx, idx_abs, dist2); 74 | // cudaDeviceSynchronize(); // for using printf in kernel function 75 | 76 | err = cudaGetLastError(); 77 | if (cudaSuccess != err) { 78 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 79 | exit(-1); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquerycluster/knnquerycluster_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _KNNQUERYCLUSTER_CUDA_KERNEL 2 | #define _KNNQUERYCLUSTER_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void knnquerycluster_cuda(int b, int n, int m, int nsample, at::Tensor xyz_tensor, at::Tensor xyz_idx_tensor, at::Tensor new_xyz_tensor, at::Tensor idx_tensor, at::Tensor idx_abs_tensor, at::Tensor dist2_tensor); // add xyz_idx_tensor 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void knnquerycluster_cuda_launcher(int b, int n, int m, int nsample, const float *xyz, const int *xyz_idx, const float *new_xyz, int *idx, int *idx_abs, float *dist2, cudaStream_t stream); // add *xyz_idx 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/pointops/src/knnqueryclustergt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/knnqueryclustergt/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/knnqueryclustergt/knnqueryclustergt_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "knnqueryclustergt_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | // add xyz_idx_tensor 16 | void knnqueryclustergt_cuda(int b, int n, int m, int nsample, at::Tensor xyz_tensor, at::Tensor xyz_idx_tensor, at::Tensor xyz_gt_tensor, at::Tensor new_xyz_tensor, at::Tensor new_xyz_gt_tensor, at::Tensor idx_tensor, at::Tensor idx_abs_tensor, at::Tensor idx_gt_tensor, at::Tensor idx_gt_abs_tensor, at::Tensor dist2_tensor) 17 | { 18 | CHECK_INPUT(new_xyz_tensor); 19 | CHECK_INPUT(xyz_tensor); 20 | CHECK_INPUT(xyz_idx_tensor); // add CHECK_INPUT of xyz_idx_tensor 21 | 22 | const float *new_xyz = new_xyz_tensor.data(); 23 | const float *xyz = xyz_tensor.data(); 24 | int *xyz_idx = xyz_idx_tensor.data(); // add *xyz_idx 25 | 26 | int *xyz_gt = xyz_gt_tensor.data(); // add *xyz_gt 27 | int *new_xyz_gt = new_xyz_gt_tensor.data(); // add *new_xyz_gt 28 | 29 | int *idx = idx_tensor.data(); 30 | int *idx_abs = idx_abs_tensor.data(); 31 | int *idx_gt = idx_gt_tensor.data(); 32 | int *idx_gt_abs = idx_gt_abs_tensor.data(); 33 | float *dist2 = dist2_tensor.data(); 34 | 35 | cudaStream_t stream = THCState_getCurrentStream(state); 36 | 37 | knnqueryclustergt_cuda_launcher(b, n, m, nsample, xyz, xyz_idx, xyz_gt, new_xyz, new_xyz_gt, idx, idx_abs, idx_gt, idx_gt_abs, dist2, stream); // add xyz_idx 38 | } 39 | -------------------------------------------------------------------------------- /lib/pointops/src/knnqueryclustergt/knnqueryclustergt_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "knnqueryclustergt_cuda_kernel.h" 3 | 4 | // Note: n is the clusters, m is the points 5 | // Note: m >> n 6 | // Note: nsample <= 200 7 | 8 | // input: xyz (b, n, 3) xyz_idx (b, n) xyz_gt (b, n) new_xyz (b, m, 3) new_xyz_gt (b, m, 1) 9 | // output: idx (b, m, nsample) idx_abs (b, m, nsample) idx_gt (b, m, 1) idx_gt_abs (b, m, 1) dist2 (b, m, nsample) 10 | __global__ void knnqueryclustergt_cuda_kernel(int b, int n, int m, int nsample, const float *__restrict__ xyz, const int *__restrict__ xyz_idx, const int *__restrict__ xyz_gt, const float *__restrict__ new_xyz, const int *__restrict__ new_xyz_gt, int *__restrict__ idx, int *__restrict__ idx_abs, int *__restrict__ idx_gt, int *__restrict__ idx_gt_abs, float *__restrict__ dist2) { 11 | int bs_idx = blockIdx.y; 12 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 13 | if (bs_idx >= b || pt_idx >= m) return; 14 | 15 | new_xyz += bs_idx * m * 3 + pt_idx * 3; 16 | xyz += bs_idx * n * 3; 17 | xyz_idx += bs_idx * n * 1; // add xyz_idx initial position 18 | xyz_gt += bs_idx * n * 1; // add xyz_gt initial position 19 | new_xyz_gt += bs_idx * m * 1 + pt_idx * 1; // add new_xyz_gt initial position 20 | idx += bs_idx * m * nsample + pt_idx * nsample; 21 | idx_abs += bs_idx * m * nsample + pt_idx * nsample; 22 | idx_gt += bs_idx * m * 1 + pt_idx * 1; 23 | idx_gt_abs += bs_idx * m * 1 + pt_idx * 1; 24 | 25 | float new_x = new_xyz[0]; 26 | float new_y = new_xyz[1]; 27 | float new_z = new_xyz[2]; 28 | int now_gt = new_xyz_gt[0]; 29 | 30 | //double* best = new double[nsample]; 31 | //int* besti = new int[nsample]; 32 | double best[200]; 33 | int besti_abs[200]; 34 | int besti_gt[200]; 35 | for(int i = 0; i < nsample; i++){ 36 | best[i] = 1e40; 37 | besti_abs[i] = 0; 38 | besti_gt[i] = 0; 39 | } 40 | for(int k = 0; k < n; k++){ 41 | float x = xyz[k * 3 + 0]; 42 | float y = xyz[k * 3 + 1]; 43 | float z = xyz[k * 3 + 2]; 44 | int tmp_gt = xyz_gt[k]; 45 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z); 46 | for(int j = 0; j < nsample; j++){ 47 | if(d2 < best[j]){ 48 | for(int i = nsample - 1; i > j; i--){ 49 | best[i] = best[i - 1]; 50 | besti_abs[i] = besti_abs[i - 1]; 51 | besti_gt[i] = besti_gt[i - 1]; 52 | } 53 | best[j] = d2; 54 | besti_abs[j] = k; 55 | besti_gt[j] = tmp_gt; 56 | break; 57 | } 58 | } 59 | } 60 | 61 | int flag = 0; 62 | int tmp = -1; 63 | for(int i = 0; i < nsample; i++){ 64 | //idx[i] = besti_abs[i]; 65 | idx[i] = xyz_idx[besti_abs[i]]; 66 | idx_abs[i] = besti_abs[i]; 67 | dist2[i] = best[i]; 68 | if (tmp == -1) { 69 | tmp = besti_gt[i]; 70 | } else if (tmp != -2 && besti_gt[i] != tmp){ 71 | tmp = -2; 72 | } 73 | 74 | if (flag == 1) continue; 75 | if (besti_gt[i] == now_gt) { 76 | flag = 1; 77 | idx_gt[0] = idx[i]; 78 | //idx_gt_abs[0] = i; 79 | } 80 | } 81 | if (flag == 0) { // may not exist gt due to the superpoints rates 82 | idx_gt[0] = idx[0]; 83 | idx_gt_abs[0] = 0; 84 | } 85 | if (tmp == -2) { 86 | idx_gt_abs[0] = 1; 87 | } else { 88 | idx_gt_abs[0] = 0; 89 | } 90 | 91 | //delete []best; 92 | //delete []besti; 93 | } 94 | 95 | 96 | void knnqueryclustergt_cuda_launcher(int b, int n, int m, int nsample, const float *xyz, const int *xyz_idx, const int *xyz_gt, const float *new_xyz, const int *new_xyz_gt, int *idx, int *idx_abs, int *idx_gt, int *idx_gt_abs, float *dist2, cudaStream_t stream) { 97 | // param xyz: (B, n, 3) 98 | // param xyz_idx: (B, n) // add 99 | // param xyz_gt: (B, n) // add 100 | // param new_xyz: (B, m, 3) 101 | // param new_xyz_gt: (B, m, 1) // add 102 | // param idx: (B, m, nsample) 103 | // param idx_abs: (B, m, nsample) 104 | // param idx_gt: (B, m, 1) 105 | 106 | cudaError_t err; 107 | 108 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 109 | dim3 threads(THREADS_PER_BLOCK); 110 | 111 | knnqueryclustergt_cuda_kernel<<>>(b, n, m, nsample, xyz, xyz_idx, xyz_gt, new_xyz, new_xyz_gt, idx, idx_abs, idx_gt, idx_gt_abs, dist2); 112 | // cudaDeviceSynchronize(); // for using printf in kernel function 113 | 114 | err = cudaGetLastError(); 115 | if (cudaSuccess != err) { 116 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 117 | exit(-1); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /lib/pointops/src/knnqueryclustergt/knnqueryclustergt_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _KNNQUERYCLUSTERGT_CUDA_KERNEL 2 | #define _KNNQUERYCLUSTERGT_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void knnqueryclustergt_cuda(int b, int n, int m, int nsample, at::Tensor xyz_tensor, at::Tensor xyz_idx_tensor, at::Tensor xyz_gt_tensor, at::Tensor new_xyz_tensor, at::Tensor new_xyz_gt_tensor, at::Tensor idx_tensor, at::Tensor idx_abs_tensor, at::Tensor idx_gt_tensor, at::Tensor idx_gt_abs_tensor, at::Tensor dist2_tensor); // add xyz_idx_tensor 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void knnqueryclustergt_cuda_launcher(int b, int n, int m, int nsample, const float *xyz, const int *xyz_idx, const int *xyz_gt, const float *new_xyz, const int *new_xyz_gt, int *idx, int *idx_abs, int *idx_gt, int *idx_gt_abs, float *dist2, cudaStream_t stream); // add *xyz_idx 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquerydilate/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/knnquerydilate/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/knnquerydilate/knnquerydilate_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "knnquerydilate_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void knnquerydilate_cuda(int b, int n, int m, int nsample, int select, at::Tensor xyz_tensor, at::Tensor new_xyz_tensor, at::Tensor idx_tensor, at::Tensor dist2_tensor) 16 | { 17 | CHECK_INPUT(new_xyz_tensor); 18 | CHECK_INPUT(xyz_tensor); 19 | 20 | const float *new_xyz = new_xyz_tensor.data(); 21 | const float *xyz = xyz_tensor.data(); 22 | int *idx = idx_tensor.data(); 23 | float *dist2 = dist2_tensor.data(); 24 | 25 | cudaStream_t stream = THCState_getCurrentStream(state); 26 | 27 | knnquerydilate_cuda_launcher(b, n, m, nsample, select, xyz, new_xyz, idx, dist2, stream); 28 | } 29 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquerydilate/knnquerydilate_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "knnquerydilate_cuda_kernel.h" 3 | //#include "stdio.h" // le add 4 | //#include "stdlib.h" // le add 5 | //#include "time.h" // le add 6 | //#include "iostream" // le add 7 | //using namespace std; 8 | // input: xyz (b, n, 3) new_xyz (b, m, 3) 9 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 10 | __global__ void knnquerydilate_cuda_kernel(int b, int n, int m, int nsample, int select, const float *__restrict__ xyz, const float *__restrict__ new_xyz, int *__restrict__ idx, float *__restrict__ dist2) { 11 | int bs_idx = blockIdx.y; 12 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 13 | if (bs_idx >= b || pt_idx >= m) return; 14 | 15 | new_xyz += bs_idx * m * 3 + pt_idx * 3; 16 | xyz += bs_idx * n * 3; 17 | idx += bs_idx * m * nsample + pt_idx * nsample; 18 | 19 | float new_x = new_xyz[0]; 20 | float new_y = new_xyz[1]; 21 | float new_z = new_xyz[2]; 22 | 23 | //double* best = new double[nsample]; 24 | //int* besti = new int[nsample]; 25 | double best[200]; 26 | int besti[200]; 27 | for(int i = 0; i < nsample; i++){ 28 | best[i] = 1e40; 29 | besti[i] = 0; 30 | } 31 | for(int k = 0; k < n; k++){ 32 | float x = xyz[k * 3 + 0]; 33 | float y = xyz[k * 3 + 1]; 34 | float z = xyz[k * 3 + 2]; 35 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z); 36 | for(int j = 0; j < nsample; j++){ 37 | if(d2 < best[j]){ 38 | for(int i = nsample - 1; i > j; i--){ 39 | best[i] = best[i - 1]; 40 | besti[i] = besti[i - 1]; 41 | } 42 | best[j] = d2; 43 | besti[j] = k; 44 | break; 45 | } 46 | } 47 | } 48 | srand(time(NULL)); 49 | int ri, tmpi; 50 | double tmp; 51 | for (int i = 0; i < nsample; i++) { 52 | //std::cout << besti[i] << " "; 53 | printf("%d ", besti[i]); 54 | } 55 | //std::cout << std::endl; 56 | printf("\n"); 57 | for (int i = nsample-1; i > 0; i--) { 58 | ri = rand() % i; 59 | tmpi = besti[i]; besti[i] = besti[ri]; besti[ri] = tmpi; 60 | tmp = best[i]; best[i] = best[ri]; best[ri] = tmp; 61 | } 62 | for (int i = 0; i < nsample; i++) { 63 | //std::cout << besti[i] << " "; 64 | printf("%d ", besti[i]); 65 | } 66 | //std::cout << std::endl; 67 | printf("\n"); 68 | 69 | //for(int i = 0; i < nsample; i++){ 70 | for (int i = 0; i < select; i++) { 71 | idx[i] = besti[i]; 72 | dist2[i] = best[i]; 73 | } 74 | //delete []best; 75 | //delete []besti; 76 | } 77 | 78 | 79 | void knnquerydilate_cuda_launcher(int b, int n, int m, int nsample, int select, const float *xyz, const float *new_xyz, int *idx, float *dist2, cudaStream_t stream) { 80 | // param new_xyz: (B, m, 3) 81 | // param xyz: (B, n, 3) 82 | // param idx: (B, m, nsample) 83 | 84 | cudaError_t err; 85 | 86 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 87 | dim3 threads(THREADS_PER_BLOCK); 88 | 89 | knnquerydilate_cuda_kernel<<>>(b, n, m, nsample, select, xyz, new_xyz, idx, dist2); 90 | // cudaDeviceSynchronize(); // for using printf in kernel function 91 | 92 | err = cudaGetLastError(); 93 | if (cudaSuccess != err) { 94 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 95 | exit(-1); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquerydilate/knnquerydilate_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _KNNQUERYDILATE_CUDA_KERNEL 2 | #define _KNNQUERYDILATE_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "stdlib.h" // le add 9 | #include "time.h" // le add 10 | 11 | void knnquerydilate_cuda(int b, int n, int m, int nsample, int select, at::Tensor xyz_tensor, at::Tensor new_xyz_tensor, at::Tensor idx_tensor, at::Tensor dist2_tensor); 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | void knnquerydilate_cuda_launcher(int b, int n, int m, int nsample, int select, const float *xyz, const float *new_xyz, int *idx, float *dist2, cudaStream_t stream); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquerypoint/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/pointops/src/knnquerypoint/__init__.py -------------------------------------------------------------------------------- /lib/pointops/src/knnquerypoint/knnquerypoint_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "knnquerypoint_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | 15 | void knnquerypoint_cuda(int b, int n, int m, int ks, int nsample, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor) // 16 | { 17 | CHECK_INPUT(idx_c_tensor); 18 | CHECK_INPUT(cid_tensor); 19 | 20 | const int *idx_c = idx_c_tensor.data(); 21 | const int *cid = cid_tensor.data(); 22 | int *idx = idx_tensor.data(); 23 | 24 | cudaStream_t stream = THCState_getCurrentStream(state); 25 | 26 | knnquerypoint_cuda_launcher(b, n, m, ks, nsample, idx_c, cid, idx, stream); 27 | } 28 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquerypoint/knnquerypoint_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "knnquerypoint_cuda_kernel.h" 3 | 4 | // input: xyz (b, n, 3) new_xyz (b, m, 3) 5 | // output: idx (b, m, nsample) dist2 (b, m, nsample) 6 | 7 | // Note: n is the number of points, m is the number of clusters 8 | // Note: nsample <= 1000 9 | 10 | // input: idx_c (b, n, ks) cid (b, m) 11 | // output: idx (b, m, nsample) 12 | __global__ void knnquerypoint_cuda_kernel(int b, int n, int m, int ks, int nsample, const int *__restrict__ idx_c, const int *__restrict__ cid, int *__restrict__ idx) { 13 | int bs_idx = blockIdx.y; 14 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 15 | if (bs_idx >= b || pt_idx >= m) return; 16 | 17 | //new_xyz += bs_idx * m * 3 + pt_idx * 3; 18 | //cid += bs_idx * m * 1 + pt_idx * 1; 19 | cid += bs_idx * m; 20 | //xyz += bs_idx * n * 3; 21 | idx_c += bs_idx * n * ks; // add 22 | idx += bs_idx * m * nsample + pt_idx * nsample; 23 | 24 | //float new_x = new_xyz[0]; 25 | //float new_y = new_xyz[1]; 26 | //float new_z = new_xyz[2]; 27 | int cluster_id = cid[0]; 28 | 29 | //double* best = new double[nsample]; 30 | //int* besti = new int[nsample]; 31 | int tmpi[1000]; 32 | for(int i = 0; i < nsample; i++){ 33 | tmpi[i] = 0; 34 | } 35 | int last = 0; 36 | for(int k = 0; k < n && last < nsample; k++){ 37 | for (int j = 0; j < ks && last < nsample; j++) { 38 | int id = idx_c[k * ks + j]; // cluster id of i-th point 39 | if (id == cluster_id) { 40 | tmpi[last] = k; 41 | last++; 42 | } 43 | } 44 | } 45 | for(int i = 0; i < last; i++){ 46 | idx[i] = tmpi[i]; 47 | } 48 | for(int i = last; i < nsample; i++){ 49 | idx[i] = cluster_id; 50 | } 51 | //delete []best; 52 | //delete []besti; 53 | } 54 | 55 | 56 | void knnquerypoint_cuda_launcher(int b, int n, int m, int ks, int nsample, const int *idx_c, const int *cid, int *idx, cudaStream_t stream) { 57 | // param new_xyz: (B, m, 3) 58 | // param xyz: (B, n, 3) 59 | // param idx: (B, m, nsample) 60 | 61 | cudaError_t err; 62 | 63 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 64 | dim3 threads(THREADS_PER_BLOCK); 65 | 66 | knnquerypoint_cuda_kernel<<>>(b, n, m, ks, nsample, idx_c, cid, idx); 67 | // cudaDeviceSynchronize(); // for using printf in kernel function 68 | 69 | err = cudaGetLastError(); 70 | if (cudaSuccess != err) { 71 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 72 | exit(-1); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/pointops/src/knnquerypoint/knnquerypoint_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _KNNQUERYPOINT_CUDA_KERNEL 2 | #define _KNNQUERYPOINT_CUDA_KERNEL 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void knnquerypoint_cuda(int b, int n, int m, int ks, int nsample, at::Tensor idx_c_tensor, at::Tensor cid_tensor, at::Tensor idx_tensor); 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void knnquerypoint_cuda_launcher(int b, int n, int m, int ks, int nsample, const int *idx_c, const int *cid, int *idx, cudaStream_t stream); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/pointops/src/labelstat/labelstat_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "labelstat_cuda_kernel.h" 7 | 8 | extern THCState *state; 9 | 10 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 11 | #define CHECK_CONTIGUOUS(x) AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 12 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x) 13 | 14 | void labelstat_idx_cuda_fast(int b, int n, int m, int nsample, int nclass, 15 | at::Tensor label_stat_tensor, at::Tensor idx_tensor, at::Tensor new_label_stat_tensor) 16 | { 17 | CHECK_INPUT(label_stat_tensor); 18 | CHECK_INPUT(idx_tensor); 19 | 20 | const int *label_stat = label_stat_tensor.data(); 21 | const int *idx = idx_tensor.data(); 22 | int *new_label_stat = new_label_stat_tensor.data(); 23 | 24 | cudaStream_t stream = THCState_getCurrentStream(state); 25 | 26 | labelstat_idx_cuda_launcher_fast(b, n, m, nsample, nclass, label_stat, idx, new_label_stat, stream); 27 | } 28 | 29 | void labelstat_ballrange_cuda_fast(int b, int n, int m, float radius, int nclass, 30 | at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor label_stat_tensor, at::Tensor new_label_stat_tensor) 31 | { 32 | CHECK_INPUT(new_xyz_tensor); 33 | CHECK_INPUT(xyz_tensor); 34 | CHECK_INPUT(label_stat_tensor); 35 | 36 | const float *new_xyz = new_xyz_tensor.data(); 37 | const float *xyz = xyz_tensor.data(); 38 | const int *label_stat = label_stat_tensor.data(); 39 | int *new_label_stat = new_label_stat_tensor.data(); 40 | 41 | cudaStream_t stream = THCState_getCurrentStream(state); 42 | 43 | labelstat_ballrange_cuda_launcher_fast(b, n, m, radius, nclass, new_xyz, xyz, label_stat, new_label_stat, stream); 44 | } 45 | 46 | void labelstat_and_ballquery_cuda_fast(int b, int n, int m, float radius, int nsample, int nclass, 47 | at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor label_stat_tensor, at::Tensor idx_tensor, at::Tensor new_label_stat_tensor) 48 | { 49 | CHECK_INPUT(new_xyz_tensor); 50 | CHECK_INPUT(xyz_tensor); 51 | CHECK_INPUT(label_stat_tensor); 52 | CHECK_INPUT(idx_tensor); 53 | 54 | const float *new_xyz = new_xyz_tensor.data(); 55 | const float *xyz = xyz_tensor.data(); 56 | const int *label_stat = label_stat_tensor.data(); 57 | int *idx = idx_tensor.data(); 58 | int *new_label_stat = new_label_stat_tensor.data(); 59 | 60 | cudaStream_t stream = THCState_getCurrentStream(state); 61 | 62 | labelstat_and_ballquery_cuda_launcher_fast(b, n, m, radius, nsample, nclass, new_xyz, xyz, label_stat, idx, new_label_stat, stream); 63 | } 64 | -------------------------------------------------------------------------------- /lib/pointops/src/labelstat/labelstat_cuda_kernel.cu: -------------------------------------------------------------------------------- 1 | #include "../cuda_utils.h" 2 | #include "labelstat_cuda_kernel.h" 3 | 4 | // input: new_xyz(b, m, 3) xyz(b, n, 3) label_stat(b, n, nclass) 5 | // output: idx(b, m, nsample) new_label_stat(b, m, nclass) 6 | __global__ void labelstat_and_ballquery_cuda_kernel_fast(int b, int n, int m, float radius, int nsample, int nclass, 7 | const float *new_xyz, const float *xyz, const int *label_stat, int *idx, int *new_label_stat) { 8 | int bs_idx = blockIdx.y; 9 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 10 | if (bs_idx >= b || pt_idx >= m) return; 11 | 12 | new_xyz += bs_idx * m * 3 + pt_idx * 3; 13 | xyz += bs_idx * n * 3; 14 | idx += bs_idx * m * nsample + pt_idx * nsample; 15 | label_stat += bs_idx * n * nclass; 16 | new_label_stat += bs_idx * m * nclass + pt_idx * nclass; 17 | 18 | for(int i = 0; i < nclass; i++){ 19 | new_label_stat[i] = 0; 20 | } 21 | 22 | float radius2 = radius * radius; 23 | float new_x = new_xyz[0]; 24 | float new_y = new_xyz[1]; 25 | float new_z = new_xyz[2]; 26 | 27 | int cnt = 0; 28 | for (int k = 0; k < n; ++k) { 29 | float x = xyz[k * 3 + 0]; 30 | float y = xyz[k * 3 + 1]; 31 | float z = xyz[k * 3 + 2]; 32 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z); 33 | if (d2 < radius2){ 34 | for(int i = 0; i < nclass; i++){ 35 | new_label_stat[i] += label_stat[k * nclass + i]; 36 | } 37 | if (cnt == 0){ 38 | for (int l = 0; l < nsample; ++l) { 39 | idx[l] = k; 40 | } 41 | } 42 | idx[cnt] = k; 43 | ++cnt; 44 | if (cnt >= nsample){ 45 | break; 46 | } 47 | } 48 | } 49 | } 50 | 51 | void labelstat_and_ballquery_cuda_launcher_fast(int b, int n, int m, float radius, int nsample, int nclass, 52 | const float *new_xyz, const float *xyz, const int *label_stat, int *idx, int *new_label_stat, cudaStream_t stream) { 53 | // param new_xyz: (B, m, 3) 54 | // param xyz: (B, n, 3) 55 | // param idx: (B, m, nsample) 56 | 57 | cudaError_t err; 58 | 59 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 60 | dim3 threads(THREADS_PER_BLOCK); 61 | 62 | labelstat_and_ballquery_cuda_kernel_fast<<>>(b, n, m, radius, nsample, nclass, new_xyz, xyz, label_stat, idx, new_label_stat); 63 | // cudaDeviceSynchronize(); // for using printf in kernel function 64 | 65 | err = cudaGetLastError(); 66 | if (cudaSuccess != err) { 67 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 68 | exit(-1); 69 | } 70 | } 71 | 72 | // input: new_xyz(b, m, 3) xyz(b, n, 3) label_stat(b, n, nclass) 73 | // output: new_label_stat(b, m, nclass) 74 | __global__ void labelstat_ballrange_cuda_kernel_fast(int b, int n, int m, float radius, int nclass, 75 | const float *new_xyz, const float *xyz, const int *label_stat, int *new_label_stat) { 76 | int bs_idx = blockIdx.y; 77 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 78 | if (bs_idx >= b || pt_idx >= m) return; 79 | 80 | new_xyz += bs_idx * m * 3 + pt_idx * 3; 81 | xyz += bs_idx * n * 3; 82 | label_stat += bs_idx * n * nclass; 83 | new_label_stat += bs_idx * m * nclass + pt_idx * nclass; 84 | 85 | for(int i = 0; i < nclass; i++){ 86 | new_label_stat[i] = 0; 87 | } 88 | 89 | float radius2 = radius * radius; 90 | float new_x = new_xyz[0]; 91 | float new_y = new_xyz[1]; 92 | float new_z = new_xyz[2]; 93 | 94 | for (int k = 0; k < n; ++k) { 95 | float x = xyz[k * 3 + 0]; 96 | float y = xyz[k * 3 + 1]; 97 | float z = xyz[k * 3 + 2]; 98 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z); 99 | if (d2 < radius2){ 100 | for(int i = 0; i < nclass; i++){ 101 | new_label_stat[i] += label_stat[k * nclass + i]; 102 | } 103 | } 104 | } 105 | } 106 | 107 | 108 | void labelstat_ballrange_cuda_launcher_fast(int b, int n, int m, float radius, int nclass, 109 | const float *new_xyz, const float *xyz, const int *label_stat, int *new_label_stat, cudaStream_t stream) { 110 | // param new_xyz: (B, m, 3) 111 | // param xyz: (B, n, 3) 112 | // param idx: (B, m, nsample) 113 | 114 | cudaError_t err; 115 | 116 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 117 | dim3 threads(THREADS_PER_BLOCK); 118 | 119 | labelstat_ballrange_cuda_kernel_fast<<>>(b, n, m, radius, nclass, new_xyz, xyz, label_stat, new_label_stat); 120 | // cudaDeviceSynchronize(); // for using printf in kernel function 121 | 122 | err = cudaGetLastError(); 123 | if (cudaSuccess != err) { 124 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 125 | exit(-1); 126 | } 127 | } 128 | 129 | // input: idx(b, m, nsample) label_stat(b, n, nclass) 130 | // output: new_label_stat(b, m, nclass) 131 | __global__ void labelstat_idx_cuda_kernel_fast(int b, int n, int m, int nsample, int nclass, 132 | const int *label_stat, const int *idx, int *new_label_stat) { 133 | int bs_idx = blockIdx.y; 134 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x; 135 | if (bs_idx >= b || pt_idx >= m) return; 136 | 137 | idx += bs_idx * m * nsample + pt_idx * nsample; 138 | label_stat += bs_idx * n * nclass; 139 | new_label_stat += bs_idx * m * nclass + pt_idx * nclass; 140 | 141 | for(int i = 0; i < nclass; i++){ 142 | new_label_stat[i] = 0; 143 | } 144 | 145 | for(int k = 0; k < nsample; k++){ 146 | const int *label_stat_k = label_stat + idx[k] * nclass; 147 | for(int i = 0; i < nclass; i++){ 148 | new_label_stat[i] += label_stat_k[i]; 149 | } 150 | } 151 | } 152 | 153 | 154 | void labelstat_idx_cuda_launcher_fast(int b, int n, int m, int nsample, int nclass, 155 | const int *label_stat, const int *idx, int *new_label_stat, cudaStream_t stream) { 156 | // param new_xyz: (B, m, 3) 157 | // param xyz: (B, n, 3) 158 | // param idx: (B, m, nsample) 159 | 160 | cudaError_t err; 161 | 162 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row) 163 | dim3 threads(THREADS_PER_BLOCK); 164 | 165 | labelstat_idx_cuda_kernel_fast<<>>(b, n, m, nsample, nclass, label_stat, idx, new_label_stat); 166 | // cudaDeviceSynchronize(); // for using printf in kernel function 167 | 168 | err = cudaGetLastError(); 169 | if (cudaSuccess != err) { 170 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err)); 171 | exit(-1); 172 | } 173 | } -------------------------------------------------------------------------------- /lib/pointops/src/labelstat/labelstat_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _LABELSTAT_CUDA_KERNEL 2 | #define _LABELSTAT_CUDA_KERNEL 3 | #include 4 | #include 5 | #include 6 | 7 | void labelstat_and_ballquery_cuda_fast(int b, int n, int m, float radius, int nsample, int nclass, 8 | at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor label_stat_tensor, at::Tensor idx_tensor, at::Tensor new_label_stat_tensor); 9 | 10 | void labelstat_ballrange_cuda_fast(int b, int n, int m, float radius, int nclass, 11 | at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor label_stat_tensor, at::Tensor new_label_stat_tensor); 12 | 13 | void labelstat_idx_cuda_fast(int b, int n, int m, int nsample, int nclass, 14 | at::Tensor label_stat_tensor, at::Tensor idx_tensor, at::Tensor new_label_stat_tensor); 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | void labelstat_and_ballquery_cuda_launcher_fast(int b, int n, int m, float radius, int nsample, int nclass, \ 21 | const float *new_xyz, const float *xyz, const int *label_stat, int *idx, int *new_label_stat, cudaStream_t stream); 22 | 23 | void labelstat_ballrange_cuda_launcher_fast(int b, int n, int m, float radius, int nclass, \ 24 | const float *new_xyz, const float *xyz, const int *label_stat, int *new_label_stat, cudaStream_t stream); 25 | 26 | void labelstat_idx_cuda_launcher_fast(int b, int n, int m, int nsample, int nclass, \ 27 | const int *label_stat, const int *idx, int *new_label_stat, cudaStream_t stream); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /lib/pointops/src/pointops_api.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ballquery/ballquery_cuda_kernel.h" 5 | #include "grouping/grouping_cuda_kernel.h" 6 | #include "grouping_int/grouping_int_cuda_kernel.h" 7 | #include "sampling/sampling_cuda_kernel.h" 8 | #include "interpolation/interpolation_cuda_kernel.h" 9 | #include "knnquery/knnquery_cuda_kernel.h" 10 | 11 | #include "knnquerycluster/knnquerycluster_cuda_kernel.h" 12 | 13 | #include "knnqueryclustergt/knnqueryclustergt_cuda_kernel.h" 14 | 15 | #include "knnquerypoint/knnquerypoint_cuda_kernel.h" 16 | 17 | #include "assofixp2c/assofixp2c_cuda_kernel.h" 18 | 19 | #include "assofixp2c_weight/assofixp2c_weight_cuda_kernel.h" 20 | 21 | #include "assomatrix/assomatrix_cuda_kernel.h" 22 | 23 | #include "assomatrix_label/assomatrix_label_cuda_kernel.h" 24 | 25 | #include "assomatrix_float/assomatrix_float_cuda_kernel.h" 26 | 27 | //#include "knnquerydilate/knnquerydilate_cuda_kernel.h" 28 | 29 | #include "labelstat/labelstat_cuda_kernel.h" 30 | #include "featuredistribute/featuredistribute_cuda_kernel.h" 31 | 32 | 33 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 34 | m.def("ballquery_cuda", &ballquery_cuda_fast, "ballquery_cuda_fast"); // name in python, cpp function address, docs 35 | 36 | m.def("knnquery_cuda", &knnquery_cuda, "knnquery_cuda"); 37 | 38 | m.def("knnquerycluster_cuda", &knnquerycluster_cuda, "knnquerycluster_cuda"); 39 | m.def("knnqueryclustergt_cuda", &knnqueryclustergt_cuda, "knnqueryclustergt_cuda"); 40 | 41 | m.def("knnquerypoint_cuda", &knnquerypoint_cuda, "knnquerypoint_cuda"); 42 | 43 | m.def("assofixp2c_cuda", &assofixp2c_cuda, "assofixp2c_cuda"); 44 | 45 | m.def("assofixp2c_weight_cuda", &assofixp2c_weight_cuda, "assofixp2c_weight_cuda"); 46 | 47 | m.def("assomatrix_cuda", &assomatrix_cuda, "assomatrix_cuda"); 48 | 49 | m.def("assomatrix_label_cuda", &assomatrix_label_cuda, "assomatrix_label_cuda"); 50 | 51 | m.def("assomatrix_float_cuda", &assomatrix_float_cuda, "assomatrix_float_cuda"); 52 | 53 | //m.def("knnquerydilate_cuda", &knnquerydilate_cuda, "knnquerydilate_cuda"); 54 | 55 | m.def("grouping_forward_cuda", &grouping_forward_cuda_fast, "grouping_forward_cuda_fast"); 56 | m.def("grouping_backward_cuda", &grouping_backward_cuda, "grouping_backward_cuda"); 57 | 58 | m.def("grouping_int_forward_cuda", &grouping_int_forward_cuda_fast, "grouping_int_forward_cuda_fast"); 59 | 60 | m.def("gathering_forward_cuda", &gathering_forward_cuda, "gathering_forward_cuda"); 61 | m.def("gathering_backward_cuda", &gathering_backward_cuda, "gathering_backward_cuda"); 62 | 63 | // add gathering_intxxxx 64 | m.def("gathering_int_forward_cuda", &gathering_int_forward_cuda, "gathering_int_forward_cuda"); 65 | m.def("gathering_int_backward_cuda", &gathering_int_backward_cuda, "gathering_int_backward_cuda"); 66 | 67 | // add gathering_clusterxxxx 68 | m.def("gathering_cluster_forward_cuda", &gathering_cluster_forward_cuda, "gathering_cluster_forward_cuda"); 69 | m.def("gathering_cluster_backward_cuda", &gathering_cluster_backward_cuda, "gathering_cluster_backward_cuda"); 70 | 71 | m.def("furthestsampling_cuda", &furthestsampling_cuda, "furthestsampling_cuda"); 72 | 73 | m.def("nearestneighbor_cuda", &nearestneighbor_cuda_fast, "nearestneighbor_cuda_fast"); 74 | m.def("interpolation_forward_cuda", &interpolation_forward_cuda_fast, "interpolation_forward_cuda_fast"); 75 | m.def("interpolation_backward_cuda", &interpolation_backward_cuda, "interpolation_backward_cuda"); 76 | 77 | m.def("labelstat_idx_cuda", &labelstat_idx_cuda_fast, "labelstat_idx_cuda_fast"); 78 | m.def("labelstat_ballrange_cuda", &labelstat_ballrange_cuda_fast, "labelstat_ballrange_cuda_fast"); 79 | m.def("labelstat_and_ballquery_cuda", &labelstat_and_ballquery_cuda_fast, "labelstat_and_ballquery_cuda_fast"); 80 | 81 | m.def("featuredistribute_cuda", &featuredistribute_cuda, "featuredistribute_cuda"); 82 | m.def("featuregather_forward_cuda", &featuregather_forward_cuda, "featuregather_forward_cuda"); 83 | m.def("featuregather_backward_cuda", &featuregather_backward_cuda, "featuregather_backward_cuda"); 84 | } 85 | -------------------------------------------------------------------------------- /lib/pointops/src/sampling/sampling_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "sampling_cuda_kernel.h" 6 | 7 | extern THCState *state; 8 | 9 | // --------------------------- gathering ---------------------- 10 | void gathering_forward_cuda(int b, int c, int n, int m, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor) 11 | { 12 | const float *points = points_tensor.data(); 13 | const int *idx = idx_tensor.data(); 14 | float *out = out_tensor.data(); 15 | gathering_forward_cuda_launcher(b, c, n, m, points, idx, out); 16 | } 17 | 18 | void gathering_backward_cuda(int b, int c, int n, int m, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor) 19 | { 20 | 21 | const float *grad_out = grad_out_tensor.data(); 22 | const int *idx = idx_tensor.data(); 23 | float *grad_points = grad_points_tensor.data(); 24 | gathering_backward_cuda_launcher(b, c, n, m, grad_out, idx, grad_points); 25 | } 26 | 27 | // --------------------------- gathering int ---------------------- 28 | void gathering_int_forward_cuda(int b, int c, int n, int m, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor) 29 | { 30 | const int *points = points_tensor.data(); 31 | const int *idx = idx_tensor.data(); 32 | int *out = out_tensor.data(); 33 | gathering_int_forward_cuda_launcher(b, c, n, m, points, idx, out); 34 | } 35 | 36 | void gathering_int_backward_cuda(int b, int c, int n, int m, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor) 37 | { 38 | 39 | const float *grad_out = grad_out_tensor.data(); 40 | const int *idx = idx_tensor.data(); 41 | float *grad_points = grad_points_tensor.data(); 42 | gathering_int_backward_cuda_launcher(b, c, n, m, grad_out, idx, grad_points); 43 | } 44 | 45 | // --------------------------- gathering cluster ---------------------- 46 | // add for finally gather cluster for each point 47 | void gathering_cluster_forward_cuda(int b, int c, int n, int m, int k, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor idx_3d_tensor, at::Tensor out_tensor) 48 | { 49 | const float *points = points_tensor.data(); 50 | const int *idx = idx_tensor.data(); 51 | const int *idx_3d = idx_3d_tensor.data(); // add 52 | float *out = out_tensor.data(); 53 | gathering_cluster_forward_cuda_launcher(b, c, n, m, k, points, idx, idx_3d, out); // modify 54 | } 55 | 56 | void gathering_cluster_backward_cuda(int b, int c, int n, int m, int k, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor idx_3d_tensor, at::Tensor grad_points_tensor) 57 | { 58 | 59 | const float *grad_out = grad_out_tensor.data(); 60 | const int *idx = idx_tensor.data(); 61 | const int *idx_3d = idx_3d_tensor.data(); // add 62 | float *grad_points = grad_points_tensor.data(); 63 | gathering_cluster_backward_cuda_launcher(b, c, n, m, k, grad_out, idx, idx_3d, grad_points); // modify 64 | } 65 | 66 | void furthestsampling_cuda(int b, int n, int m, at::Tensor points_tensor, at::Tensor temp_tensor, at::Tensor idx_tensor) 67 | { 68 | const float *points = points_tensor.data(); 69 | float *temp = temp_tensor.data(); 70 | int *idx = idx_tensor.data(); 71 | furthestsampling_cuda_launcher(b, n, m, points, temp, idx); 72 | } 73 | -------------------------------------------------------------------------------- /lib/pointops/src/sampling/sampling_cuda_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _SAMPLING_CUDA_KERNEL 2 | #define _SAMPLING_CUDA_KERNEL 3 | #include 4 | #include 5 | #include 6 | 7 | void gathering_forward_cuda(int b, int c, int n, int m, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor); 8 | void gathering_backward_cuda(int b, int c, int n, int m, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor); 9 | 10 | void gathering_int_forward_cuda(int b, int c, int n, int m, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor); 11 | void gathering_int_backward_cuda(int b, int c, int n, int m, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor); 12 | 13 | void gathering_cluster_forward_cuda(int b, int c, int n, int m, int k, at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor idx_3d_tensor, at::Tensor out_tensor); 14 | void gathering_cluster_backward_cuda(int b, int c, int n, int m, int k, at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor idx_3d_tensor, at::Tensor grad_points_tensor); 15 | 16 | void furthestsampling_cuda(int b, int n, int m, at::Tensor points_tensor, at::Tensor temp_tensor, at::Tensor idx_tensor); 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | void gathering_forward_cuda_launcher(int b, int c, int n, int m, const float *points, const int *idx, float *out); 23 | void gathering_backward_cuda_launcher(int b, int c, int n, int m, const float *grad_out, const int *idx, float *grad_points); 24 | 25 | void gathering_int_forward_cuda_launcher(int b, int c, int n, int m, const int *points, const int *idx, int *out); 26 | void gathering_int_backward_cuda_launcher(int b, int c, int n, int m, const float *grad_out, const int *idx, float *grad_points); 27 | 28 | void gathering_cluster_forward_cuda_launcher(int b, int c, int n, int m, int k, const float *points, const int *idx, const int *idx_3d, float *out); 29 | void gathering_cluster_backward_cuda_launcher(int b, int c, int n, int m, int k, const float *grad_out, const int *idx, const int *idx_3d, float *grad_points); 30 | 31 | void furthestsampling_cuda_launcher(int b, int n, int m, const float *dataset, float *temp, int *idxs); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | #endif 37 | -------------------------------------------------------------------------------- /lib/sync_bn/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : __init__.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | from .batchnorm import SynchronizedBatchNorm1d, SynchronizedBatchNorm2d, SynchronizedBatchNorm3d 12 | from .replicate import DataParallelWithCallback, patch_replication_callback 13 | -------------------------------------------------------------------------------- /lib/sync_bn/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/sync_bn/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /lib/sync_bn/__pycache__/batchnorm.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/sync_bn/__pycache__/batchnorm.cpython-36.pyc -------------------------------------------------------------------------------- /lib/sync_bn/__pycache__/comm.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/sync_bn/__pycache__/comm.cpython-36.pyc -------------------------------------------------------------------------------- /lib/sync_bn/__pycache__/replicate.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpthink/SPNet/d7603ce614610ddb716f5b8146faba3ce008b86d/lib/sync_bn/__pycache__/replicate.cpython-36.pyc -------------------------------------------------------------------------------- /lib/sync_bn/comm.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : comm.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import queue 12 | import collections 13 | import threading 14 | 15 | __all__ = ['FutureResult', 'SlavePipe', 'SyncMaster'] 16 | 17 | 18 | class FutureResult(object): 19 | """A thread-safe future implementation. Used only as one-to-one pipe.""" 20 | 21 | def __init__(self): 22 | self._result = None 23 | self._lock = threading.Lock() 24 | self._cond = threading.Condition(self._lock) 25 | 26 | def put(self, result): 27 | with self._lock: 28 | assert self._result is None, 'Previous result has\'t been fetched.' 29 | self._result = result 30 | self._cond.notify() 31 | 32 | def get(self): 33 | with self._lock: 34 | if self._result is None: 35 | self._cond.wait() 36 | 37 | res = self._result 38 | self._result = None 39 | return res 40 | 41 | 42 | _MasterRegistry = collections.namedtuple('MasterRegistry', ['result']) 43 | _SlavePipeBase = collections.namedtuple('_SlavePipeBase', ['identifier', 'queue', 'result']) 44 | 45 | 46 | class SlavePipe(_SlavePipeBase): 47 | """Pipe for master-slave communication.""" 48 | 49 | def run_slave(self, msg): 50 | self.queue.put((self.identifier, msg)) 51 | ret = self.result.get() 52 | self.queue.put(True) 53 | return ret 54 | 55 | 56 | class SyncMaster(object): 57 | """An abstract `SyncMaster` object. 58 | 59 | - During the replication, as the data parallel will trigger an callback of each module, all slave devices should 60 | call `register(id)` and obtain an `SlavePipe` to communicate with the master. 61 | - During the forward pass, master device invokes `run_master`, all messages from slave devices will be collected, 62 | and passed to a registered callback. 63 | - After receiving the messages, the master device should gather the information and determine to message passed 64 | back to each slave devices. 65 | """ 66 | 67 | def __init__(self, master_callback): 68 | """ 69 | 70 | Args: 71 | master_callback: a callback to be invoked after having collected messages from slave devices. 72 | """ 73 | self._master_callback = master_callback 74 | self._queue = queue.Queue() 75 | self._registry = collections.OrderedDict() 76 | self._activated = False 77 | 78 | def __getstate__(self): 79 | return {'master_callback': self._master_callback} 80 | 81 | def __setstate__(self, state): 82 | self.__init__(state['master_callback']) 83 | 84 | def register_slave(self, identifier): 85 | """ 86 | Register an slave device. 87 | 88 | Args: 89 | identifier: an identifier, usually is the device id. 90 | 91 | Returns: a `SlavePipe` object which can be used to communicate with the master device. 92 | 93 | """ 94 | if self._activated: 95 | assert self._queue.empty(), 'Queue is not clean before next initialization.' 96 | self._activated = False 97 | self._registry.clear() 98 | future = FutureResult() 99 | self._registry[identifier] = _MasterRegistry(future) 100 | return SlavePipe(identifier, self._queue, future) 101 | 102 | def run_master(self, master_msg): 103 | """ 104 | Main entry for the master device in each forward pass. 105 | The messages were first collected from each devices (including the master device), and then 106 | an callback will be invoked to compute the message to be sent back to each devices 107 | (including the master device). 108 | 109 | Args: 110 | master_msg: the message that the master want to send to itself. This will be placed as the first 111 | message when calling `master_callback`. For detailed usage, see `_SynchronizedBatchNorm` for an example. 112 | 113 | Returns: the message to be sent back to the master device. 114 | 115 | """ 116 | self._activated = True 117 | 118 | intermediates = [(0, master_msg)] 119 | for i in range(self.nr_slaves): 120 | intermediates.append(self._queue.get()) 121 | 122 | results = self._master_callback(intermediates) 123 | assert results[0][0] == 0, 'The first result should belongs to the master.' 124 | 125 | for i, res in results: 126 | if i == 0: 127 | continue 128 | self._registry[i].result.put(res) 129 | 130 | for i in range(self.nr_slaves): 131 | assert self._queue.get() is True 132 | 133 | return results[0][1] 134 | 135 | @property 136 | def nr_slaves(self): 137 | return len(self._registry) 138 | -------------------------------------------------------------------------------- /lib/sync_bn/replicate.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : replicate.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import functools 12 | 13 | from torch.nn.parallel.data_parallel import DataParallel 14 | 15 | __all__ = [ 16 | 'CallbackContext', 17 | 'execute_replication_callbacks', 18 | 'DataParallelWithCallback', 19 | 'patch_replication_callback' 20 | ] 21 | 22 | 23 | class CallbackContext(object): 24 | pass 25 | 26 | 27 | def execute_replication_callbacks(modules): 28 | """ 29 | Execute an replication callback `__data_parallel_replicate__` on each module created by original replication. 30 | 31 | The callback will be invoked with arguments `__data_parallel_replicate__(ctx, copy_id)` 32 | 33 | Note that, as all modules are isomorphism, we assign each sub-module with a context 34 | (shared among multiple copies of this module on different devices). 35 | Through this context, different copies can share some information. 36 | 37 | We guarantee that the callback on the master copy (the first copy) will be called ahead of calling the callback 38 | of any slave copies. 39 | """ 40 | master_copy = modules[0] 41 | nr_modules = len(list(master_copy.modules())) 42 | ctxs = [CallbackContext() for _ in range(nr_modules)] 43 | 44 | for i, module in enumerate(modules): 45 | for j, m in enumerate(module.modules()): 46 | if hasattr(m, '__data_parallel_replicate__'): 47 | m.__data_parallel_replicate__(ctxs[j], i) 48 | 49 | 50 | class DataParallelWithCallback(DataParallel): 51 | """ 52 | Data Parallel with a replication callback. 53 | 54 | An replication callback `__data_parallel_replicate__` of each module will be invoked after being created by 55 | original `replicate` functions. 56 | The callback will be invoked with arguments `__data_parallel_replicate__(ctx, copy_id)` 57 | 58 | Examples: 59 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 60 | > sync_bn = DataParallelWithCallback(sync_bn, device_ids=[0, 1]) 61 | # sync_bn.__data_parallel_replicate__ will be invoked. 62 | """ 63 | 64 | def replicate(self, module, device_ids): 65 | modules = super(DataParallelWithCallback, self).replicate(module, device_ids) 66 | execute_replication_callbacks(modules) 67 | return modules 68 | 69 | 70 | def patch_replication_callback(data_parallel): 71 | """ 72 | Monkey-patch an existing `DataParallel` object. Add the replication callback. 73 | Useful when you have customized `DataParallel` implementation. 74 | 75 | Examples: 76 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 77 | > sync_bn = DataParallel(sync_bn, device_ids=[0, 1]) 78 | > patch_replication_callback(sync_bn) 79 | # this is equivalent to 80 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 81 | > sync_bn = DataParallelWithCallback(sync_bn, device_ids=[0, 1]) 82 | """ 83 | 84 | assert isinstance(data_parallel, DataParallel) 85 | 86 | old_replicate = data_parallel.replicate 87 | 88 | @functools.wraps(old_replicate) 89 | def new_replicate(module, device_ids): 90 | modules = old_replicate(module, device_ids) 91 | execute_replication_callbacks(modules) 92 | return modules 93 | 94 | data_parallel.replicate = new_replicate 95 | -------------------------------------------------------------------------------- /lib/sync_bn/unittest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : unittest.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import unittest 12 | 13 | import numpy as np 14 | from torch.autograd import Variable 15 | 16 | 17 | def as_numpy(v): 18 | if isinstance(v, Variable): 19 | v = v.data 20 | return v.cpu().numpy() 21 | 22 | 23 | class TorchTestCase(unittest.TestCase): 24 | def assertTensorClose(self, a, b, atol=1e-3, rtol=1e-3): 25 | npa, npb = as_numpy(a), as_numpy(b) 26 | self.assertTrue( 27 | np.allclose(npa, npb, atol=atol), 28 | 'Tensor close check failed\n{}\n{}\nadiff={}, rdiff={}'.format(a, b, np.abs(npa - npb).max(), np.abs((npa - npb) / np.fmax(npa, 1e-5)).max()) 29 | ) 30 | -------------------------------------------------------------------------------- /tool/sh_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export PYTHONPATH=./ 3 | 4 | PYTHON=python 5 | dataset=$1 6 | exp_name=$2 7 | config=$3 8 | epoch=$4 9 | 10 | 11 | exp_dir=exp/${dataset}/${exp_name} 12 | 13 | model_log=${exp_dir}/log 14 | mkdir -p ${model_log} 15 | 16 | save_folder=${exp_dir}/test_results/epoch_${epoch} 17 | mkdir -p ${save_folder} 18 | 19 | model_path=${exp_dir}/saved_model 20 | 21 | now=$(date +"%Y%m%d_%H%M%S") 22 | 23 | cp tool/sh_test.sh tool/test.py ${config} ${exp_dir} 24 | $PYTHON tool/test.py \ 25 | --config ${config} \ 26 | --model_path ${model_path} \ 27 | --epoch ${epoch} \ 28 | --save_folder ${save_folder} 2>&1 | tee ${model_log}/test-$epoch-$now.log 29 | -------------------------------------------------------------------------------- /tool/sh_train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export PYTHONPATH=./ 3 | 4 | PYTHON=python 5 | dataset=$1 6 | exp_name=$2 7 | config=$3 8 | 9 | exp_dir=exp/${dataset}/${exp_name} 10 | 11 | model_log=${exp_dir}/log 12 | mkdir -p ${model_log} 13 | 14 | model_path=${exp_dir}/saved_model 15 | mkdir -p ${model_path} 16 | 17 | model_events=${exp_dir}/events 18 | mkdir -p ${model_events} 19 | 20 | now=$(date +"%Y%m%d_%H%M%S") 21 | 22 | cp tool/sh_train.sh tool/train.py ${config} ${exp_dir} 23 | 24 | $PYTHON tool/train.py \ 25 | --config ${config} \ 26 | --model_path ${model_path} \ 27 | --save_path=${exp_dir} 2>&1 | tee ${model_log}/train-$now.log 28 | 29 | -------------------------------------------------------------------------------- /util/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | 5 | -------------------------------------------------------------------------------- /util/compute_spg/calc_sp_metrics_v1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Oct 11 10:12:49 2018 5 | 6 | @author: landrieuloic 7 | """ 8 | 9 | """ 10 | Large-scale Point Cloud Semantic Segmentation with Superpoint Graphs 11 | http://arxiv.org/abs/1711.09869 12 | 2017 Loic Landrieu, Martin Simonovsky 13 | """ 14 | import glob, os 15 | import argparse 16 | import numpy as np 17 | import sys 18 | import ast 19 | import csv 20 | import h5py 21 | import torchnet as tnt 22 | import torch 23 | import metrics 24 | from metrics import * 25 | 26 | 27 | def perfect_prediction(components, labels): 28 | """assign each superpoint with the majority label""" 29 | #print(pred.shape) 30 | full_pred = np.zeros((labels.shape[0],),dtype='uint32') 31 | 32 | for i_com in range(len(components)): 33 | #print(len(components[i_com])) 34 | #te=labels[components[i_com]] 35 | #print(te.shape) 36 | #label_com = np.argmax(np.bincount(labels[components[i_com]])) 37 | # label_com = labels[components[i_com],1:].sum(0).argmax() 38 | label_com = labels[components[i_com], :].sum(0).argmax() 39 | #print(label_com) 40 | full_pred[components[i_com]]=label_com 41 | 42 | 43 | return full_pred 44 | 45 | def relax_edge_binary(edg_binary, edg_source, edg_target, n_ver, tolerance): 46 | if torch.is_tensor(edg_binary): 47 | relaxed_binary = edg_binary.cpu().numpy().copy() 48 | else: 49 | relaxed_binary = edg_binary.copy() 50 | transition_vertex = np.full((n_ver,), 0, dtype = 'uint8') 51 | for i_tolerance in range(tolerance): 52 | transition_vertex[edg_source[relaxed_binary.nonzero()]] = True 53 | transition_vertex[edg_target[relaxed_binary.nonzero()]] = True 54 | relaxed_binary[transition_vertex[edg_source]] = True 55 | relaxed_binary[transition_vertex[edg_target]>0] = True 56 | return relaxed_binary 57 | 58 | def partition2ply(filename, xyz, components): 59 | """write a ply with random colors for each components""" 60 | random_color = lambda: random.randint(0, 255) 61 | color = np.zeros(xyz.shape) 62 | for i_com in range(0, len(components)): 63 | color[components[i_com], :] = [random_color(), random_color() 64 | , random_color()] 65 | prop = [('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1') 66 | , ('green', 'u1'), ('blue', 'u1')] 67 | vertex_all = np.empty(len(xyz), dtype=prop) 68 | for i in range(0, 3): 69 | vertex_all[prop[i][0]] = xyz[:, i] 70 | for i in range(0, 3): 71 | vertex_all[prop[i+3][0]] = color[:, i] 72 | ply = PlyData([PlyElement.describe(vertex_all, 'vertex')], text=True) 73 | ply.write(filename) 74 | 75 | # data_root='/all/Dataset/S3DIS/superpoint_graphs/' 76 | # data_root='/all/Dataset/S3DIS/spg_ssp_superpoint_graphs/' 77 | 78 | file_cnt=0 79 | p_cnt=0 80 | sp_cnt=0 81 | sp_cnt2=0 82 | 83 | BR_tolerance=1 84 | 85 | #reg_strenth=[0.02,0.03,0.04,0.05,0.06] 86 | reg_strenth=[0.10] 87 | reg_strenth=[0.12] 88 | #data_root='/all/Dataset/vKITTI/new_vkitti/' 89 | #spg_root='/all/hl_cvpr2021/Results/vKITTI/SPG/' 90 | #spg_root='/all/hl_cvpr2021/Results/vKITTI/SPG_norgb/' 91 | # for rs in reg_strenth: 92 | # confusion_matrix_classes = metrics.ConfusionMatrix(13) 93 | # confusion_matrix_BR = metrics.ConfusionMatrix(2) 94 | # confusion_matrix_BP = metrics.ConfusionMatrix(2) 95 | 96 | confusion_matrix = metrics.ConfusionMatrix(13) 97 | BR_meter = tnt.meter.AverageValueMeter() 98 | BP_meter = tnt.meter.AverageValueMeter() 99 | 100 | data_root = '/test/dataset/3d_datasets/spnet_semanticposs/20201121_point_all_rm_unlabel_2geof' 101 | data_folder = os.path.join(data_root, 'sp_voxel') 102 | fea_folder = os.path.join(data_root, 'points_voxels') 103 | 104 | for file in os.listdir(data_folder): 105 | if '02_' not in file: continue 106 | file_cnt += 1 107 | file_name = os.path.join(data_folder, file) 108 | data_file = h5py.File(file_name, 'r') 109 | print(file_name) 110 | # sp_length= np.array(data_file["sp_length"], dtype='float32') 111 | in_component = np.array(data_file["in_component_v"], dtype='uint32') 112 | 113 | # n_com = len(sp_length) 114 | grp = data_file['components_v'] 115 | n_com = len(grp) 116 | 117 | components = np.empty((n_com,), dtype=object) 118 | 119 | for i_com in range(0, n_com): 120 | components[i_com] = np.array(grp[str(i_com)], dtype='uint32').tolist() 121 | 122 | #fea_file=fea_folder+file 123 | fea_file = h5py.File(os.path.join(fea_folder, file), 'r') 124 | xyz = np.array(fea_file['xyz_v'], dtype='float32') 125 | labels = np.array(fea_file['labels_v']).squeeze() 126 | edg_source = np.array(fea_file['source'], dtype='int').squeeze() 127 | edg_target = np.array(fea_file['target'], dtype='int').squeeze() 128 | is_transition = np.array(fea_file['is_transition']) 129 | 130 | pred_transition = in_component[edg_source]!=in_component[edg_target] 131 | 132 | print('labels: {}'.format(labels.shape)) 133 | 134 | one_hot = np.eye(13) 135 | labels = one_hot[labels] 136 | print('labels: {}'.format(labels.shape)) 137 | 138 | # exit() 139 | full_pred= perfect_prediction(components, labels) 140 | #full_pred= perfect_prediction(components,tlabels) 141 | 142 | # confusion_matrix.count_predicted_batch(labels[:, 1:], full_pred) 143 | confusion_matrix.count_predicted_batch(labels[:, :], full_pred) 144 | BR_meter.add((is_transition.sum())*compute_boundary_recall(is_transition, relax_edge_binary(pred_transition, edg_source, edg_target, xyz.shape[0], BR_tolerance)),n=is_transition.sum()) 145 | BP_meter.add((pred_transition.sum())*compute_boundary_precision(relax_edge_binary(is_transition, edg_source, edg_target, xyz.shape[0], BR_tolerance), pred_transition),n=pred_transition.sum()) 146 | #print(confusion_matrix.get_overall_accuracy(),BR_meter.value()[0], BP_meter.value()[0]) 147 | 148 | 149 | # n_com = len(sp_length) 150 | sp_cnt+=n_com 151 | p_cnt+=len(in_component) 152 | #print('======Area_{}====== Finished'.format(i)) 153 | 154 | 155 | print(p_cnt, sp_cnt) 156 | print(p_cnt//sp_cnt) 157 | print(sp_cnt, file_cnt) 158 | print('avg: superpoint {}'.format(sp_cnt//file_cnt)) 159 | print(confusion_matrix.get_overall_accuracy(), BR_meter.value()[0], BP_meter.value()[0]) -------------------------------------------------------------------------------- /util/compute_spg/get_metric.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Oct 11 10:12:49 2018 5 | 6 | @author: landrieuloic 7 | """ 8 | 9 | """ 10 | Large-scale Point Cloud Semantic Segmentation with Superpoint Graphs 11 | http://arxiv.org/abs/1711.09869 12 | 2017 Loic Landrieu, Martin Simonovsky 13 | """ 14 | import glob, os 15 | import argparse 16 | import numpy as np 17 | import sys 18 | import ast 19 | import csv 20 | import h5py 21 | import torchnet as tnt 22 | import torch 23 | from learning import metrics 24 | from learning.metrics import * 25 | 26 | 27 | def perfect_prediction(components,labels): 28 | """assign each superpoint with the majority label""" 29 | #print(pred.shape) 30 | full_pred = np.zeros((labels.shape[0],),dtype='uint32') 31 | 32 | for i_com in range(len(components)): 33 | #print(len(components[i_com])) 34 | #te=labels[components[i_com]] 35 | #print(te.shape) 36 | #label_com = np.argmax(np.bincount(labels[components[i_com]])) 37 | label_com = labels[components[i_com],1:].sum(0).argmax() 38 | #print(label_com) 39 | full_pred[components[i_com]]=label_com 40 | 41 | 42 | return full_pred 43 | 44 | def relax_edge_binary(edg_binary, edg_source, edg_target, n_ver, tolerance): 45 | if torch.is_tensor(edg_binary): 46 | relaxed_binary = edg_binary.cpu().numpy().copy() 47 | else: 48 | relaxed_binary = edg_binary.copy() 49 | transition_vertex = np.full((n_ver,), 0, dtype = 'uint8') 50 | for i_tolerance in range(tolerance): 51 | transition_vertex[edg_source[relaxed_binary.nonzero()]] = True 52 | transition_vertex[edg_target[relaxed_binary.nonzero()]] = True 53 | relaxed_binary[transition_vertex[edg_source]] = True 54 | relaxed_binary[transition_vertex[edg_target]>0] = True 55 | return relaxed_binary 56 | 57 | def partition2ply(filename, xyz, components): 58 | """write a ply with random colors for each components""" 59 | random_color = lambda: random.randint(0, 255) 60 | color = np.zeros(xyz.shape) 61 | for i_com in range(0, len(components)): 62 | color[components[i_com], :] = [random_color(), random_color() 63 | , random_color()] 64 | prop = [('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1') 65 | , ('green', 'u1'), ('blue', 'u1')] 66 | vertex_all = np.empty(len(xyz), dtype=prop) 67 | for i in range(0, 3): 68 | vertex_all[prop[i][0]] = xyz[:, i] 69 | for i in range(0, 3): 70 | vertex_all[prop[i+3][0]] = color[:, i] 71 | ply = PlyData([PlyElement.describe(vertex_all, 'vertex')], text=True) 72 | ply.write(filename) 73 | 74 | #data_root='/all/Dataset/S3DIS/superpoint_graphs/' 75 | #data_root='/all/Dataset/S3DIS/spg_ssp_superpoint_graphs/' 76 | 77 | file_cnt=0 78 | p_cnt=0 79 | sp_cnt=0 80 | sp_cnt2=0 81 | 82 | BR_meter = tnt.meter.AverageValueMeter() 83 | BP_meter = tnt.meter.AverageValueMeter() 84 | confusion_matrix = metrics.ConfusionMatrix(13) 85 | BR_tolerance=1 86 | 87 | #reg_strenth=[0.02,0.03,0.04,0.05,0.06] 88 | reg_strenth=[0.10] 89 | reg_strenth=[0.12] 90 | for rs in reg_strenth: 91 | confusion_matrix_classes = metrics.ConfusionMatrix(13) 92 | confusion_matrix_BR = metrics.ConfusionMatrix(2) 93 | confusion_matrix_BP = metrics.ConfusionMatrix(2) 94 | 95 | res='/all/hl_cvpr2021/Results/S3DIS/SPG/res_file/rs_{}_A5.h5'.format(rs) 96 | #res='/test/hl_cvpr2021/Results/S3DIS/SPG/6_fold/rs_{}/'.format(rs) 97 | #res='/all/hl_cvpr2021/Results/S3DIS/SPG_norgb/6_fold/rs_{}/'.format(rs) 98 | #res='/all/hl_cvpr2021/Results/S3DIS/SPG_norgb/A5/rs_{}/res.h5'.format(rs) 99 | #res='/all/hl_cvpr2021/Results/ScanNet/SPG/results/rs_{}.h5'.format(rs) 100 | #res='/all/hl_cvpr2021/Results/ScanNet/SPG_norgb/results/rs_{}.h5'.format(rs) 101 | 102 | #res='/all/hl_cvpr2021/Results/vKITTI/SPG/rs_0.03.h5' 103 | #res='/all/hl_cvpr2021/Results/vKITTI/SPG/rs_0.03.h5' 104 | #res='/all/hl_cvpr2021/Results/vKITTI/SPG/rs_0.5.h5' 105 | #res='/all/hl_cvpr2021/Results/vKITTI/SPG_norgb/rs_0.5.h5' 106 | print(res) 107 | C_classes = np.zeros((13,13)) 108 | C_BR = np.zeros((2,2)) 109 | C_BP = np.zeros((2,2)) 110 | 111 | #res_file = h5py.File(res+'res.h5', 'r') 112 | res_file = h5py.File(res, 'r') 113 | c_classes = np.array(res_file["confusion_matrix_classes"]) 114 | c_BP = np.array(res_file["confusion_matrix_BP"]) 115 | c_BR = np.array(res_file["confusion_matrix_BR"]) 116 | n_sp= np.array(res_file["average_superpoint"]) 117 | #print(n_sp) 118 | print('='*20) 119 | print('rs={}'.format(rs)) 120 | print("n_sp = %5.1f \t ASA = %3.2f %% \t BR = %3.2f %% \t BP = %3.2f %%" % \ 121 | (n_sp,100 * c_classes.trace() / c_classes.sum(), 100 * c_BR[1,1] / (c_BR[1,1] + c_BR[1,0]),100 * c_BP[1,1] / (c_BP[1,1] + c_BP[0,1]) )) 122 | 123 | 124 | -------------------------------------------------------------------------------- /util/compute_spg/metrics.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | from __future__ import print_function 3 | from builtins import range 4 | 5 | import numpy as np 6 | 7 | # extended official code from http://www.semantic3d.net/scripts/metric.py 8 | class ConfusionMatrix: 9 | """Streaming interface to allow for any source of predictions. Initialize it, count predictions one by one, then print confusion matrix and intersection-union score""" 10 | def __init__(self, number_of_labels = 2): 11 | self.number_of_labels = number_of_labels 12 | self.confusion_matrix = np.zeros(shape=(self.number_of_labels,self.number_of_labels)) 13 | def count_predicted(self, ground_truth, predicted, number_of_added_elements=1): 14 | self.confusion_matrix[ground_truth][predicted] += number_of_added_elements 15 | 16 | def count_predicted_batch(self, ground_truth_vec, predicted): # added 17 | for i in range(ground_truth_vec.shape[0]): 18 | self.confusion_matrix[:,predicted[i]] += ground_truth_vec[i,:] 19 | 20 | def count_predicted_batch_hard(self, ground_truth_vec, predicted): # added 21 | for i in range(ground_truth_vec.shape[0]): 22 | self.confusion_matrix[ground_truth_vec[i],predicted[i]] += 1 23 | 24 | """labels are integers from 0 to number_of_labels-1""" 25 | def get_count(self, ground_truth, predicted): 26 | return self.confusion_matrix[ground_truth][predicted] 27 | """returns list of lists of integers; use it as result[ground_truth][predicted] 28 | to know how many samples of class ground_truth were reported as class predicted""" 29 | def get_confusion_matrix(self): 30 | return self.confusion_matrix 31 | """returns list of 64-bit floats""" 32 | def get_intersection_union_per_class(self): 33 | matrix_diagonal = [self.confusion_matrix[i][i] for i in range(self.number_of_labels)] 34 | errors_summed_by_row = [0] * self.number_of_labels 35 | for row in range(self.number_of_labels): 36 | for column in range(self.number_of_labels): 37 | if row != column: 38 | errors_summed_by_row[row] += self.confusion_matrix[row][column] 39 | errors_summed_by_column = [0] * self.number_of_labels 40 | for column in range(self.number_of_labels): 41 | for row in range(self.number_of_labels): 42 | if row != column: 43 | errors_summed_by_column[column] += self.confusion_matrix[row][column] 44 | 45 | divisor = [0] * self.number_of_labels 46 | for i in range(self.number_of_labels): 47 | divisor[i] = matrix_diagonal[i] + errors_summed_by_row[i] + errors_summed_by_column[i] 48 | if matrix_diagonal[i] == 0: 49 | divisor[i] = 1 50 | 51 | return [float(matrix_diagonal[i]) / divisor[i] for i in range(self.number_of_labels)] 52 | """returns 64-bit float""" 53 | 54 | def get_overall_accuracy(self): 55 | matrix_diagonal = 0 56 | all_values = 0 57 | for row in range(self.number_of_labels): 58 | for column in range(self.number_of_labels): 59 | all_values += self.confusion_matrix[row][column] 60 | if row == column: 61 | matrix_diagonal += self.confusion_matrix[row][column] 62 | if all_values == 0: 63 | all_values = 1 64 | return float(matrix_diagonal) / all_values 65 | 66 | 67 | def get_average_intersection_union(self): 68 | values = self.get_intersection_union_per_class() 69 | class_seen = ((self.confusion_matrix.sum(1)+self.confusion_matrix.sum(0))!=0).sum() 70 | return sum(values) / class_seen 71 | 72 | def get_mean_class_accuracy(self): # added 73 | re = 0 74 | for i in range(self.number_of_labels): 75 | re = re + self.confusion_matrix[i][i] / max(1,np.sum(self.confusion_matrix[i,:])) 76 | return re/self.number_of_labels 77 | 78 | def count_gt(self, ground_truth): 79 | return self.confusion_matrix[ground_truth,:].sum() 80 | 81 | def compute_predicted_transitions(in_component, edg_source, edg_target): 82 | 83 | pred_transitions = in_component[edg_source] != in_component[edg_target] 84 | return pred_transitions 85 | 86 | #----------------------------------------------------------- 87 | def compute_boundary_recall(is_transition, pred_transitions): 88 | return 100*((is_transition==pred_transitions)*is_transition).sum()/is_transition.sum() 89 | 90 | #----------------------------------------------------------- 91 | def compute_boundary_precision(is_transition, pred_transitions): 92 | return 100*((is_transition==pred_transitions)*pred_transitions).sum()/pred_transitions.sum() 93 | #-------------------------------------------- 94 | 95 | def mode(array, only_freq=False): 96 | value, counts = np.unique(array, return_counts=True) 97 | if only_freq: 98 | return np.amax(counts) 99 | else: 100 | return value[np.argmax(counts)], np.amax(counts) 101 | #------------------------------------------------ 102 | def compute_OOA(components, labels): 103 | hard_labels = labels.argmax(1) 104 | correct_labels=0 105 | for comp in components: 106 | dump, freq = mode(hard_labels[comp]) 107 | correct_labels+=freq 108 | return 100*correct_labels/len(labels) 109 | -------------------------------------------------------------------------------- /util/config.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Functions for parsing args 3 | # ----------------------------------------------------------------------------- 4 | import yaml 5 | import os 6 | from ast import literal_eval 7 | import copy 8 | 9 | 10 | class CfgNode(dict): 11 | """ 12 | CfgNode represents an internal node in the configuration tree. It's a simple 13 | dict-like container that allows for attribute-based access to keys. 14 | """ 15 | 16 | def __init__(self, init_dict=None, key_list=None, new_allowed=False): 17 | # Recursively convert nested dictionaries in init_dict into CfgNodes 18 | init_dict = {} if init_dict is None else init_dict 19 | key_list = [] if key_list is None else key_list 20 | for k, v in init_dict.items(): 21 | if type(v) is dict: 22 | # Convert dict to CfgNode 23 | init_dict[k] = CfgNode(v, key_list=key_list + [k]) 24 | super(CfgNode, self).__init__(init_dict) 25 | 26 | def __getattr__(self, name): 27 | if name in self: 28 | return self[name] 29 | else: 30 | raise AttributeError(name) 31 | 32 | def __setattr__(self, name, value): 33 | self[name] = value 34 | 35 | def __str__(self): 36 | def _indent(s_, num_spaces): 37 | s = s_.split("\n") 38 | if len(s) == 1: 39 | return s_ 40 | first = s.pop(0) 41 | s = [(num_spaces * " ") + line for line in s] 42 | s = "\n".join(s) 43 | s = first + "\n" + s 44 | return s 45 | 46 | r = "" 47 | s = [] 48 | for k, v in sorted(self.items()): 49 | seperator = "\n" if isinstance(v, CfgNode) else " " 50 | attr_str = "{}:{}{}".format(str(k), seperator, str(v)) 51 | attr_str = _indent(attr_str, 2) 52 | s.append(attr_str) 53 | r += "\n".join(s) 54 | return r 55 | 56 | def __repr__(self): 57 | return "{}({})".format(self.__class__.__name__, super(CfgNode, self).__repr__()) 58 | 59 | 60 | def load_cfg_from_cfg_file(file): 61 | cfg = {} 62 | assert os.path.isfile(file) and file.endswith('.yaml'), \ 63 | '{} is not a yaml file'.format(file) 64 | 65 | with open(file, 'r') as f: 66 | cfg_from_file = yaml.safe_load(f) 67 | 68 | for key in cfg_from_file: 69 | for k, v in cfg_from_file[key].items(): 70 | cfg[k] = v 71 | 72 | cfg = CfgNode(cfg) 73 | return cfg 74 | 75 | 76 | def merge_cfg_from_list(cfg, cfg_list): 77 | new_cfg = copy.deepcopy(cfg) 78 | assert len(cfg_list) % 2 == 0 79 | for full_key, v in zip(cfg_list[0::2], cfg_list[1::2]): 80 | subkey = full_key.split('.')[-1] 81 | assert subkey in cfg, 'Non-existent key: {}'.format(full_key) 82 | value = _decode_cfg_value(v) 83 | value = _check_and_coerce_cfg_value_type( 84 | value, cfg[subkey], subkey, full_key 85 | ) 86 | setattr(new_cfg, subkey, value) 87 | 88 | return new_cfg 89 | 90 | 91 | def _decode_cfg_value(v): 92 | """Decodes a raw config value (e.g., from a yaml config files or command 93 | line argument) into a Python object. 94 | """ 95 | # All remaining processing is only applied to strings 96 | if not isinstance(v, str): 97 | return v 98 | # Try to interpret `v` as a: 99 | # string, number, tuple, list, dict, boolean, or None 100 | try: 101 | v = literal_eval(v) 102 | # The following two excepts allow v to pass through when it represents a 103 | # string. 104 | # 105 | # Longer explanation: 106 | # The type of v is always a string (before calling literal_eval), but 107 | # sometimes it *represents* a string and other times a data structure, like 108 | # a list. In the case that v represents a string, what we got back from the 109 | # yaml parser is 'foo' *without quotes* (so, not '"foo"'). literal_eval is 110 | # ok with '"foo"', but will raise a ValueError if given 'foo'. In other 111 | # cases, like paths (v = 'foo/bar' and not v = '"foo/bar"'), literal_eval 112 | # will raise a SyntaxError. 113 | except ValueError: 114 | pass 115 | except SyntaxError: 116 | pass 117 | return v 118 | 119 | 120 | def _check_and_coerce_cfg_value_type(replacement, original, key, full_key): 121 | """Checks that `replacement`, which is intended to replace `original` is of 122 | the right type. The type is correct if it matches exactly or is one of a few 123 | cases in which the type can be easily coerced. 124 | """ 125 | original_type = type(original) 126 | replacement_type = type(replacement) 127 | 128 | # The types must match (with some exceptions) 129 | if replacement_type == original_type: 130 | return replacement 131 | 132 | # Cast replacement from from_type to to_type if the replacement and original 133 | # types match from_type and to_type 134 | def conditional_cast(from_type, to_type): 135 | if replacement_type == from_type and original_type == to_type: 136 | return True, to_type(replacement) 137 | else: 138 | return False, None 139 | 140 | # Conditionally casts 141 | # list <-> tuple 142 | casts = [(tuple, list), (list, tuple)] 143 | # For py2: allow converting from str (bytes) to a unicode string 144 | try: 145 | casts.append((str, unicode)) # noqa: F821 146 | except Exception: 147 | pass 148 | 149 | for (from_type, to_type) in casts: 150 | converted, converted_value = conditional_cast(from_type, to_type) 151 | if converted: 152 | return converted_value 153 | 154 | raise ValueError( 155 | "Type mismatch ({} vs. {}) with values ({} vs. {}) for config " 156 | "key: {}".format( 157 | original_type, replacement_type, original, replacement, full_key 158 | ) 159 | ) 160 | 161 | 162 | def _assert_with_logging(cond, msg): 163 | if not cond: 164 | logger.debug(msg) 165 | assert cond, msg 166 | 167 | -------------------------------------------------------------------------------- /util/dataset.py: -------------------------------------------------------------------------------- 1 | import os 2 | import h5py 3 | import numpy as np 4 | 5 | from torch.utils.data import Dataset 6 | 7 | 8 | def make_dataset(split='train', data_root=None, data_list=None): 9 | if not os.path.isfile(data_list): 10 | raise (RuntimeError("Point list file do not exist: " + data_list + "\n")) 11 | point_list = [] 12 | list_read = open(data_list).readlines() 13 | print("Totally {} samples in {} set.".format(len(list_read), split)) 14 | for line in list_read: 15 | point_list.append(os.path.join(data_root, line.strip())) 16 | return point_list 17 | 18 | 19 | class PointData(Dataset): 20 | def __init__(self, split='train', data_root=None, data_list=None, transform=None, num_point=None, random_index=False): 21 | assert split in ['train', 'val', 'test'] 22 | self.split = split 23 | self.data_list = make_dataset(split, data_root, data_list) 24 | self.transform = transform 25 | self.num_point = num_point 26 | self.random_index = random_index 27 | 28 | def __len__(self): 29 | return len(self.data_list) 30 | 31 | def __getitem__(self, index): 32 | data_path = self.data_list[index] 33 | f = h5py.File(data_path, 'r') 34 | data = f['data'][:] 35 | if self.split is 'test': 36 | label = 255 # place holder 37 | else: 38 | label = f['label'][:] 39 | f.close() 40 | if self.num_point is None: 41 | self.num_point = data.shape[0] 42 | idxs = np.arange(data.shape[0]) 43 | if self.random_index: 44 | np.random.shuffle(idxs) 45 | idxs = idxs[0:self.num_point] 46 | data = data[idxs, :] 47 | if label.size != 1: # seg data 48 | label = label[idxs] 49 | if self.transform is not None: 50 | data, label = self.transform(data, label) 51 | return data, label 52 | 53 | 54 | if __name__ == '__main__': 55 | data_root = '/mnt/sda1/hszhao/dataset/3d/s3dis' 56 | data_list = '/mnt/sda1/hszhao/dataset/3d/s3dis/list/train12346.txt' 57 | point_data = PointData('train', data_root, data_list) 58 | print('point data size:', point_data.__len__()) 59 | print('point data 0 shape:', point_data.__getitem__(0)[0].shape) 60 | print('point label 0 shape:', point_data.__getitem__(0)[1].shape) 61 | -------------------------------------------------------------------------------- /util/metrics.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | from __future__ import print_function 3 | from builtins import range 4 | 5 | import numpy as np 6 | 7 | # extended official code from http://www.semantic3d.net/scripts/metric.py 8 | class ConfusionMatrix: 9 | """Streaming interface to allow for any source of predictions. Initialize it, count predictions one by one, then print confusion matrix and intersection-union score""" 10 | def __init__(self, number_of_labels = 2): 11 | self.number_of_labels = number_of_labels 12 | self.confusion_matrix = np.zeros(shape=(self.number_of_labels,self.number_of_labels)) 13 | def count_predicted(self, ground_truth, predicted, number_of_added_elements=1): 14 | self.confusion_matrix[ground_truth][predicted] += number_of_added_elements 15 | 16 | def count_predicted_batch(self, ground_truth_vec, predicted): # added 17 | for i in range(ground_truth_vec.shape[0]): 18 | self.confusion_matrix[:,predicted[i]] += ground_truth_vec[i,:] 19 | 20 | def count_predicted_batch_hard(self, ground_truth_vec, predicted): # added 21 | for i in range(ground_truth_vec.shape[0]): 22 | self.confusion_matrix[ground_truth_vec[i],predicted[i]] += 1 23 | 24 | """labels are integers from 0 to number_of_labels-1""" 25 | def get_count(self, ground_truth, predicted): 26 | return self.confusion_matrix[ground_truth][predicted] 27 | """returns list of lists of integers; use it as result[ground_truth][predicted] 28 | to know how many samples of class ground_truth were reported as class predicted""" 29 | def get_confusion_matrix(self): 30 | return self.confusion_matrix 31 | """returns list of 64-bit floats""" 32 | def get_intersection_union_per_class(self): 33 | matrix_diagonal = [self.confusion_matrix[i][i] for i in range(self.number_of_labels)] 34 | errors_summed_by_row = [0] * self.number_of_labels 35 | for row in range(self.number_of_labels): 36 | for column in range(self.number_of_labels): 37 | if row != column: 38 | errors_summed_by_row[row] += self.confusion_matrix[row][column] 39 | errors_summed_by_column = [0] * self.number_of_labels 40 | for column in range(self.number_of_labels): 41 | for row in range(self.number_of_labels): 42 | if row != column: 43 | errors_summed_by_column[column] += self.confusion_matrix[row][column] 44 | 45 | divisor = [0] * self.number_of_labels 46 | for i in range(self.number_of_labels): 47 | divisor[i] = matrix_diagonal[i] + errors_summed_by_row[i] + errors_summed_by_column[i] 48 | if matrix_diagonal[i] == 0: 49 | divisor[i] = 1 50 | 51 | return [float(matrix_diagonal[i]) / divisor[i] for i in range(self.number_of_labels)] 52 | """returns 64-bit float""" 53 | 54 | def get_overall_accuracy(self): 55 | matrix_diagonal = 0 56 | all_values = 0 57 | for row in range(self.number_of_labels): 58 | for column in range(self.number_of_labels): 59 | all_values += self.confusion_matrix[row][column] 60 | if row == column: 61 | matrix_diagonal += self.confusion_matrix[row][column] 62 | if all_values == 0: 63 | all_values = 1 64 | return float(matrix_diagonal) / all_values 65 | 66 | 67 | def get_average_intersection_union(self): 68 | values = self.get_intersection_union_per_class() 69 | class_seen = ((self.confusion_matrix.sum(1)+self.confusion_matrix.sum(0))!=0).sum() 70 | return sum(values) / class_seen 71 | 72 | def get_mean_class_accuracy(self): # added 73 | re = 0 74 | for i in range(self.number_of_labels): 75 | re = re + self.confusion_matrix[i][i] / max(1,np.sum(self.confusion_matrix[i,:])) 76 | return re/self.number_of_labels 77 | 78 | def count_gt(self, ground_truth): 79 | return self.confusion_matrix[ground_truth,:].sum() 80 | 81 | def compute_predicted_transitions(in_component, edg_source, edg_target): 82 | 83 | pred_transitions = in_component[edg_source] != in_component[edg_target] 84 | return pred_transitions 85 | 86 | #----------------------------------------------------------- 87 | def compute_boundary_recall(is_transition, pred_transitions): 88 | return 100*((is_transition==pred_transitions)*is_transition).sum()/is_transition.sum() 89 | 90 | #----------------------------------------------------------- 91 | def compute_boundary_precision(is_transition, pred_transitions): 92 | return 100*((is_transition==pred_transitions)*pred_transitions).sum()/pred_transitions.sum() 93 | #-------------------------------------------- 94 | 95 | def mode(array, only_freq=False): 96 | value, counts = np.unique(array, return_counts=True) 97 | if only_freq: 98 | return np.amax(counts) 99 | else: 100 | return value[np.argmax(counts)], np.amax(counts) 101 | #------------------------------------------------ 102 | def compute_OOA(components, labels): 103 | hard_labels = labels.argmax(1) 104 | correct_labels=0 105 | for comp in components: 106 | dump, freq = mode(hard_labels[comp]) 107 | correct_labels+=freq 108 | return 100*correct_labels/len(labels) 109 | -------------------------------------------------------------------------------- /util/provider.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import sys 4 | import random 5 | import glob 6 | from plyfile import PlyData, PlyElement 7 | import numpy as np 8 | from numpy import genfromtxt 9 | import h5py 10 | #import laspy 11 | from sklearn.neighbors import NearestNeighbors 12 | import colorsys 13 | 14 | def get_color_from_label(object_label, dataset): 15 | """associate the color corresponding to the class""" 16 | if dataset == 's3dis': #S3DIS 17 | object_label = { 18 | 0: [0 , 0, 0], #unlabelled .->. black 19 | 1: [ 233, 229, 107], #'ceiling' .-> .yellow 20 | 2: [ 95, 156, 196], #'floor' .-> . blue 21 | 3: [ 179, 116, 81], #'wall' -> brown 22 | 4: [ 81, 163, 148], #'column' -> bluegreen 23 | 5: [ 241, 149, 131], #'beam' -> salmon 24 | 6: [ 77, 174, 84], #'window' -> bright green 25 | 7: [ 108, 135, 75], #'door' -> dark green 26 | 8: [ 79, 79, 76], #'table' -> dark grey 27 | 9: [ 41, 49, 101], #'chair' -> darkblue 28 | 10: [223, 52, 52], #'bookcase' -> red 29 | 11: [ 89, 47, 95], #'sofa' -> purple 30 | 12: [ 81, 109, 114], #'board' -> grey 31 | 13: [233, 233, 229], #'clutter' -> light grey 32 | }.get(object_label, -1) 33 | elif (dataset == 'sema3d'): #Semantic3D 34 | object_label = { 35 | 0: [0 , 0, 0], #unlabelled .->. black 36 | 1: [ 200, 200, 200], #'man-made terrain' -> grey 37 | 2: [ 0, 70, 0], #'natural terrain' -> dark green 38 | 3: [ 0, 255, 0], #'high vegetation' -> bright green 39 | 4: [ 255, 255, 0], #'low vegetation' -> yellow 40 | 5: [ 255, 0, 0], #'building' -> red 41 | 6: [ 148, 0, 211], #'hard scape' -> violet 42 | 7: [ 0, 255, 255], #'artifact' -> cyan 43 | 8: [ 255, 8, 127], #'cars' -> pink 44 | }.get(object_label, -1) 45 | elif (dataset == 'custom_dataset'): #Custom set 46 | object_label = { 47 | 0: [0 , 0, 0], #unlabelled .->. black 48 | 1: [ 255, 0, 0], #'classe A' -> red 49 | 2: [ 0, 255, 0], #'classeB' -> green 50 | }.get(object_label, -1) 51 | else: 52 | raise ValueError('Unknown dataset: %s' % (dataset)) 53 | if object_label == -1: 54 | raise ValueError('Type not recognized: %s' % (object_label)) 55 | return object_label 56 | 57 | def write_components(file_name, components, in_component,xyz,rgb): 58 | """save the partition and spg information""" 59 | if os.path.isfile(file_name): 60 | os.remove(file_name) 61 | #print(file_name) 62 | data_file = h5py.File(file_name, 'w') 63 | grp = data_file.create_group('components') 64 | n_com = len(components) 65 | for i_com in range(0, n_com): 66 | grp.create_dataset(str(i_com), data=components[i_com], dtype='uint32') 67 | data_file.create_dataset('in_component', data=in_component, dtype='uint32') 68 | data_file.create_dataset('xyz', data=xyz, dtype='float32') 69 | data_file.create_dataset('rgb', data=rgb, dtype='uint32') 70 | 71 | def write_pruned_spg(file_name, xyz,rgb,labels): 72 | """save the partition and spg information""" 73 | if os.path.isfile(file_name): 74 | os.remove(file_name) 75 | print(file_name) 76 | data_file = h5py.File(file_name, 'w') 77 | data_file.create_dataset('xyz' 78 | , data=xyz, dtype='float32') 79 | data_file.create_dataset('rgb' 80 | , data=rgb, dtype='uint32') 81 | data_file.create_dataset('labels' 82 | , data=labels, dtype='uint32') 83 | 84 | 85 | def partition2ply(filename, xyz, components): 86 | """write a ply with random colors for each components""" 87 | random_color = lambda: random.randint(0, 255) 88 | color = np.zeros(xyz.shape) 89 | for i_com in range(0, len(components)): 90 | color[components[i_com], :] = [random_color(), random_color() 91 | , random_color()] 92 | prop = [('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1') 93 | , ('green', 'u1'), ('blue', 'u1')] 94 | vertex_all = np.empty(len(xyz), dtype=prop) 95 | for i in range(0, 3): 96 | vertex_all[prop[i][0]] = xyz[:, i] 97 | for i in range(0, 3): 98 | vertex_all[prop[i+3][0]] = color[:, i] 99 | ply = PlyData([PlyElement.describe(vertex_all, 'vertex')], text=True) 100 | ply.write(filename) 101 | 102 | def prediction2ply(filename, xyz, prediction, n_label, dataset): 103 | """write a ply with colors for each class""" 104 | if len(prediction.shape) > 1 and prediction.shape[1] > 1: 105 | prediction = np.argmax(prediction, axis = 1) 106 | color = np.zeros(xyz.shape) 107 | for i_label in range(0, n_label + 1): 108 | color[np.where(prediction == i_label), :] = get_color_from_label(i_label, dataset) 109 | prop = [('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')] 110 | vertex_all = np.empty(len(xyz), dtype=prop) 111 | for i in range(0, 3): 112 | vertex_all[prop[i][0]] = xyz[:, i] 113 | for i in range(0, 3): 114 | vertex_all[prop[i+3][0]] = color[:, i] 115 | ply = PlyData([PlyElement.describe(vertex_all, 'vertex')], text=True) 116 | ply.write(filename) 117 | 118 | 119 | def write_ply(filename, xyz, rgb): 120 | """write into a ply file""" 121 | prop = [('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')] 122 | vertex_all = np.empty(len(xyz), dtype=prop) 123 | for i_prop in range(0, 3): 124 | vertex_all[prop[i_prop][0]] = xyz[:, i_prop] 125 | for i_prop in range(0, 3): 126 | vertex_all[prop[i_prop+3][0]] = rgb[:, i_prop] 127 | ply = PlyData([PlyElement.describe(vertex_all, 'vertex')], text=True) 128 | ply.write(filename) -------------------------------------------------------------------------------- /util/transform.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import torch 4 | 5 | 6 | class Compose(object): 7 | def __init__(self, transforms): 8 | self.transforms = transforms 9 | 10 | def __call__(self, data, label): 11 | for t in self.transforms: 12 | data, label = t(data, label) 13 | return data, label 14 | 15 | class Compose_withIDX(object): 16 | def __init__(self, transforms): 17 | self.transforms = transforms 18 | 19 | def __call__(self, data, label, l1, l2, l3, l4): 20 | for t in self.transforms: 21 | data, label, l1, l2, l3, l4 = t(data, label, l1, l2, l3, l4) 22 | return data, label, l1, l2, l3, l4 23 | 24 | class ToTensor(object): 25 | def __call__(self, data, label): 26 | data = torch.from_numpy(data) 27 | if not isinstance(data, torch.FloatTensor): 28 | data = data.float() 29 | label = torch.from_numpy(label) 30 | if not isinstance(label, torch.LongTensor): 31 | label = label.long() 32 | return data, label 33 | 34 | class ToTensor_withIDX(object): 35 | def __call__(self, data, label, l1, l2, l3, l4): 36 | data = torch.from_numpy(data) 37 | if not isinstance(data, torch.FloatTensor): 38 | data = data.float() 39 | 40 | label = torch.from_numpy(label) 41 | if not isinstance(label, torch.LongTensor): 42 | label = label.long() 43 | 44 | if l1 is not None: 45 | l1 = torch.from_numpy(l1) 46 | if not isinstance(l1, torch.IntTensor): 47 | l1 = l1.int() 48 | 49 | if l2 is not None: 50 | l2 = torch.from_numpy(l2) 51 | if not isinstance(l2, torch.IntTensor): 52 | l2 = l2.int() 53 | 54 | if l3 is not None: 55 | l3 = torch.from_numpy(l3) 56 | if not isinstance(l3, torch.IntTensor): 57 | l3 = l3.int() 58 | if l4 is not None: 59 | l4 = torch.from_numpy(l4) 60 | if not isinstance(l4, torch.IntTensor): 61 | l4 = l4.int() 62 | 63 | 64 | return data, label, l1, l2, l3, l4 65 | 66 | 67 | class RandomRotate(object): 68 | def __init__(self, rotate_angle=None, along_z=False): 69 | self.rotate_angle = rotate_angle 70 | self.along_z = along_z 71 | 72 | def __call__(self, data, label): 73 | if self.rotate_angle is None: 74 | rotate_angle = np.random.uniform() * 2 * np.pi 75 | else: 76 | rotate_angle = self.rotate_angle 77 | cosval, sinval = np.cos(rotate_angle), np.sin(rotate_angle) 78 | if self.along_z: 79 | rotation_matrix = np.array([[cosval, sinval, 0], [-sinval, cosval, 0], [0, 0, 1]]) 80 | else: 81 | rotation_matrix = np.array([[cosval, 0, sinval], [0, 1, 0], [-sinval, 0, cosval]]) 82 | data[:, 0:3] = np.dot(data[:, 0:3], rotation_matrix) 83 | if data.shape[1] > 3: # use normal 84 | data[:, 3:6] = np.dot(data[:, 3:6], rotation_matrix) 85 | return data, label 86 | 87 | 88 | class RandomRotatePerturbation(object): 89 | def __init__(self, angle_sigma=0.06, angle_clip=0.18): 90 | self.angle_sigma = angle_sigma 91 | self.angle_clip = angle_clip 92 | 93 | def __call__(self, data, label): 94 | angles = np.clip(self.angle_sigma*np.random.randn(3), -self.angle_clip, self.angle_clip) 95 | Rx = np.array([[1, 0, 0], 96 | [0, np.cos(angles[0]), -np.sin(angles[0])], 97 | [0, np.sin(angles[0]), np.cos(angles[0])]]) 98 | Ry = np.array([[np.cos(angles[1]), 0, np.sin(angles[1])], 99 | [0, 1, 0], 100 | [-np.sin(angles[1]), 0, np.cos(angles[1])]]) 101 | Rz = np.array([[np.cos(angles[2]), -np.sin(angles[2]), 0], 102 | [np.sin(angles[2]), np.cos(angles[2]), 0], 103 | [0, 0, 1]]) 104 | R = np.dot(Rz, np.dot(Ry, Rx)) 105 | data[:, 0:3] = np.dot(data[:, 0:3], R) 106 | if data.shape[1] > 3: # use normal 107 | data[:, 3:6] = np.dot(data[:, 3:6], R) 108 | return data, label 109 | 110 | 111 | class RandomScale(object): 112 | def __init__(self, scale_low=0.8, scale_high=1.25): 113 | self.scale_low = scale_low 114 | self.scale_high = scale_high 115 | 116 | def __call__(self, data, label): 117 | scale = np.random.uniform(self.scale_low, self.scale_high) 118 | data[:, 0:3] *= scale 119 | return data, label 120 | 121 | 122 | class RandomShift(object): 123 | def __init__(self, shift_range=0.1): 124 | self.shift_range = shift_range 125 | 126 | def __call__(self, data, label): 127 | shift = np.random.uniform(-self.shift_range, self.shift_range, 3) 128 | data[:, 0:3] += shift 129 | return data, label 130 | 131 | 132 | class RandomJitter(object): 133 | def __init__(self, sigma=0.01, clip=0.05): 134 | self.sigma = sigma 135 | self.clip = clip 136 | 137 | def __call__(self, data, label): 138 | assert (self.clip > 0) 139 | jitter = np.clip(self.sigma * np.random.randn(data.shape[0], 3), -1 * self.clip, self.clip) 140 | data[:, 0:3] += jitter 141 | return data, label 142 | --------------------------------------------------------------------------------