├── LICENSE
├── README.md
├── configs
├── __init__.py
├── config_files
│ ├── ISCNet.yaml
│ ├── ISCNet_completion.yaml
│ ├── ISCNet_detection.yaml
│ └── ISCNet_test.yaml
├── config_utils.py
├── path_config.py
└── scannet_config.py
├── datasets
├── scannet
│ ├── raw_lablemap_to_synsetoffset.pkl
│ ├── scannet_means.npz
│ └── scannetv2-labels.combined.tsv
└── splits
│ ├── fullscan
│ ├── scannetv2_test.json
│ ├── scannetv2_train.json
│ └── scannetv2_val.json
│ └── scannet
│ ├── scannetv2_train.txt
│ └── scannetv2_val.txt
├── demo.py
├── demo
├── inputs
│ ├── scene0549_00.off
│ └── scene0575_00.off
├── outputs
│ ├── scene0549_00
│ │ ├── 000000_pc.ply
│ │ ├── 000000_pred_confident_nms_bbox.npz
│ │ ├── pred.png
│ │ ├── proposal_107_mesh.ply
│ │ ├── proposal_113_mesh.ply
│ │ ├── proposal_118_mesh.ply
│ │ ├── proposal_200_mesh.ply
│ │ ├── proposal_201_mesh.ply
│ │ ├── proposal_225_mesh.ply
│ │ ├── proposal_22_mesh.ply
│ │ ├── proposal_230_mesh.ply
│ │ ├── proposal_232_mesh.ply
│ │ ├── proposal_253_mesh.ply
│ │ ├── proposal_38_mesh.ply
│ │ ├── proposal_97_mesh.ply
│ │ └── proposal_99_mesh.ply
│ └── scene0575_00
│ │ ├── 000000_pc.ply
│ │ ├── 000000_pred_confident_nms_bbox.npz
│ │ ├── pred.png
│ │ ├── proposal_133_mesh.ply
│ │ ├── proposal_139_mesh.ply
│ │ ├── proposal_147_mesh.ply
│ │ ├── proposal_159_mesh.ply
│ │ ├── proposal_163_mesh.ply
│ │ ├── proposal_182_mesh.ply
│ │ ├── proposal_188_mesh.ply
│ │ ├── proposal_196_mesh.ply
│ │ ├── proposal_221_mesh.ply
│ │ ├── proposal_228_mesh.ply
│ │ ├── proposal_233_mesh.ply
│ │ ├── proposal_24_mesh.ply
│ │ ├── proposal_253_mesh.ply
│ │ ├── proposal_25_mesh.ply
│ │ └── proposal_97_mesh.ply
└── screenshots
│ ├── screenshot_demo.png
│ └── screenshot_scan2cad.png
├── environment.yml
├── external
├── binvox_rw.py
├── common.py
├── libkdtree
│ ├── .travis.yml
│ ├── LICENSE.txt
│ ├── MANIFEST.in
│ ├── Makefile
│ ├── README
│ ├── README.rst
│ ├── appveyor.yml
│ ├── appveyor
│ │ ├── install.ps1
│ │ ├── missing-headers.ps1
│ │ └── run_with_compiler.cmd
│ ├── pykdtree
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ └── __init__.cpython-36.pyc
│ │ ├── _kdtree_core.c
│ │ ├── _kdtree_core.c.mako
│ │ ├── kdtree.c
│ │ ├── kdtree.cpython-36m-x86_64-linux-gnu.so
│ │ ├── kdtree.pyx
│ │ ├── render_template.py
│ │ └── test_tree.py
│ ├── scripts
│ │ └── build-manylinux-wheels.sh
│ ├── setup.cfg
│ └── setup.py
├── libmesh
│ ├── .gitignore
│ ├── __init__.py
│ ├── inside_mesh.py
│ ├── triangle_hash.cpython-36m-x86_64-linux-gnu.so
│ └── triangle_hash.pyx
├── libmise
│ ├── .gitignore
│ ├── __init__.py
│ ├── __pycache__
│ │ └── __init__.cpython-36.pyc
│ ├── mise.cpython-36m-x86_64-linux-gnu.so
│ ├── mise.pyx
│ └── test.py
├── librender
│ ├── __init__.py
│ ├── build
│ │ └── temp.linux-x86_64-3.6
│ │ │ ├── offscreen.o
│ │ │ └── pyrender.o
│ ├── offscreen.cpp
│ ├── offscreen.h
│ ├── pyrender.cpp
│ ├── pyrender.cpython-36m-x86_64-linux-gnu.so
│ ├── pyrender.pyx
│ ├── setup.py
│ └── test.py
├── libsimplify
│ ├── Simplify.h
│ ├── __init__.py
│ ├── __pycache__
│ │ └── __init__.cpython-36.pyc
│ ├── simplify_mesh.cpp
│ ├── simplify_mesh.cpython-36m-x86_64-linux-gnu.so
│ ├── simplify_mesh.pyx
│ └── test.py
├── libvoxelize
│ ├── .gitignore
│ ├── __init__.py
│ ├── tribox2.h
│ ├── voxelize.cpython-36m-x86_64-linux-gnu.so
│ └── voxelize.pyx
├── pointnet2_ops_lib
│ ├── MANIFEST.in
│ ├── pointnet2_ops
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-36.pyc
│ │ │ ├── pointnet2_modules.cpython-36.pyc
│ │ │ └── pointnet2_utils.cpython-36.pyc
│ │ ├── _ext-src
│ │ │ ├── include
│ │ │ │ ├── ball_query.h
│ │ │ │ ├── cuda_utils.h
│ │ │ │ ├── group_points.h
│ │ │ │ ├── interpolate.h
│ │ │ │ ├── sampling.h
│ │ │ │ └── utils.h
│ │ │ └── src
│ │ │ │ ├── ball_query.cpp
│ │ │ │ ├── ball_query_gpu.cu
│ │ │ │ ├── bindings.cpp
│ │ │ │ ├── group_points.cpp
│ │ │ │ ├── group_points_gpu.cu
│ │ │ │ ├── interpolate.cpp
│ │ │ │ ├── interpolate_gpu.cu
│ │ │ │ ├── sampling.cpp
│ │ │ │ └── sampling_gpu.cu
│ │ ├── _version.py
│ │ ├── pointnet2_modules.py
│ │ ├── pointnet2_utils.py
│ │ └── pytorch_utils.py
│ └── setup.py
├── pyTorchChamferDistance
│ ├── .gitignore
│ ├── LICENSE.md
│ ├── README.md
│ └── chamfer_distance
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ └── chamfer_distance.cpython-36.pyc
│ │ ├── chamfer_distance.cpp
│ │ ├── chamfer_distance.cu
│ │ └── chamfer_distance.py
├── pyfusion
│ ├── .gitignore
│ ├── CMakeLists.txt
│ ├── LICENSE
│ ├── README.md
│ ├── __init__.py
│ ├── cyfusion.cpython-36m-x86_64-linux-gnu.so
│ ├── cyfusion.pyx
│ ├── fusion.cpp
│ ├── fusion.cu
│ ├── fusion.h
│ ├── fusion_zach_tvl1.cu
│ ├── gpu_common.h
│ └── setup.py
├── pyrender
│ ├── .gitignore
│ ├── README.md
│ ├── offscreen.cpp
│ ├── offscreen.h
│ ├── pyrender.pyx
│ └── setup.py
└── voxels.py
├── main.py
├── models
├── __init__.py
├── datasets.py
├── iscnet
│ ├── __init__.py
│ ├── config.py
│ ├── dataloader.py
│ ├── modules
│ │ ├── __init__.py
│ │ ├── encoder_latent.py
│ │ ├── generator.py
│ │ ├── layers.py
│ │ ├── network.py
│ │ ├── occ_decoder.py
│ │ ├── occupancy_net.py
│ │ ├── pointnet2backbone.py
│ │ ├── pointseg.py
│ │ ├── proposal_module.py
│ │ ├── skip_propagation.py
│ │ └── vote_module.py
│ ├── testing.py
│ └── training.py
├── loss.py
├── network.py
├── optimizers.py
├── registers.py
├── testing.py
└── training.py
├── net_utils
├── __init__.py
├── ap_helper.py
├── box_util.py
├── eval_det.py
├── libs.py
├── metric_util.py
├── nms.py
├── nn_distance.py
├── registry.py
├── transforms.py
├── utils.py
└── visualization.py
├── out
└── samples
│ ├── scene0001_00
│ └── verify.png
│ └── scene0549_00
│ ├── camera_center
│ ├── gt.png
│ ├── points.png
│ ├── pred.png
│ └── verify.png
├── requirements.txt
├── setup.py
├── test.py
├── test_epoch.py
├── train.py
├── train_epoch.py
└── utils
├── __init__.py
├── clean_log.py
├── pc_util.py
├── read_and_write.py
├── scannet
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ ├── load_scannet_data.cpython-36.pyc
│ ├── scannet_utils.cpython-36.pyc
│ └── tools.cpython-36.pyc
├── gen_scannet_w_orientation.py
├── load_scannet_data.py
├── scannet_utils.py
├── split_data.py
├── tools.py
└── visualization
│ ├── __init__.py
│ ├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── vis_scannet.cpython-36.pyc
│ ├── vis_for_comparison.py
│ ├── vis_for_demo.py
│ ├── vis_gt.py
│ ├── vis_prediction.py
│ ├── vis_scan2cad.py
│ └── vis_scannet.py
└── shapenet
├── 1_fuse_shapenetv2.py
├── 2_sample_mesh.py
├── 3_simplify_fusion.py
├── __init__.py
├── __pycache__
├── __init__.cpython-36.pyc
└── common.cpython-36.pyc
├── common.py
├── simplification.mlx
└── tools.py
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Yinyu Nie
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/configs/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/configs/__init__.py
--------------------------------------------------------------------------------
/configs/config_files/ISCNet.yaml:
--------------------------------------------------------------------------------
1 | method: ISCNet
2 | resume: False
3 | finetune: True
4 | weight: ['out/iscnet/2021-03-30T22:48:41.879548/model_best.pth']
5 | seed: 10
6 | device:
7 | use_gpu: True
8 | gpu_ids: '0,1'
9 | num_workers: 8
10 | data:
11 | dataset: scannet
12 | split: datasets/splits/fullscan
13 | num_point: 80000
14 | num_target: 256
15 | vote_factor: 1
16 | cluster_sampling: vote_fps
17 | ap_iou_thresh: 0.25
18 | no_height: False
19 | use_color_detection: False
20 | use_color_completion: False
21 | shapenet_path: datasets/ShapeNetv2_data
22 | points_unpackbits: True
23 | points_subsample: [1024, 1024]
24 | hidden_dim: 512
25 | c_dim: 512
26 | z_dim: 32
27 | threshold: 0.5
28 | completion_limit_in_train: 10
29 | use_cls_for_completion: False
30 | skip_propagate: True
31 | model:
32 | backbone:
33 | method: Pointnet2Backbone
34 | loss: Null
35 | voting:
36 | method: VotingModule
37 | loss: Null
38 | detection:
39 | method: ProposalModule
40 | loss: DetectionLoss
41 | skip_propagation:
42 | method: SkipPropagation
43 | loss: Null
44 | completion:
45 | method: ONet
46 | loss: ONet_Loss
47 | weight: 0.005
48 | optimizer:
49 | method: Adam
50 | lr: 5e-5
51 | betas: [0.9, 0.999]
52 | eps: 1e-08
53 | weight_decay: 0
54 | scheduler:
55 | patience: 20
56 | factor: 0.1
57 | threshold: 0.01
58 | bnscheduler:
59 | bn_decay_step: 20
60 | bn_decay_rate: 0.5
61 | bn_momentum_init: 0.5
62 | bn_momentum_max: 0.001
63 | train:
64 | epochs: 240
65 | phase: 'completion'
66 | freeze: []
67 | batch_size: 8
68 | val:
69 | phase: 'completion'
70 | batch_size: 8
71 | use_cls_nms: True
72 | use_3d_nms: True
73 | ap_iou_thresholds: [0.25, 0.5]
74 | faster_eval: True
75 | nms_iou: 0.25
76 | use_old_type_nms: False
77 | per_class_proposal: True
78 | conf_thresh: 0.05
79 | demo:
80 | phase: 'completion'
81 | log:
82 | vis_path: visualization
83 | save_results: True
84 | vis_step: 500
85 | print_step: 10
86 | path: out/iscnet
87 |
--------------------------------------------------------------------------------
/configs/config_files/ISCNet_completion.yaml:
--------------------------------------------------------------------------------
1 | method: ISCNet
2 | resume: False
3 | finetune: True
4 | weight: ['out/iscnet/2021-03-28T15:52:57.350715/model_best.pth']
5 | seed: 10
6 | device:
7 | use_gpu: True
8 | gpu_ids: '0,1'
9 | num_workers: 8
10 | data:
11 | dataset: scannet
12 | split: datasets/splits/fullscan
13 | num_point: 80000
14 | num_target: 256
15 | vote_factor: 1
16 | cluster_sampling: vote_fps
17 | ap_iou_thresh: 0.25
18 | no_height: False
19 | use_color_detection: False
20 | use_color_completion: False
21 | shapenet_path: datasets/ShapeNetv2_data
22 | points_unpackbits: True
23 | points_subsample: [1024, 1024]
24 | hidden_dim: 512
25 | c_dim: 512
26 | z_dim: 32
27 | threshold: 0.5
28 | completion_limit_in_train: 10
29 | use_cls_for_completion: False
30 | skip_propagate: True
31 | model:
32 | backbone:
33 | method: Pointnet2Backbone
34 | loss: Null
35 | voting:
36 | method: VotingModule
37 | loss: Null
38 | detection:
39 | method: ProposalModule
40 | loss: DetectionLoss
41 | skip_propagation:
42 | method: SkipPropagation
43 | loss: Null
44 | completion:
45 | method: ONet
46 | loss: ONet_Loss
47 | weight: 1
48 | optimizer:
49 | method: Adam
50 | lr: 1e-4
51 | betas: [0.9, 0.999]
52 | eps: 1e-08
53 | weight_decay: 0
54 | scheduler:
55 | patience: 20
56 | factor: 0.1
57 | threshold: 0.01
58 | bnscheduler:
59 | bn_decay_step: 20
60 | bn_decay_rate: 0.5
61 | bn_momentum_init: 0.5
62 | bn_momentum_max: 0.001
63 | train:
64 | epochs: 240
65 | phase: 'completion'
66 | freeze: ['backbone', 'voting', 'detection']
67 | batch_size: 8
68 | val:
69 | phase: 'completion'
70 | batch_size: 8
71 | use_cls_nms: True
72 | use_3d_nms: True
73 | ap_iou_thresholds: [0.25, 0.5]
74 | faster_eval: True
75 | nms_iou: 0.25
76 | use_old_type_nms: False
77 | per_class_proposal: True
78 | conf_thresh: 0.05
79 | demo:
80 | phase: 'completion'
81 | log:
82 | vis_path: visualization
83 | save_results: True
84 | vis_step: 500
85 | print_step: 10
86 | path: out/iscnet
87 |
--------------------------------------------------------------------------------
/configs/config_files/ISCNet_detection.yaml:
--------------------------------------------------------------------------------
1 | method: ISCNet
2 | resume: False
3 | finetune: False
4 | weight: []
5 | seed: 10
6 | device:
7 | use_gpu: True
8 | gpu_ids: '0,1'
9 | num_workers: 8
10 | data:
11 | dataset: scannet
12 | split: datasets/splits/fullscan
13 | num_point: 80000
14 | num_target: 256
15 | vote_factor: 1
16 | cluster_sampling: vote_fps
17 | ap_iou_thresh: 0.25
18 | no_height: False
19 | use_color_detection: False
20 | use_color_completion: False
21 | shapenet_path: datasets/ShapeNetv2_data
22 | points_unpackbits: True
23 | points_subsample: [1024, 1024]
24 | hidden_dim: 512
25 | c_dim: 512
26 | z_dim: 32
27 | threshold: 0.5
28 | completion_limit_in_train: 10
29 | use_cls_for_completion: False
30 | skip_propagate: True
31 | model:
32 | backbone:
33 | method: Pointnet2Backbone
34 | loss: Null
35 | voting:
36 | method: VotingModule
37 | loss: Null
38 | detection:
39 | method: ProposalModule
40 | loss: DetectionLoss
41 | skip_propagation:
42 | method: SkipPropagation
43 | loss: Null
44 | completion:
45 | method: ONet
46 | loss: ONet_Loss
47 | weight: 1
48 | optimizer:
49 | method: Adam
50 | lr: 1e-3
51 | betas: [0.9, 0.999]
52 | eps: 1e-08
53 | weight_decay: 0
54 | scheduler:
55 | patience: 20
56 | factor: 0.1
57 | threshold: 0.01
58 | bnscheduler:
59 | bn_decay_step: 20
60 | bn_decay_rate: 0.5
61 | bn_momentum_init: 0.5
62 | bn_momentum_max: 0.001
63 | train:
64 | epochs: 240
65 | phase: 'detection'
66 | freeze: []
67 | batch_size: 8
68 | val:
69 | phase: 'detection'
70 | batch_size: 8
71 | use_cls_nms: True
72 | use_3d_nms: True
73 | ap_iou_thresholds: [0.25, 0.5]
74 | faster_eval: True
75 | nms_iou: 0.25
76 | use_old_type_nms: False
77 | per_class_proposal: True
78 | conf_thresh: 0.05
79 | demo:
80 | phase: 'detection'
81 | log:
82 | vis_path: visualization
83 | save_results: True
84 | vis_step: 500
85 | print_step: 10
86 | path: out/iscnet
87 |
--------------------------------------------------------------------------------
/configs/config_files/ISCNet_test.yaml:
--------------------------------------------------------------------------------
1 | method: ISCNet
2 | resume: False
3 | finetune: True
4 | weight: ['out/pretrained_models/pretrained_weight.pth']
5 | seed: 10
6 | device:
7 | use_gpu: True
8 | gpu_ids: '0'
9 | num_workers: 0
10 | data:
11 | dataset: scannet
12 | split: datasets/splits/fullscan
13 | num_point: 80000
14 | num_target: 256
15 | vote_factor: 1
16 | cluster_sampling: seed_fps
17 | ap_iou_thresh: 0.25
18 | no_height: False
19 | use_color_detection: False
20 | use_color_completion: False
21 | shapenet_path: datasets/ShapeNetv2_data
22 | points_unpackbits: True
23 | points_subsample: [1024, 1024]
24 | hidden_dim: 512
25 | c_dim: 512
26 | z_dim: 32
27 | threshold: 0.5
28 | completion_limit_in_train: 10
29 | use_cls_for_completion: False
30 | skip_propagate: True
31 | model:
32 | backbone:
33 | method: Pointnet2Backbone
34 | loss: Null
35 | voting:
36 | method: VotingModule
37 | loss: Null
38 | detection:
39 | method: ProposalModule
40 | loss: DetectionLoss
41 | skip_propagation:
42 | method: SkipPropagation
43 | loss: Null
44 | completion:
45 | method: ONet
46 | loss: ONet_Loss
47 | weight: 0.005
48 | test:
49 | phase: 'completion'
50 | batch_size: 1
51 | use_cls_nms: True
52 | use_3d_nms: True
53 | ap_iou_thresholds: [0.5]
54 | faster_eval: False
55 | nms_iou: 0.25
56 | use_old_type_nms: False
57 | per_class_proposal: True
58 | conf_thresh: 0.05
59 | evaluate_mesh_mAP: False
60 | generation:
61 | generate_mesh: True
62 | resolution_0: 32
63 | upsampling_steps: 0
64 | use_sampling: False
65 | refinement_step: 0
66 | simplify_nfaces: Null
67 | dump_threshold: 0.5
68 | dump_results: True
69 | demo:
70 | phase: 'completion'
71 | log:
72 | vis_path: visualization
73 | save_results: True
74 | vis_step: 100
75 | print_step: 10
76 | path: out/iscnet
77 |
--------------------------------------------------------------------------------
/configs/path_config.py:
--------------------------------------------------------------------------------
1 | '''
2 | Path configs for the whole project.
3 | author: ynie
4 | date: July, 2020
5 | '''
6 | import os
7 | from glob import glob
8 | import pickle
9 |
10 | import numpy as np
11 | from utils.scannet.scannet_utils import read_label_mapping
12 |
13 | SHAPENETCLASSES = ['void',
14 | 'table', 'jar', 'skateboard', 'car', 'bottle',
15 | 'tower', 'chair', 'bookshelf', 'camera', 'airplane',
16 | 'laptop', 'basket', 'sofa', 'knife', 'can',
17 | 'rifle', 'train', 'pillow', 'lamp', 'trash_bin',
18 | 'mailbox', 'watercraft', 'motorbike', 'dishwasher', 'bench',
19 | 'pistol', 'rocket', 'loudspeaker', 'file cabinet', 'bag',
20 | 'cabinet', 'bed', 'birdhouse', 'display', 'piano',
21 | 'earphone', 'telephone', 'stove', 'microphone', 'bus',
22 | 'mug', 'remote', 'bathtub', 'bowl', 'keyboard',
23 | 'guitar', 'washer', 'bicycle', 'faucet', 'printer',
24 | 'cap', 'clock', 'helmet', 'flowerpot', 'microwaves']
25 |
26 | ScanNet_OBJ_CLASS_IDS = np.array([ 1, 7, 8, 13, 20, 31, 34, 43])
27 | ShapeNetIDMap = {'4379243': 'table', '3593526': 'jar', '4225987': 'skateboard', '2958343': 'car', '2876657': 'bottle', '4460130': 'tower', '3001627': 'chair', '2871439': 'bookshelf', '2942699': 'camera', '2691156': 'airplane', '3642806': 'laptop', '2801938': 'basket', '4256520': 'sofa', '3624134': 'knife', '2946921': 'can', '4090263': 'rifle', '4468005': 'train', '3938244': 'pillow', '3636649': 'lamp', '2747177': 'trash_bin', '3710193': 'mailbox', '4530566': 'watercraft', '3790512': 'motorbike', '3207941': 'dishwasher', '2828884': 'bench', '3948459': 'pistol', '4099429': 'rocket', '3691459': 'loudspeaker', '3337140': 'file cabinet', '2773838': 'bag', '2933112': 'cabinet', '2818832': 'bed', '2843684': 'birdhouse', '3211117': 'display', '3928116': 'piano', '3261776': 'earphone', '4401088': 'telephone', '4330267': 'stove', '3759954': 'microphone', '2924116': 'bus', '3797390': 'mug', '4074963': 'remote', '2808440': 'bathtub', '2880940': 'bowl', '3085013': 'keyboard', '3467517': 'guitar', '4554684': 'washer', '2834778': 'bicycle', '3325088': 'faucet', '4004475': 'printer', '2954340': 'cap', '3046257': 'clock', '3513137': 'helmet', '3991062': 'flowerpot', '3761084': 'microwaves'}
28 |
29 | class PathConfig(object):
30 | def __init__(self, dataset):
31 | if dataset == 'scannet':
32 | self.metadata_root = 'datasets/scannet'
33 | self.split_files = ['datasets/splits/scannet/scannetv2_train.txt',
34 | 'datasets/splits/scannet/scannetv2_val.txt']
35 | all_scenes = []
36 | for split_file in self.split_files:
37 | all_scenes += list(np.loadtxt(split_file, dtype=str))
38 |
39 | scene_paths = np.sort(glob(os.path.join(self.metadata_root, 'scans', '*')))
40 | self.scene_paths = [scene_path for scene_path in scene_paths if os.path.basename(scene_path) in all_scenes]
41 | self.scan2cad_annotation_path = os.path.join(self.metadata_root, 'scan2cad_download_link/full_annotations.json')
42 | self.processed_data_path = os.path.join(self.metadata_root, 'processed_data')
43 |
44 | label_type = 'synsetoffset'
45 | self.raw_label_map_file = os.path.join(self.metadata_root, 'raw_lablemap_to_' + label_type + '.pkl')
46 | self.OBJ_CLASS_IDS = ScanNet_OBJ_CLASS_IDS
47 |
48 | if not os.path.exists(self.raw_label_map_file):
49 | LABEL_MAP_FILE = os.path.join(self.metadata_root, 'scannetv2-labels.combined.tsv')
50 | assert os.path.exists(LABEL_MAP_FILE)
51 | raw_label_map = read_label_mapping(LABEL_MAP_FILE, label_from='raw_category', label_to=label_type)
52 | label_map = {}
53 | for key, item in raw_label_map.items():
54 | if item in ShapeNetIDMap:
55 | label_map[key] = SHAPENETCLASSES.index(ShapeNetIDMap[item])
56 | else:
57 | label_map[key] = 0
58 | with open(self.raw_label_map_file, 'wb') as file:
59 | pickle.dump(label_map, file)
60 |
61 | if not os.path.exists(self.processed_data_path):
62 | os.mkdir(self.processed_data_path)
63 |
64 | if __name__ == '__main__':
65 | path_config = PathConfig('scannet')
66 | print(path_config.scene_paths)
67 |
--------------------------------------------------------------------------------
/configs/scannet_config.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Facebook, Inc. and its affiliates.
2 | #
3 | # This source code is licensed under the MIT license found in the
4 | # LICENSE file in the root directory of this source tree.
5 |
6 | import numpy as np
7 | from configs.path_config import SHAPENETCLASSES
8 | from configs.path_config import ScanNet_OBJ_CLASS_IDS as OBJ_CLASS_IDS
9 | import torch
10 |
11 | class ScannetConfig(object):
12 | def __init__(self):
13 | self.num_class = len(OBJ_CLASS_IDS)
14 | self.num_heading_bin = 12
15 | self.num_size_cluster = len(OBJ_CLASS_IDS)
16 |
17 | self.type2class = {SHAPENETCLASSES[cls]:index for index, cls in enumerate(OBJ_CLASS_IDS)}
18 | self.class2type = {self.type2class[t]: t for t in self.type2class}
19 | self.class_ids = OBJ_CLASS_IDS
20 | self.shapenetid2class = {class_id: i for i, class_id in enumerate(list(self.class_ids))}
21 | self.mean_size_arr = np.load('datasets/scannet/scannet_means.npz')['arr_0']
22 | self.type_mean_size = {}
23 | self.data_path = 'datasets/scannet/processed_data'
24 | for i in range(self.num_size_cluster):
25 | self.type_mean_size[self.class2type[i]] = self.mean_size_arr[i, :]
26 |
27 | def angle2class(self, angle):
28 | ''' Convert continuous angle to discrete class
29 | [optinal] also small regression number from
30 | class center angle to current angle.
31 |
32 | angle is from 0-2pi (or -pi~pi), class center at 0, 1*(2pi/N), 2*(2pi/N) ... (N-1)*(2pi/N)
33 | return is class of int32 of 0,1,...,N-1 and a number such that
34 | class*(2pi/N) + number = angle
35 | '''
36 | num_class = self.num_heading_bin
37 | angle = angle % (2 * np.pi)
38 | assert False not in (angle >= 0) * (angle <= 2 * np.pi)
39 | angle_per_class = 2 * np.pi / float(num_class)
40 | shifted_angle = (angle + angle_per_class / 2) % (2 * np.pi)
41 | class_id = np.int16(shifted_angle / angle_per_class)
42 | residual_angle = shifted_angle - (class_id * angle_per_class + angle_per_class / 2)
43 | return class_id, residual_angle
44 |
45 | def class2angle(self, pred_cls, residual, to_label_format=True):
46 | ''' Inverse function to angle2class '''
47 | num_class = self.num_heading_bin
48 | angle_per_class = 2*np.pi/float(num_class)
49 | angle_center = pred_cls * angle_per_class
50 | angle = angle_center + residual
51 | if to_label_format and angle>np.pi:
52 | angle = angle - 2*np.pi
53 | return angle
54 |
55 | def class2angle_cuda(self, pred_cls, residual, to_label_format=True):
56 | ''' Inverse function to angle2class.'''
57 | num_class = self.num_heading_bin
58 | angle_per_class = 2 * np.pi / float(num_class)
59 | angle_center = pred_cls.float() * angle_per_class
60 | angle = angle_center + residual
61 | if to_label_format:
62 | angle = angle - 2*np.pi*(angle>np.pi).float()
63 | return angle
64 |
65 | def size2class(self, size, type_name):
66 | ''' Convert 3D box size (l,w,h) to size class and size residual '''
67 | size_class = self.type2class[type_name]
68 | size_residual = size - self.type_mean_size[type_name]
69 | return size_class, size_residual
70 |
71 | def class2size(self, pred_cls, residual):
72 | ''' Inverse function to size2class '''
73 | return self.mean_size_arr[pred_cls, :] + residual
74 |
75 | def class2size_cuda(self, pred_cls, residual):
76 | ''' Inverse function to size2class '''
77 | mean_size_arr = torch.from_numpy(self.mean_size_arr).to(residual.device).float()
78 | return mean_size_arr[pred_cls.view(-1), :].view(*pred_cls.size(), 3) + residual
79 |
80 | def param2obb(self, center, heading_class, heading_residual, size_class, size_residual):
81 | heading_angle = self.class2angle(heading_class, heading_residual)
82 | box_size = self.class2size(int(size_class), size_residual)
83 | obb = np.zeros((7,))
84 | obb[0:3] = center
85 | obb[3:6] = box_size
86 | obb[6] = heading_angle
87 | return obb
88 |
89 |
90 | def rotate_aligned_boxes(input_boxes, rot_mat):
91 | centers, lengths = input_boxes[:, 0:3], input_boxes[:, 3:6]
92 | new_centers = np.dot(centers, np.transpose(rot_mat))
93 |
94 | dx, dy = lengths[:, 0] / 2.0, lengths[:, 1] / 2.0
95 | new_x = np.zeros((dx.shape[0], 4))
96 | new_y = np.zeros((dx.shape[0], 4))
97 |
98 | for i, crnr in enumerate([(-1, -1), (1, -1), (1, 1), (-1, 1)]):
99 | crnrs = np.zeros((dx.shape[0], 3))
100 | crnrs[:, 0] = crnr[0] * dx
101 | crnrs[:, 1] = crnr[1] * dy
102 | crnrs = np.dot(crnrs, np.transpose(rot_mat))
103 | new_x[:, i] = crnrs[:, 0]
104 | new_y[:, i] = crnrs[:, 1]
105 |
106 | new_dx = 2.0 * np.max(new_x, 1)
107 | new_dy = 2.0 * np.max(new_y, 1)
108 | new_lengths = np.stack((new_dx, new_dy, lengths[:, 2]), axis=1)
109 |
110 | return np.concatenate([new_centers, new_lengths], axis=1)
111 |
112 | if __name__ == '__main__':
113 | cfg = ScannetConfig()
--------------------------------------------------------------------------------
/datasets/scannet/raw_lablemap_to_synsetoffset.pkl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/datasets/scannet/raw_lablemap_to_synsetoffset.pkl
--------------------------------------------------------------------------------
/datasets/scannet/scannet_means.npz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/datasets/scannet/scannet_means.npz
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/000000_pred_confident_nms_bbox.npz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/000000_pred_confident_nms_bbox.npz
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/pred.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/pred.png
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_107_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_107_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_113_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_113_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_118_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_118_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_200_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_200_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_201_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_201_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_225_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_225_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_22_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_22_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_230_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_230_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_232_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_232_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_253_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_253_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_38_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_38_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_97_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_97_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0549_00/proposal_99_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0549_00/proposal_99_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/000000_pred_confident_nms_bbox.npz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/000000_pred_confident_nms_bbox.npz
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/pred.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/pred.png
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_133_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_133_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_139_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_139_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_147_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_147_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_159_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_159_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_163_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_163_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_182_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_182_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_188_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_188_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_196_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_196_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_221_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_221_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_228_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_228_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_233_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_233_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_24_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_24_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_253_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_253_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_25_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_25_mesh.ply
--------------------------------------------------------------------------------
/demo/outputs/scene0575_00/proposal_97_mesh.ply:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/outputs/scene0575_00/proposal_97_mesh.ply
--------------------------------------------------------------------------------
/demo/screenshots/screenshot_demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/screenshots/screenshot_demo.png
--------------------------------------------------------------------------------
/demo/screenshots/screenshot_scan2cad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/demo/screenshots/screenshot_scan2cad.png
--------------------------------------------------------------------------------
/environment.yml:
--------------------------------------------------------------------------------
1 | name: rfdnet
2 | channels:
3 | - pytorch
4 | - defaults
5 | dependencies:
6 | - _libgcc_mutex=0.1
7 | - blas=1.0
8 | - ca-certificates=2021.1.19
9 | - certifi=2020.12.5
10 | - cudatoolkit=11.0.221
11 | - dataclasses=0.8
12 | - freetype=2.10.4
13 | - intel-openmp=2020.2
14 | - jpeg=9b
15 | - lcms2=2.11
16 | - ld_impl_linux-64=2.33.1
17 | - libffi=3.3
18 | - libgcc-ng=9.1.0
19 | - libpng=1.6.37
20 | - libstdcxx-ng=9.1.0
21 | - libtiff=4.2.0
22 | - libuv=1.40.0
23 | - libwebp-base=1.2.0
24 | - lz4-c=1.9.3
25 | - mkl=2020.2
26 | - mkl-service=2.3.0
27 | - mkl_fft=1.3.0
28 | - mkl_random=1.1.1
29 | - ncurses=6.2
30 | - ninja=1.10.2
31 | - numpy=1.19.2
32 | - numpy-base=1.19.2
33 | - olefile=0.46
34 | - openssl=1.1.1j
35 | - pillow=8.1.2
36 | - pip=21.0.1
37 | - python=3.6.13
38 | - pytorch=1.7.1
39 | - readline=8.1
40 | - setuptools=52.0.0
41 | - six=1.15.0
42 | - sqlite=3.35.2
43 | - tk=8.6.10
44 | - torchaudio=0.7.2
45 | - torchvision=0.8.2
46 | - typing_extensions=3.7.4.3
47 | - wheel=0.36.2
48 | - xz=5.2.5
49 | - zlib=1.2.11
50 | - zstd=1.4.5
51 | - pip:
52 | - absl-py==0.12.0
53 | - cachetools==4.2.1
54 | - chardet==4.0.0
55 | - cycler==0.10.0
56 | - cython==0.29.22
57 | - decorator==4.4.2
58 | - google-auth==1.28.0
59 | - google-auth-oauthlib==0.4.3
60 | - grpcio==1.36.1
61 | - idna==2.10
62 | - imageio==2.9.0
63 | - importlib-metadata==3.7.3
64 | - kiwisolver==1.3.1
65 | - llvmlite==0.36.0
66 | - markdown==3.3.4
67 | - matplotlib==3.3.4
68 | - networkx==2.5
69 | - numba==0.53.0
70 | - numpy-quaternion==2021.3.17.16.51.43
71 | - oauthlib==3.1.0
72 | - pandas==1.1.5
73 | - plyfile==0.7.3
74 | - protobuf==3.15.6
75 | - pyasn1==0.4.8
76 | - pyasn1-modules==0.2.8
77 | - pymcubes==0.1.2
78 | - pyparsing==2.4.7
79 | - python-dateutil==2.8.1
80 | - pytz==2021.1
81 | - pywavelets==1.1.1
82 | - pyyaml==5.4.1
83 | - requests==2.25.1
84 | - requests-oauthlib==1.3.0
85 | - rsa==4.7.2
86 | - scikit-image==0.17.2
87 | - scipy==1.5.4
88 | - seaborn==0.11.1
89 | - shapely==1.7.1
90 | - tensorboard==2.4.1
91 | - tensorboard-plugin-wit==1.8.0
92 | - tifffile==2020.9.3
93 | - tqdm==4.59.0
94 | - trimesh==3.9.9
95 | - urllib3==1.26.4
96 | - vtk==9.0.1
97 | - werkzeug==1.0.1
98 | - zipp==3.4.1
99 |
--------------------------------------------------------------------------------
/external/libkdtree/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - '2.7'
4 | - '3.6'
5 |
6 | env:
7 | - USE_OMP=0
8 | - USE_OMP=1 OMP_NUM_THREADS=4
9 |
10 | before_install:
11 | - sudo apt-get install python-dev
12 |
13 | install:
14 | - python setup.py install
15 |
16 | script: python setup.py test
17 |
--------------------------------------------------------------------------------
/external/libkdtree/MANIFEST.in:
--------------------------------------------------------------------------------
1 | exclude pykdtree/render_template.py
2 | include LICENSE.txt
3 | include README.rst
4 | include pykdtree/*.pyx
5 |
--------------------------------------------------------------------------------
/external/libkdtree/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: clean build
2 |
3 | build: pykdtree/kdtree.c pykdtree/_kdtree_core.c
4 | python setup.py build
5 |
6 | pykdtree/kdtree.c: pykdtree/kdtree.pyx
7 | cython pykdtree/kdtree.pyx
8 |
9 | pykdtree/_kdtree_core.c: pykdtree/_kdtree_core.c.mako
10 | cd pykdtree && python render_template.py
11 |
12 | clean:
13 | rm -rf build/
14 | rm -f pykdtree/*.so
15 |
--------------------------------------------------------------------------------
/external/libkdtree/README:
--------------------------------------------------------------------------------
1 | README.rst
--------------------------------------------------------------------------------
/external/libkdtree/appveyor.yml:
--------------------------------------------------------------------------------
1 | environment:
2 | global:
3 | # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
4 | # /E:ON and /V:ON options are not enabled in the batch script intepreter
5 | # See: http://stackoverflow.com/a/13751649/163740
6 | CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_compiler.cmd"
7 | # Don't build with openmp because it isn't supported in appveyor's compilers
8 | USE_OMP: "0"
9 |
10 | matrix:
11 | - PYTHON: "C:\\Python27_32"
12 | PYTHON_VERSION: "2.7.8"
13 | PYTHON_ARCH: "32"
14 | MINICONDA_VERSION: "2"
15 |
16 | - PYTHON: "C:\\Python27_64"
17 | PYTHON_VERSION: "2.7.8"
18 | PYTHON_ARCH: "64"
19 | MINICONDA_VERSION: "2"
20 |
21 | - PYTHON: "C:\\Python36_32"
22 | PYTHON_VERSION: "3.6"
23 | PYTHON_ARCH: "32"
24 | MINICONDA_VERSION: "3"
25 | USE_OMP: "0"
26 |
27 | - PYTHON: "C:\\Python36_64"
28 | PYTHON_VERSION: "3.6"
29 | PYTHON_ARCH: "64"
30 | MINICONDA_VERSION: "3"
31 | USE_OMP: "0"
32 |
33 | - PYTHON: "C:\\Python36_32"
34 | PYTHON_VERSION: "3.6"
35 | PYTHON_ARCH: "32"
36 | MINICONDA_VERSION: "3"
37 | USE_OMP: "1"
38 | OMP_NUM_THREADS: "4"
39 |
40 | - PYTHON: "C:\\Python36_64"
41 | PYTHON_VERSION: "3.6"
42 | PYTHON_ARCH: "64"
43 | MINICONDA_VERSION: "3"
44 | USE_OMP: "1"
45 | OMP_NUM_THREADS: "4"
46 |
47 | install:
48 | - "git submodule update --init --recursive"
49 | - ECHO "Filesystem root:"
50 | - ps: "ls \"C:/\""
51 |
52 | - ECHO "Installed SDKs:"
53 | - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
54 |
55 | # install miniconda with the powershell script install.ps1
56 | - "powershell ./appveyor/install.ps1"
57 | # install missing headers that aren't included with MSVC 2008
58 | # https://github.com/omnia-md/conda-recipes/pull/524
59 | - "powershell ./appveyor/missing-headers.ps1"
60 |
61 | # Prepend newly installed Python to the PATH of this build (this cannot be
62 | # done from inside the powershell script as it would require to restart
63 | # the parent CMD process).
64 | - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
65 |
66 | # Check that we have the expected version and architecture for Python
67 | - "python --version"
68 | - "python -c \"import struct; print(struct.calcsize('P') * 8)\""
69 |
70 | # Install the build dependencies of the project. If some dependencies contain
71 | # compiled extensions and are not provided as pre-built wheel packages,
72 | # pip will build them from source using the MSVC compiler matching the
73 | # target Python version and architecture
74 | - "conda update --yes conda"
75 | - "conda config --add channels conda-forge"
76 | - "conda create -q --yes -n test python=%PYTHON_VERSION% numpy nose"
77 | - "activate test"
78 | - "pip install coveralls"
79 | - "where python"
80 |
81 | build: false # Not a C# project, build stuff at the test step instead.
82 |
83 | test_script:
84 | # Build the compiled extension and run the project tests
85 | - "%CMD_IN_ENV% python setup.py test"
86 |
87 | after_test:
88 | # If tests are successful, create a whl package for the project.
89 | - "%CMD_IN_ENV% python setup.py bdist_wheel bdist_wininst"
90 | - ps: "ls dist"
91 |
92 | artifacts:
93 | # Archive the generated wheel package in the ci.appveyor.com build report.
94 | - path: dist\*
95 |
96 | #on_success:
97 | # - TODO: upload the content of dist/*.whl to a public wheelhouse
98 | #
99 |
--------------------------------------------------------------------------------
/external/libkdtree/appveyor/install.ps1:
--------------------------------------------------------------------------------
1 | # Sample script to install anaconda under windows
2 | # Authors: Stuart Mumford
3 | # Borrwed from: Olivier Grisel and Kyle Kastner
4 | # License: BSD 3 clause
5 |
6 | $MINICONDA_URL = "http://repo.continuum.io/miniconda/"
7 |
8 | function DownloadMiniconda ($miniconda_version, $platform_suffix) {
9 | $webclient = New-Object System.Net.WebClient
10 | $filename = "Miniconda" + $miniconda_version + "-latest" + "-Windows-" + $platform_suffix + ".exe"
11 |
12 | $url = $MINICONDA_URL + $filename
13 |
14 | $basedir = $pwd.Path + "\"
15 | $filepath = $basedir + $filename
16 | if (Test-Path $filename) {
17 | Write-Host "Reusing" $filepath
18 | return $filepath
19 | }
20 |
21 | # Download and retry up to 3 times in case of network transient errors.
22 | Write-Host "Downloading" $filename "from" $url
23 | $retry_attempts = 2
24 | for($i=0; $i -lt $retry_attempts; $i++){
25 | try {
26 | $webclient.DownloadFile($url, $filepath)
27 | break
28 | }
29 | Catch [Exception]{
30 | Start-Sleep 1
31 | }
32 | }
33 | if (Test-Path $filepath) {
34 | Write-Host "File saved at" $filepath
35 | } else {
36 | # Retry once to get the error message if any at the last try
37 | $webclient.DownloadFile($url, $filepath)
38 | }
39 | return $filepath
40 | }
41 |
42 | function InstallMiniconda ($miniconda_version, $architecture, $python_home) {
43 | Write-Host "Installing miniconda" $miniconda_version "for" $architecture "bit architecture to" $python_home
44 | if (Test-Path $python_home) {
45 | Write-Host $python_home "already exists, skipping."
46 | return $false
47 | }
48 | if ($architecture -eq "32") {
49 | $platform_suffix = "x86"
50 | } else {
51 | $platform_suffix = "x86_64"
52 | }
53 | $filepath = DownloadMiniconda $miniconda_version $platform_suffix
54 | Write-Host "Installing" $filepath "to" $python_home
55 | $args = "/InstallationType=AllUsers /S /AddToPath=1 /RegisterPython=1 /D=" + $python_home
56 | Write-Host $filepath $args
57 | Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru
58 | #Start-Sleep -s 15
59 | if (Test-Path $python_home) {
60 | Write-Host "Miniconda $miniconda_version ($architecture) installation complete"
61 | } else {
62 | Write-Host "Failed to install Python in $python_home"
63 | Exit 1
64 | }
65 | }
66 |
67 | function main () {
68 | InstallMiniconda $env:MINICONDA_VERSION $env:PYTHON_ARCH $env:PYTHON
69 | }
70 |
71 | main
72 |
--------------------------------------------------------------------------------
/external/libkdtree/appveyor/missing-headers.ps1:
--------------------------------------------------------------------------------
1 | function InstallMissingHeaders () {
2 | # Visual Studio 2008 is missing stdint.h, but you can just download one
3 | # from the web.
4 | # http://stackoverflow.com/questions/126279/c99-stdint-h-header-and-ms-visual-studio
5 | $webclient = New-Object System.Net.WebClient
6 |
7 | $include_dirs = @("C:\Program Files\Microsoft SDKs\Windows\v7.0\Include",
8 | "C:\Program Files\Microsoft SDKs\Windows\v7.1\Include",
9 | "C:\Users\appveyor\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\include",
10 | "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include",
11 | "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include")
12 |
13 | Foreach ($include_dir in $include_dirs) {
14 | $urls = @(@("https://raw.githubusercontent.com/chemeris/msinttypes/master/stdint.h", "stdint.h"),
15 | @("https://raw.githubusercontent.com/chemeris/msinttypes/master/inttypes.h", "inttypes.h"))
16 |
17 | Foreach ($i in $urls) {
18 | $url = $i[0]
19 | $filename = $i[1]
20 |
21 | $filepath = "$include_dir\$filename"
22 | if (Test-Path $filepath) {
23 | Write-Host $filename "already exists in" $include_dir
24 | continue
25 | }
26 |
27 | Write-Host "Downloading remedial " $filename " from" $url "to" $filepath
28 | $retry_attempts = 2
29 | for($i=0; $i -lt $retry_attempts; $i++){
30 | try {
31 | $webclient.DownloadFile($url, $filepath)
32 | break
33 | }
34 | Catch [Exception]{
35 | Start-Sleep 1
36 | }
37 | }
38 |
39 | if (Test-Path $filepath) {
40 | Write-Host "File saved at" $filepath
41 | } else {
42 | # Retry once to get the error message if any at the last try
43 | $webclient.DownloadFile($url, $filepath)
44 | }
45 | }
46 | }
47 | }
48 |
49 | function main() {
50 | InstallMissingHeaders
51 | }
52 |
53 | main
54 |
--------------------------------------------------------------------------------
/external/libkdtree/appveyor/run_with_compiler.cmd:
--------------------------------------------------------------------------------
1 | :: To build extensions for 64 bit Python 3, we need to configure environment
2 | :: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
3 | :: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1)
4 | ::
5 | :: To build extensions for 64 bit Python 2, we need to configure environment
6 | :: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of:
7 | :: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0)
8 | ::
9 | :: 32 bit builds do not require specific environment configurations.
10 | ::
11 | :: Note: this script needs to be run with the /E:ON and /V:ON flags for the
12 | :: cmd interpreter, at least for (SDK v7.0)
13 | ::
14 | :: More details at:
15 | :: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
16 | :: http://stackoverflow.com/a/13751649/163740
17 | ::
18 | :: Author: Olivier Grisel
19 | :: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
20 | @ECHO OFF
21 |
22 | SET COMMAND_TO_RUN=%*
23 | SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
24 |
25 | SET MAJOR_PYTHON_VERSION="%PYTHON_VERSION:~0,1%"
26 | SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1%
27 | IF %MAJOR_PYTHON_VERSION% == "2" (
28 | SET WINDOWS_SDK_VERSION="v7.0"
29 | SET SET_SDK_64=Y
30 | ) ELSE IF %MAJOR_PYTHON_VERSION% == "3" (
31 | SET WINDOWS_SDK_VERSION="v7.1"
32 | IF %MINOR_PYTHON_VERSION% LEQ 4 (
33 | SET SET_SDK_64=Y
34 | ) ELSE (
35 | SET SET_SDK_64=N
36 | )
37 | ) ELSE (
38 | ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%"
39 | EXIT 1
40 | )
41 |
42 | IF "%PYTHON_ARCH%"=="64" (
43 | IF %SET_SDK_64% == Y (
44 | ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture
45 | SET DISTUTILS_USE_SDK=1
46 | SET MSSdk=1
47 | "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
48 | "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
49 | ECHO Executing: %COMMAND_TO_RUN%
50 | call %COMMAND_TO_RUN% || EXIT 1
51 | ) ELSE (
52 | ECHO Using default MSVC build environment for 64 bit architecture
53 | ECHO Executing: %COMMAND_TO_RUN%
54 | call %COMMAND_TO_RUN% || EXIT 1
55 | )
56 | ) ELSE (
57 | ECHO Using default MSVC build environment for 32 bit architecture
58 | ECHO Executing: %COMMAND_TO_RUN%
59 | call %COMMAND_TO_RUN% || EXIT 1
60 | )
61 |
--------------------------------------------------------------------------------
/external/libkdtree/pykdtree/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libkdtree/pykdtree/__init__.py
--------------------------------------------------------------------------------
/external/libkdtree/pykdtree/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libkdtree/pykdtree/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/external/libkdtree/pykdtree/kdtree.cpython-36m-x86_64-linux-gnu.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libkdtree/pykdtree/kdtree.cpython-36m-x86_64-linux-gnu.so
--------------------------------------------------------------------------------
/external/libkdtree/pykdtree/render_template.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from mako.template import Template
4 |
5 | mytemplate = Template(filename='_kdtree_core.c.mako')
6 | with open('_kdtree_core.c', 'w') as fp:
7 | fp.write(mytemplate.render())
8 |
--------------------------------------------------------------------------------
/external/libkdtree/scripts/build-manylinux-wheels.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e -x
3 |
4 | # This is to be run by Docker inside a Docker image.
5 | # You can test it locally on a Linux machine by installing docker and running from this repo's root:
6 | # $ docker run -e PLAT=manylinux1_x86_64 -v `pwd`:/io quay.io/pypa/manylinux1_x86_64 /io/scripts/build-manylinux-wheels.sh
7 |
8 | # * The -e just defines an environment variable PLAT=[docker name] inside the
9 | # docker - auditwheel can't detect the docker name automatically.
10 | # * The -v gives a directory alias for passing files in and out of the docker
11 | # (/io is arbitrary). E.g the `setup.py` script would be accessed in the
12 | # docker via `/io/setup.py`.
13 | # * quay.io/pypa/manylinux1_x86_64 is the full docker image name. Docker
14 | # downloads it automatically.
15 | # * The last argument is a shell command that the Docker will execute.
16 | # Filenames must be from the Docker's perspective.
17 |
18 | # Wheels are initially generated as you would usually, but put in a temp
19 | # directory temp-wheels. The pip-cache is optional but can speed up local builds
20 | # having a real permanent pip-cache dir.
21 | mkdir -p /io/pip-cache
22 | mkdir -p /io/temp-wheels
23 |
24 | # Clean out any old existing wheels.
25 | find /io/temp-wheels/ -type f -delete
26 |
27 | # Iterate through available pythons.
28 | for PYBIN in /opt/python/cp3[6789]*/bin; do
29 | "${PYBIN}/pip" install -q -U setuptools wheel nose --cache-dir /io/pip-cache
30 | # Run the following in root of this repo.
31 | (cd /io/ && USE_OMP=$USE_OMP "${PYBIN}/pip" install -q .)
32 | (cd /io/ && USE_OMP=$USE_OMP "${PYBIN}/python" setup.py nosetests)
33 | (cd /io/ && USE_OMP=$USE_OMP "${PYBIN}/python" setup.py -q bdist_wheel -d /io/temp-wheels)
34 | done
35 |
36 | "$PYBIN/pip" install -q auditwheel
37 |
38 | # Wheels aren't considered manylinux unless they have been through
39 | # auditwheel. Audited wheels go in /io/dist/.
40 | mkdir -p /io/dist/
41 |
42 | for whl in /io/temp-wheels/*.whl; do
43 | auditwheel repair "$whl" --plat "$PLAT" -w /io/dist/
44 | done
45 |
--------------------------------------------------------------------------------
/external/libkdtree/setup.cfg:
--------------------------------------------------------------------------------
1 | [bdist_rpm]
2 | requires=python3-numpy
3 | release=1
4 |
5 |
6 |
--------------------------------------------------------------------------------
/external/libkdtree/setup.py:
--------------------------------------------------------------------------------
1 | #pykdtree, Fast kd-tree implementation with OpenMP-enabled queries
2 | #
3 | #Copyright (C) 2013 - present Esben S. Nielsen
4 | #
5 | # This program is free software: you can redistribute it and/or modify it under
6 | # the terms of the GNU Lesser General Public License as published by the Free
7 | # Software Foundation, either version 3 of the License, or
8 | #(at your option) any later version.
9 | #
10 | # This program is distributed in the hope that it will be useful, but WITHOUT
11 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 | # details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License along
16 | # with this program. If not, see .
17 |
18 | import os
19 | import sys
20 | from setuptools import setup, Extension
21 | from setuptools.command.build_ext import build_ext
22 |
23 |
24 | def is_conda_interpreter():
25 | """Is the running interpreter from Anaconda or miniconda?
26 |
27 | See https://stackoverflow.com/a/21318941/433202
28 |
29 | Examples::
30 |
31 | 2.7.6 |Anaconda 1.8.0 (x86_64)| (default, Jan 10 2014, 11:23:15)
32 | 2.7.6 |Continuum Analytics, Inc.| (default, Jan 10 2014, 11:23:15)
33 | 3.6.6 | packaged by conda-forge | (default, Jul 26 2018, 09:55:02)
34 |
35 | """
36 | return 'conda' in sys.version or 'Continuum' in sys.version
37 |
38 |
39 | # Get OpenMP setting from environment
40 | try:
41 | use_omp = int(os.environ['USE_OMP'])
42 | except KeyError:
43 | # OpenMP is not supported with default clang
44 | # Conda provides its own compiler which does support openmp
45 | use_omp = 'darwin' not in sys.platform or is_conda_interpreter()
46 |
47 |
48 | def set_builtin(name, value):
49 | if isinstance(__builtins__, dict):
50 | __builtins__[name] = value
51 | else:
52 | setattr(__builtins__, name, value)
53 |
54 |
55 | # Custom builder to handler compiler flags. Edit if needed.
56 | class build_ext_subclass(build_ext):
57 | def build_extensions(self):
58 | comp = self.compiler.compiler_type
59 | if comp in ('unix', 'cygwin', 'mingw32'):
60 | # Check if build is with OpenMP
61 | if use_omp:
62 | extra_compile_args = ['-std=c99', '-O3', '-fopenmp']
63 | extra_link_args=['-lgomp']
64 | else:
65 | extra_compile_args = ['-std=c99', '-O3']
66 | extra_link_args = []
67 | elif comp == 'msvc':
68 | extra_compile_args = ['/Ox']
69 | extra_link_args = []
70 | if use_omp:
71 | extra_compile_args.append('/openmp')
72 | else:
73 | # Add support for more compilers here
74 | raise ValueError('Compiler flags undefined for %s. Please modify setup.py and add compiler flags'
75 | % comp)
76 | self.extensions[0].extra_compile_args = extra_compile_args
77 | self.extensions[0].extra_link_args = extra_link_args
78 | build_ext.build_extensions(self)
79 |
80 | def finalize_options(self):
81 | '''
82 | In order to avoid premature import of numpy before it gets installed as a dependency
83 | get numpy include directories during the extensions building process
84 | http://stackoverflow.com/questions/19919905/how-to-bootstrap-numpy-installation-in-setup-py
85 | '''
86 | build_ext.finalize_options(self)
87 | # Prevent numpy from thinking it is still in its setup process:
88 | set_builtin('__NUMPY_SETUP__', False)
89 | import numpy
90 | self.include_dirs.append(numpy.get_include())
91 |
92 | with open('README.rst', 'r') as readme_file:
93 | readme = readme_file.read()
94 |
95 | setup(
96 | name='pykdtree',
97 | version='1.3.4',
98 | url="https://github.com/storpipfugl/pykdtree",
99 | description='Fast kd-tree implementation with OpenMP-enabled queries',
100 | long_description=readme,
101 | author='Esben S. Nielsen',
102 | author_email='storpipfugl@gmail.com',
103 | packages=['pykdtree'],
104 | python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
105 | install_requires=['numpy'],
106 | setup_requires=['numpy'],
107 | tests_require=['nose'],
108 | zip_safe=False,
109 | test_suite='nose.collector',
110 | ext_modules=[Extension('pykdtree.kdtree',
111 | ['pykdtree/kdtree.c', 'pykdtree/_kdtree_core.c'])],
112 | cmdclass={'build_ext': build_ext_subclass},
113 | classifiers=[
114 | 'Development Status :: 5 - Production/Stable',
115 | ('License :: OSI Approved :: '
116 | 'GNU Lesser General Public License v3 (LGPLv3)'),
117 | 'Programming Language :: Python',
118 | 'Operating System :: OS Independent',
119 | 'Intended Audience :: Science/Research',
120 | 'Topic :: Scientific/Engineering'
121 | ]
122 | )
123 |
--------------------------------------------------------------------------------
/external/libmesh/.gitignore:
--------------------------------------------------------------------------------
1 | triangle_hash.cpp
2 | build
3 |
--------------------------------------------------------------------------------
/external/libmesh/__init__.py:
--------------------------------------------------------------------------------
1 | from .inside_mesh import (
2 | check_mesh_contains, MeshIntersector, TriangleIntersector2d
3 | )
4 |
5 |
6 | __all__ = [
7 | check_mesh_contains, MeshIntersector, TriangleIntersector2d
8 | ]
9 |
--------------------------------------------------------------------------------
/external/libmesh/triangle_hash.cpython-36m-x86_64-linux-gnu.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libmesh/triangle_hash.cpython-36m-x86_64-linux-gnu.so
--------------------------------------------------------------------------------
/external/libmesh/triangle_hash.pyx:
--------------------------------------------------------------------------------
1 |
2 | # distutils: language=c++
3 | import numpy as np
4 | cimport numpy as np
5 | cimport cython
6 | from libcpp.vector cimport vector
7 | from libc.math cimport floor, ceil
8 |
9 | cdef class TriangleHash:
10 | cdef vector[vector[int]] spatial_hash
11 | cdef int resolution
12 |
13 | def __cinit__(self, double[:, :, :] triangles, int resolution):
14 | self.spatial_hash.resize(resolution * resolution)
15 | self.resolution = resolution
16 | self._build_hash(triangles)
17 |
18 | @cython.boundscheck(False) # Deactivate bounds checking
19 | @cython.wraparound(False) # Deactivate negative indexing.
20 | cdef int _build_hash(self, double[:, :, :] triangles):
21 | assert(triangles.shape[1] == 3)
22 | assert(triangles.shape[2] == 2)
23 |
24 | cdef int n_tri = triangles.shape[0]
25 | cdef int bbox_min[2]
26 | cdef int bbox_max[2]
27 |
28 | cdef int i_tri, j, x, y
29 | cdef int spatial_idx
30 |
31 | for i_tri in range(n_tri):
32 | # Compute bounding box
33 | for j in range(2):
34 | bbox_min[j] = min(
35 | triangles[i_tri, 0, j], triangles[i_tri, 1, j], triangles[i_tri, 2, j]
36 | )
37 | bbox_max[j] = max(
38 | triangles[i_tri, 0, j], triangles[i_tri, 1, j], triangles[i_tri, 2, j]
39 | )
40 | bbox_min[j] = min(max(bbox_min[j], 0), self.resolution - 1)
41 | bbox_max[j] = min(max(bbox_max[j], 0), self.resolution - 1)
42 |
43 | # Find all voxels where bounding box intersects
44 | for x in range(bbox_min[0], bbox_max[0] + 1):
45 | for y in range(bbox_min[1], bbox_max[1] + 1):
46 | spatial_idx = self.resolution * x + y
47 | self.spatial_hash[spatial_idx].push_back(i_tri)
48 |
49 | @cython.boundscheck(False) # Deactivate bounds checking
50 | @cython.wraparound(False) # Deactivate negative indexing.
51 | cpdef query(self, double[:, :] points):
52 | assert(points.shape[1] == 2)
53 | cdef int n_points = points.shape[0]
54 |
55 | cdef vector[int] points_indices
56 | cdef vector[int] tri_indices
57 | # cdef int[:] points_indices_np
58 | # cdef int[:] tri_indices_np
59 |
60 | cdef int i_point, k, x, y
61 | cdef int spatial_idx
62 |
63 | for i_point in range(n_points):
64 | x = int(points[i_point, 0])
65 | y = int(points[i_point, 1])
66 | if not (0 <= x < self.resolution and 0 <= y < self.resolution):
67 | continue
68 |
69 | spatial_idx = self.resolution * x + y
70 | for i_tri in self.spatial_hash[spatial_idx]:
71 | points_indices.push_back(i_point)
72 | tri_indices.push_back(i_tri)
73 |
74 | points_indices_np = np.zeros(points_indices.size(), dtype=np.int32)
75 | tri_indices_np = np.zeros(tri_indices.size(), dtype=np.int32)
76 |
77 | cdef int[:] points_indices_view = points_indices_np
78 | cdef int[:] tri_indices_view = tri_indices_np
79 |
80 | for k in range(points_indices.size()):
81 | points_indices_view[k] = points_indices[k]
82 |
83 | for k in range(tri_indices.size()):
84 | tri_indices_view[k] = tri_indices[k]
85 |
86 | return points_indices_np, tri_indices_np
87 |
--------------------------------------------------------------------------------
/external/libmise/.gitignore:
--------------------------------------------------------------------------------
1 | mise.c
2 | mise.cpp
3 | mise.html
4 |
--------------------------------------------------------------------------------
/external/libmise/__init__.py:
--------------------------------------------------------------------------------
1 | from .mise import MISE
2 |
3 |
4 | __all__ = [
5 | MISE
6 | ]
7 |
--------------------------------------------------------------------------------
/external/libmise/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libmise/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/external/libmise/mise.cpython-36m-x86_64-linux-gnu.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libmise/mise.cpython-36m-x86_64-linux-gnu.so
--------------------------------------------------------------------------------
/external/libmise/test.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from mise import MISE
3 | import time
4 |
5 | t0 = time.time()
6 | extractor = MISE(1, 2, 0.)
7 |
8 | p = extractor.query()
9 | i = 0
10 |
11 | while p.shape[0] != 0:
12 | print(i)
13 | print(p)
14 | v = 2 * (p.sum(axis=-1) > 2).astype(np.float64) - 1
15 | extractor.update(p, v)
16 | p = extractor.query()
17 | i += 1
18 | if (i >= 8):
19 | break
20 |
21 | print(extractor.to_dense())
22 | # p, v = extractor.get_points()
23 | # print(p)
24 | # print(v)
25 | print('Total time: %f' % (time.time() - t0))
26 |
--------------------------------------------------------------------------------
/external/librender/__init__.py:
--------------------------------------------------------------------------------
1 | import ctypes
2 | import os
3 |
4 | #pyrender_dir = os.path.dirname(os.path.realpath(__file__))
5 | #ctypes.cdll.LoadLibrary(os.path.join(pyrender_dir, 'pyrender.so'))
6 | from external.librender.pyrender import *
7 |
--------------------------------------------------------------------------------
/external/librender/build/temp.linux-x86_64-3.6/offscreen.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/librender/build/temp.linux-x86_64-3.6/offscreen.o
--------------------------------------------------------------------------------
/external/librender/build/temp.linux-x86_64-3.6/pyrender.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/librender/build/temp.linux-x86_64-3.6/pyrender.o
--------------------------------------------------------------------------------
/external/librender/offscreen.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBRENDER_OFFSCREEN_H
2 | #define LIBRENDER_OFFSCREEN_H
3 |
4 | #include "GL/glew.h"
5 | #include "GL/gl.h"
6 | #include "GL/glu.h"
7 | #include "GL/glut.h"
8 |
9 | class OffscreenGL {
10 |
11 | public:
12 | OffscreenGL(int maxHeight, int maxWidth);
13 | ~OffscreenGL();
14 |
15 | private:
16 | static int glutWin;
17 | static bool glutInitialized;
18 | GLuint fb;
19 | GLuint renderTex;
20 | GLuint depthTex;
21 | };
22 |
23 |
24 | void renderDepthMesh(double *FM, int fNum, double *VM, int vNum, double *CM, double *intrinsics, int *imgSizeV, double *zNearFarV, unsigned char * imgBuffer, float *depthBuffer, bool *maskBuffer, double linewidth, bool coloring);
25 |
26 | #endif
--------------------------------------------------------------------------------
/external/librender/pyrender.cpython-36m-x86_64-linux-gnu.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/librender/pyrender.cpython-36m-x86_64-linux-gnu.so
--------------------------------------------------------------------------------
/external/librender/pyrender.pyx:
--------------------------------------------------------------------------------
1 | cimport cython
2 | import numpy as np
3 | cimport numpy as np
4 |
5 | from libc.stdlib cimport free, malloc
6 | from libcpp cimport bool
7 | from cpython cimport PyObject, Py_INCREF
8 |
9 | CREATE_INIT = True # workaround, so cython builds a init function
10 |
11 | np.import_array()
12 |
13 |
14 | cdef extern from "offscreen.h":
15 | void renderDepthMesh(double *FM, int fNum, double *VM, int vNum, double *CM, double *intrinsics, int *imgSizeV, double *zNearFarV, unsigned char * imgBuffer, float *depthBuffer, bool *maskBuffer, double linewidth, bool coloring);
16 |
17 |
18 | def render(double[:,::1] vertices, double[:,::1] faces, double[::1] cam_intr, double[::1] znf, int[::1] img_size):
19 | if vertices.shape[0] != 3:
20 | raise Exception('vertices must be a 3xM double array')
21 | if faces.shape[0] != 3:
22 | raise Exception('faces must be a 3xM double array')
23 | if cam_intr.shape[0] != 4:
24 | raise Exception('cam_intr must be a 4x1 double vector')
25 | if img_size.shape[0] != 2:
26 | raise Exception('img_size must be a 2x1 int vector')
27 |
28 | cdef double* VM = &(vertices[0,0])
29 | cdef int vNum = vertices.shape[1]
30 | cdef double* FM = &(faces[0,0])
31 | cdef int fNum = faces.shape[1]
32 | cdef double* intrinsics = &(cam_intr[0])
33 | cdef double* zNearVarV = &(znf[0])
34 | cdef int* imgSize = &(img_size[0])
35 |
36 | cdef bool coloring = False
37 | cdef double* CM = NULL
38 |
39 | depth = np.empty((img_size[1], img_size[0]), dtype=np.float32)
40 | mask = np.empty((img_size[1], img_size[0]), dtype=np.uint8)
41 | img = np.empty((3, img_size[1], img_size[0]), dtype=np.uint8)
42 | cdef float[:,::1] depth_view = depth
43 | cdef unsigned char[:,::1] mask_view = mask
44 | cdef unsigned char[:,:,::1] img_view = img
45 | cdef float* depthBuffer = &(depth_view[0,0])
46 | cdef bool* maskBuffer = &(mask_view[0,0])
47 | cdef unsigned char* imgBuffer = &(img_view[0,0,0])
48 |
49 | renderDepthMesh(FM, fNum, VM, vNum, CM, intrinsics, imgSize, zNearVarV, imgBuffer, depthBuffer, maskBuffer, 0, coloring);
50 |
51 | return depth.T, mask.T, img.transpose((2,1,0))
52 |
--------------------------------------------------------------------------------
/external/librender/setup.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup
2 | from distutils.extension import Extension
3 | from Cython.Distutils import build_ext
4 | import numpy as np
5 |
6 | extra_compile_args = ["-ffast-math", '-msse', '-msse2', '-msse3', '-msse4.2', '-O4', '-fopenmp']
7 | extra_link_args = ['-lGLEW', '-lglut', '-lGL', '-lGLU', '-fopenmp']
8 |
9 | setup(
10 | name="pyrender",
11 | cmdclass= {'build_ext': build_ext},
12 | ext_modules=[
13 | Extension('pyrender',
14 | [
15 | 'pyrender.pyx',
16 | 'offscreen.cpp',
17 | ],
18 | language='c++',
19 | include_dirs=[np.get_include()],
20 | extra_compile_args=extra_compile_args,
21 | extra_link_args=extra_link_args
22 | )
23 | ]
24 | )
25 |
26 |
27 |
--------------------------------------------------------------------------------
/external/librender/test.py:
--------------------------------------------------------------------------------
1 | import pyrender
2 | import numpy as np
3 | from matplotlib import pyplot
4 | import math
5 |
6 | # render settings
7 | img_h = 480
8 | img_w = 480
9 | fx = 480.
10 | fy = 480.
11 | cx = 240
12 | cy = 240
13 |
14 | def model():
15 |
16 | # note that xx is height here!
17 | xx = -0.2
18 | yy = -0.2
19 | zz = -0.2
20 |
21 | v000 = (xx, yy, zz) # 0
22 | v001 = (xx, yy, zz + 0.4) # 1
23 | v010 = (xx, yy + 0.4, zz) # 2
24 | v011 = (xx, yy + 0.4, zz + 0.4) # 3
25 | v100 = (xx + 0.4, yy, zz) # 4
26 | v101 = (xx + 0.4, yy, zz + 0.4) # 5
27 | v110 = (xx + 0.4, yy + 0.4, zz) # 6
28 | v111 = (xx + 0.4, yy + 0.4, zz + 0.4) # 7
29 |
30 | f1 = [0, 2, 4]
31 | f2 = [4, 2, 6]
32 | f3 = [1, 3, 5]
33 | f4 = [5, 3, 7]
34 | f5 = [0, 1, 2]
35 | f6 = [1, 3, 2]
36 | f7 = [4, 5, 7]
37 | f8 = [4, 7, 6]
38 | f9 = [4, 0, 1]
39 | f10 = [4, 5, 1]
40 | f11 = [2, 3, 6]
41 | f12 = [3, 7, 6]
42 |
43 | vertices = []
44 | vertices.append(v000)
45 | vertices.append(v001)
46 | vertices.append(v010)
47 | vertices.append(v011)
48 | vertices.append(v100)
49 | vertices.append(v101)
50 | vertices.append(v110)
51 | vertices.append(v111)
52 |
53 | faces = []
54 | faces.append(f1)
55 | faces.append(f2)
56 | faces.append(f3)
57 | faces.append(f4)
58 | faces.append(f5)
59 | faces.append(f6)
60 | faces.append(f7)
61 | faces.append(f8)
62 | faces.append(f9)
63 | faces.append(f10)
64 | faces.append(f11)
65 | faces.append(f12)
66 |
67 | return vertices, faces
68 |
69 | def render(vertices, faces):
70 |
71 | x = 0
72 | y = math.pi/4
73 | z = 0
74 | R_x = np.array([[1, 0, 0], [0, math.cos(x), -math.sin(x)], [0, math.sin(x), math.cos(x)]])
75 | R_y = np.array([[math.cos(y), 0, math.sin(y)], [0, 1, 0], [-math.sin(y), 0, math.cos(y)]])
76 | R_z = np.array([[math.cos(z), -math.sin(z), 0], [math.sin(z), math.cos(z), 0], [0, 0, 1]])
77 | R = R_z.dot(R_y.dot(R_x))
78 |
79 | np_vertices = np.array(vertices).astype(np.float64)
80 | np_vertices = R.dot(np_vertices.T).T
81 | np_vertices[:, 2] += 1.5
82 | np_faces = np.array(faces).astype(np.float64)
83 | np_faces += 1
84 |
85 | depthmap, mask, img = pyrender.render(np_vertices.T.copy(), np_faces.T.copy(), np.array([fx, fy, cx, cy]), np.array([1., 2.]), np.array([img_h, img_w], dtype=np.int32))
86 | pyplot.imshow(depthmap)
87 | pyplot.show()
88 | pyplot.imshow(img)
89 | pyplot.show()
90 |
91 | if __name__ == '__main__':
92 | vertices, faces = model()
93 | render(vertices, faces)
94 |
--------------------------------------------------------------------------------
/external/libsimplify/__init__.py:
--------------------------------------------------------------------------------
1 | from .simplify_mesh import (
2 | mesh_simplify
3 | )
4 | import trimesh
5 |
6 |
7 | def simplify_mesh(mesh, f_target=10000, agressiveness=7.):
8 | vertices = mesh.vertices
9 | faces = mesh.faces
10 |
11 | vertices, faces = mesh_simplify(vertices, faces, f_target, agressiveness)
12 |
13 | mesh_simplified = trimesh.Trimesh(vertices, faces, process=False)
14 |
15 | return mesh_simplified
16 |
--------------------------------------------------------------------------------
/external/libsimplify/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libsimplify/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/external/libsimplify/simplify_mesh.cpython-36m-x86_64-linux-gnu.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libsimplify/simplify_mesh.cpython-36m-x86_64-linux-gnu.so
--------------------------------------------------------------------------------
/external/libsimplify/simplify_mesh.pyx:
--------------------------------------------------------------------------------
1 | # distutils: language = c++
2 | from libcpp.vector cimport vector
3 | import numpy as np
4 | cimport numpy as np
5 |
6 |
7 | cdef extern from "Simplify.h":
8 | cdef struct vec3f:
9 | double x, y, z
10 |
11 | cdef cppclass SymetricMatrix:
12 | SymetricMatrix() except +
13 |
14 |
15 | cdef extern from "Simplify.h" namespace "Simplify":
16 | cdef struct Triangle:
17 | int v[3]
18 | double err[4]
19 | int deleted, dirty, attr
20 | vec3f uvs[3]
21 | int material
22 |
23 | cdef struct Vertex:
24 | vec3f p
25 | int tstart, tcount
26 | SymetricMatrix q
27 | int border
28 |
29 | cdef vector[Triangle] triangles
30 | cdef vector[Vertex] vertices
31 | cdef void simplify_mesh(int, double)
32 |
33 |
34 | cpdef mesh_simplify(double[:, ::1] vertices_in, long[:, ::1] triangles_in,
35 | int f_target, double agressiveness=7.) except +:
36 | vertices.clear()
37 | triangles.clear()
38 |
39 | # Read in vertices and triangles
40 | cdef Vertex v
41 | for iv in range(vertices_in.shape[0]):
42 | v = Vertex()
43 | v.p.x = vertices_in[iv, 0]
44 | v.p.y = vertices_in[iv, 1]
45 | v.p.z = vertices_in[iv, 2]
46 | vertices.push_back(v)
47 |
48 | cdef Triangle t
49 | for it in range(triangles_in.shape[0]):
50 | t = Triangle()
51 | t.v[0] = triangles_in[it, 0]
52 | t.v[1] = triangles_in[it, 1]
53 | t.v[2] = triangles_in[it, 2]
54 | triangles.push_back(t)
55 |
56 | # Simplify
57 | # print('Simplify...')
58 | simplify_mesh(f_target, agressiveness)
59 |
60 | # Only use triangles that are not deleted
61 | cdef vector[Triangle] triangles_notdel
62 | triangles_notdel.reserve(triangles.size())
63 |
64 | for t in triangles:
65 | if not t.deleted:
66 | triangles_notdel.push_back(t)
67 |
68 | # Read out triangles
69 | vertices_out = np.empty((vertices.size(), 3), dtype=np.float64)
70 | triangles_out = np.empty((triangles_notdel.size(), 3), dtype=np.int64)
71 |
72 | cdef double[:, :] vertices_out_view = vertices_out
73 | cdef long[:, :] triangles_out_view = triangles_out
74 |
75 | for iv in range(vertices.size()):
76 | vertices_out_view[iv, 0] = vertices[iv].p.x
77 | vertices_out_view[iv, 1] = vertices[iv].p.y
78 | vertices_out_view[iv, 2] = vertices[iv].p.z
79 |
80 | for it in range(triangles_notdel.size()):
81 | triangles_out_view[it, 0] = triangles_notdel[it].v[0]
82 | triangles_out_view[it, 1] = triangles_notdel[it].v[1]
83 | triangles_out_view[it, 2] = triangles_notdel[it].v[2]
84 |
85 | # Clear vertices and triangles
86 | vertices.clear()
87 | triangles.clear()
88 |
89 | return vertices_out, triangles_out
--------------------------------------------------------------------------------
/external/libsimplify/test.py:
--------------------------------------------------------------------------------
1 | from simplify_mesh import mesh_simplify
2 | import numpy as np
3 |
4 | v = np.random.rand(100, 3)
5 | f = np.random.choice(range(100), (50, 3))
6 |
7 | mesh_simplify(v, f, 50)
--------------------------------------------------------------------------------
/external/libvoxelize/.gitignore:
--------------------------------------------------------------------------------
1 | voxelize.c
2 | voxelize.html
3 | build
4 |
--------------------------------------------------------------------------------
/external/libvoxelize/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libvoxelize/__init__.py
--------------------------------------------------------------------------------
/external/libvoxelize/voxelize.cpython-36m-x86_64-linux-gnu.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/libvoxelize/voxelize.cpython-36m-x86_64-linux-gnu.so
--------------------------------------------------------------------------------
/external/libvoxelize/voxelize.pyx:
--------------------------------------------------------------------------------
1 | cimport cython
2 | from libc.math cimport floor, ceil
3 | from cython.view cimport array as cvarray
4 |
5 | cdef extern from "tribox2.h":
6 | int triBoxOverlap(float boxcenter[3], float boxhalfsize[3],
7 | float tri0[3], float tri1[3], float tri2[3])
8 |
9 |
10 | @cython.boundscheck(False) # Deactivate bounds checking
11 | @cython.wraparound(False) # Deactivate negative indexing.
12 | cpdef int voxelize_mesh_(bint[:, :, :] occ, float[:, :, ::1] faces):
13 | assert(faces.shape[1] == 3)
14 | assert(faces.shape[2] == 3)
15 |
16 | n_faces = faces.shape[0]
17 | cdef int i
18 | for i in range(n_faces):
19 | voxelize_triangle_(occ, faces[i])
20 |
21 |
22 | @cython.boundscheck(False) # Deactivate bounds checking
23 | @cython.wraparound(False) # Deactivate negative indexing.
24 | cpdef int voxelize_triangle_(bint[:, :, :] occupancies, float[:, ::1] triverts):
25 | cdef int bbox_min[3]
26 | cdef int bbox_max[3]
27 | cdef int i, j, k
28 | cdef float boxhalfsize[3]
29 | cdef float boxcenter[3]
30 | cdef bint intersection
31 |
32 | boxhalfsize[:] = (0.5, 0.5, 0.5)
33 |
34 | for i in range(3):
35 | bbox_min[i] = (
36 | min(triverts[0, i], triverts[1, i], triverts[2, i])
37 | )
38 | bbox_min[i] = min(max(bbox_min[i], 0), occupancies.shape[i] - 1)
39 |
40 | for i in range(3):
41 | bbox_max[i] = (
42 | max(triverts[0, i], triverts[1, i], triverts[2, i])
43 | )
44 | bbox_max[i] = min(max(bbox_max[i], 0), occupancies.shape[i] - 1)
45 |
46 | for i in range(bbox_min[0], bbox_max[0] + 1):
47 | for j in range(bbox_min[1], bbox_max[1] + 1):
48 | for k in range(bbox_min[2], bbox_max[2] + 1):
49 | boxcenter[:] = (i + 0.5, j + 0.5, k + 0.5)
50 | intersection = triBoxOverlap(&boxcenter[0], &boxhalfsize[0],
51 | &triverts[0, 0], &triverts[1, 0], &triverts[2, 0])
52 | occupancies[i, j, k] |= intersection
53 |
54 |
55 | @cython.boundscheck(False) # Deactivate bounds checking
56 | @cython.wraparound(False) # Deactivate negative indexing.
57 | cdef int test_triangle_aabb(float[::1] boxcenter, float[::1] boxhalfsize, float[:, ::1] triverts):
58 | assert(boxcenter.shape[0] == 3)
59 | assert(boxhalfsize.shape[0] == 3)
60 | assert(triverts.shape[0] == triverts.shape[1] == 3)
61 |
62 | # print(triverts)
63 | # Call functions
64 | cdef int result = triBoxOverlap(&boxcenter[0], &boxhalfsize[0],
65 | &triverts[0, 0], &triverts[1, 0], &triverts[2, 0])
66 | return result
67 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft pointnet2_ops/_ext-src
2 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/__init__.py:
--------------------------------------------------------------------------------
1 | import pointnet2_ops.pointnet2_modules
2 | import pointnet2_ops.pointnet2_utils
3 | from pointnet2_ops._version import __version__
4 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/pointnet2_ops_lib/pointnet2_ops/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/__pycache__/pointnet2_modules.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/pointnet2_ops_lib/pointnet2_ops/__pycache__/pointnet2_modules.cpython-36.pyc
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/__pycache__/pointnet2_utils.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/pointnet2_ops_lib/pointnet2_ops/__pycache__/pointnet2_utils.cpython-36.pyc
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/include/ball_query.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | at::Tensor ball_query(at::Tensor new_xyz, at::Tensor xyz, const float radius,
5 | const int nsample);
6 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/include/cuda_utils.h:
--------------------------------------------------------------------------------
1 | #ifndef _CUDA_UTILS_H
2 | #define _CUDA_UTILS_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #define TOTAL_THREADS 512
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 |
18 | return max(min(1 << pow_2, TOTAL_THREADS), 1);
19 | }
20 |
21 | inline dim3 opt_block_config(int x, int y) {
22 | const int x_threads = opt_n_threads(x);
23 | const int y_threads =
24 | max(min(opt_n_threads(y), TOTAL_THREADS / x_threads), 1);
25 | dim3 block_config(x_threads, y_threads, 1);
26 |
27 | return block_config;
28 | }
29 |
30 | #define CUDA_CHECK_ERRORS() \
31 | do { \
32 | cudaError_t err = cudaGetLastError(); \
33 | if (cudaSuccess != err) { \
34 | fprintf(stderr, "CUDA kernel failed : %s\n%s at L:%d in %s\n", \
35 | cudaGetErrorString(err), __PRETTY_FUNCTION__, __LINE__, \
36 | __FILE__); \
37 | exit(-1); \
38 | } \
39 | } while (0)
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/include/group_points.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | at::Tensor group_points(at::Tensor points, at::Tensor idx);
5 | at::Tensor group_points_grad(at::Tensor grad_out, at::Tensor idx, const int n);
6 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/include/interpolate.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | std::vector three_nn(at::Tensor unknowns, at::Tensor knows);
7 | at::Tensor three_interpolate(at::Tensor points, at::Tensor idx,
8 | at::Tensor weight);
9 | at::Tensor three_interpolate_grad(at::Tensor grad_out, at::Tensor idx,
10 | at::Tensor weight, const int m);
11 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/include/sampling.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | at::Tensor gather_points(at::Tensor points, at::Tensor idx);
5 | at::Tensor gather_points_grad(at::Tensor grad_out, at::Tensor idx, const int n);
6 | at::Tensor furthest_point_sampling(at::Tensor points, const int nsamples);
7 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/include/utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | #define CHECK_CUDA(x) \
6 | do { \
7 | AT_ASSERT(x.is_cuda(), #x " must be a CUDA tensor"); \
8 | } while (0)
9 |
10 | #define CHECK_CONTIGUOUS(x) \
11 | do { \
12 | AT_ASSERT(x.is_contiguous(), #x " must be a contiguous tensor"); \
13 | } while (0)
14 |
15 | #define CHECK_IS_INT(x) \
16 | do { \
17 | AT_ASSERT(x.scalar_type() == at::ScalarType::Int, \
18 | #x " must be an int tensor"); \
19 | } while (0)
20 |
21 | #define CHECK_IS_FLOAT(x) \
22 | do { \
23 | AT_ASSERT(x.scalar_type() == at::ScalarType::Float, \
24 | #x " must be a float tensor"); \
25 | } while (0)
26 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/src/ball_query.cpp:
--------------------------------------------------------------------------------
1 | #include "ball_query.h"
2 | #include "utils.h"
3 |
4 | void query_ball_point_kernel_wrapper(int b, int n, int m, float radius,
5 | int nsample, const float *new_xyz,
6 | const float *xyz, int *idx);
7 |
8 | at::Tensor ball_query(at::Tensor new_xyz, at::Tensor xyz, const float radius,
9 | const int nsample) {
10 | CHECK_CONTIGUOUS(new_xyz);
11 | CHECK_CONTIGUOUS(xyz);
12 | CHECK_IS_FLOAT(new_xyz);
13 | CHECK_IS_FLOAT(xyz);
14 |
15 | if (new_xyz.is_cuda()) {
16 | CHECK_CUDA(xyz);
17 | }
18 |
19 | at::Tensor idx =
20 | torch::zeros({new_xyz.size(0), new_xyz.size(1), nsample},
21 | at::device(new_xyz.device()).dtype(at::ScalarType::Int));
22 |
23 | if (new_xyz.is_cuda()) {
24 | query_ball_point_kernel_wrapper(xyz.size(0), xyz.size(1), new_xyz.size(1),
25 | radius, nsample, new_xyz.data_ptr(),
26 | xyz.data_ptr(), idx.data_ptr());
27 | } else {
28 | AT_ASSERT(false, "CPU not supported");
29 | }
30 |
31 | return idx;
32 | }
33 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/src/ball_query_gpu.cu:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "cuda_utils.h"
6 |
7 | // input: new_xyz(b, m, 3) xyz(b, n, 3)
8 | // output: idx(b, m, nsample)
9 | __global__ void query_ball_point_kernel(int b, int n, int m, float radius,
10 | int nsample,
11 | const float *__restrict__ new_xyz,
12 | const float *__restrict__ xyz,
13 | int *__restrict__ idx) {
14 | int batch_index = blockIdx.x;
15 | xyz += batch_index * n * 3;
16 | new_xyz += batch_index * m * 3;
17 | idx += m * nsample * batch_index;
18 |
19 | int index = threadIdx.x;
20 | int stride = blockDim.x;
21 |
22 | float radius2 = radius * radius;
23 | for (int j = index; j < m; j += stride) {
24 | float new_x = new_xyz[j * 3 + 0];
25 | float new_y = new_xyz[j * 3 + 1];
26 | float new_z = new_xyz[j * 3 + 2];
27 | for (int k = 0, cnt = 0; k < n && cnt < nsample; ++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) +
32 | (new_z - z) * (new_z - z);
33 | if (d2 < radius2) {
34 | if (cnt == 0) {
35 | for (int l = 0; l < nsample; ++l) {
36 | idx[j * nsample + l] = k;
37 | }
38 | }
39 | idx[j * nsample + cnt] = k;
40 | ++cnt;
41 | }
42 | }
43 | }
44 | }
45 |
46 | void query_ball_point_kernel_wrapper(int b, int n, int m, float radius,
47 | int nsample, const float *new_xyz,
48 | const float *xyz, int *idx) {
49 | cudaStream_t stream = at::cuda::getCurrentCUDAStream();
50 | query_ball_point_kernel<<>>(
51 | b, n, m, radius, nsample, new_xyz, xyz, idx);
52 |
53 | CUDA_CHECK_ERRORS();
54 | }
55 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/src/bindings.cpp:
--------------------------------------------------------------------------------
1 | #include "ball_query.h"
2 | #include "group_points.h"
3 | #include "interpolate.h"
4 | #include "sampling.h"
5 |
6 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
7 | m.def("gather_points", &gather_points);
8 | m.def("gather_points_grad", &gather_points_grad);
9 | m.def("furthest_point_sampling", &furthest_point_sampling);
10 |
11 | m.def("three_nn", &three_nn);
12 | m.def("three_interpolate", &three_interpolate);
13 | m.def("three_interpolate_grad", &three_interpolate_grad);
14 |
15 | m.def("ball_query", &ball_query);
16 |
17 | m.def("group_points", &group_points);
18 | m.def("group_points_grad", &group_points_grad);
19 | }
20 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/src/group_points.cpp:
--------------------------------------------------------------------------------
1 | #include "group_points.h"
2 | #include "utils.h"
3 |
4 | void group_points_kernel_wrapper(int b, int c, int n, int npoints, int nsample,
5 | const float *points, const int *idx,
6 | float *out);
7 |
8 | void group_points_grad_kernel_wrapper(int b, int c, int n, int npoints,
9 | int nsample, const float *grad_out,
10 | const int *idx, float *grad_points);
11 |
12 | at::Tensor group_points(at::Tensor points, at::Tensor idx) {
13 | CHECK_CONTIGUOUS(points);
14 | CHECK_CONTIGUOUS(idx);
15 | CHECK_IS_FLOAT(points);
16 | CHECK_IS_INT(idx);
17 |
18 | if (points.is_cuda()) {
19 | CHECK_CUDA(idx);
20 | }
21 |
22 | at::Tensor output =
23 | torch::zeros({points.size(0), points.size(1), idx.size(1), idx.size(2)},
24 | at::device(points.device()).dtype(at::ScalarType::Float));
25 |
26 | if (points.is_cuda()) {
27 | group_points_kernel_wrapper(points.size(0), points.size(1), points.size(2),
28 | idx.size(1), idx.size(2),
29 | points.data_ptr(), idx.data_ptr(),
30 | output.data_ptr());
31 | } else {
32 | AT_ASSERT(false, "CPU not supported");
33 | }
34 |
35 | return output;
36 | }
37 |
38 | at::Tensor group_points_grad(at::Tensor grad_out, at::Tensor idx, const int n) {
39 | CHECK_CONTIGUOUS(grad_out);
40 | CHECK_CONTIGUOUS(idx);
41 | CHECK_IS_FLOAT(grad_out);
42 | CHECK_IS_INT(idx);
43 |
44 | if (grad_out.is_cuda()) {
45 | CHECK_CUDA(idx);
46 | }
47 |
48 | at::Tensor output =
49 | torch::zeros({grad_out.size(0), grad_out.size(1), n},
50 | at::device(grad_out.device()).dtype(at::ScalarType::Float));
51 |
52 | if (grad_out.is_cuda()) {
53 | group_points_grad_kernel_wrapper(
54 | grad_out.size(0), grad_out.size(1), n, idx.size(1), idx.size(2),
55 | grad_out.data_ptr(), idx.data_ptr(),
56 | output.data_ptr());
57 | } else {
58 | AT_ASSERT(false, "CPU not supported");
59 | }
60 |
61 | return output;
62 | }
63 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/src/group_points_gpu.cu:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "cuda_utils.h"
5 |
6 | // input: points(b, c, n) idx(b, npoints, nsample)
7 | // output: out(b, c, npoints, nsample)
8 | __global__ void group_points_kernel(int b, int c, int n, int npoints,
9 | int nsample,
10 | const float *__restrict__ points,
11 | const int *__restrict__ idx,
12 | float *__restrict__ out) {
13 | int batch_index = blockIdx.x;
14 | points += batch_index * n * c;
15 | idx += batch_index * npoints * nsample;
16 | out += batch_index * npoints * nsample * c;
17 |
18 | const int index = threadIdx.y * blockDim.x + threadIdx.x;
19 | const int stride = blockDim.y * blockDim.x;
20 | for (int i = index; i < c * npoints; i += stride) {
21 | const int l = i / npoints;
22 | const int j = i % npoints;
23 | for (int k = 0; k < nsample; ++k) {
24 | int ii = idx[j * nsample + k];
25 | out[(l * npoints + j) * nsample + k] = points[l * n + ii];
26 | }
27 | }
28 | }
29 |
30 | void group_points_kernel_wrapper(int b, int c, int n, int npoints, int nsample,
31 | const float *points, const int *idx,
32 | float *out) {
33 | cudaStream_t stream = at::cuda::getCurrentCUDAStream();
34 |
35 | group_points_kernel<<>>(
36 | b, c, n, npoints, nsample, points, idx, out);
37 |
38 | CUDA_CHECK_ERRORS();
39 | }
40 |
41 | // input: grad_out(b, c, npoints, nsample), idx(b, npoints, nsample)
42 | // output: grad_points(b, c, n)
43 | __global__ void group_points_grad_kernel(int b, int c, int n, int npoints,
44 | int nsample,
45 | const float *__restrict__ grad_out,
46 | const int *__restrict__ idx,
47 | float *__restrict__ grad_points) {
48 | int batch_index = blockIdx.x;
49 | grad_out += batch_index * npoints * nsample * c;
50 | idx += batch_index * npoints * nsample;
51 | grad_points += batch_index * n * c;
52 |
53 | const int index = threadIdx.y * blockDim.x + threadIdx.x;
54 | const int stride = blockDim.y * blockDim.x;
55 | for (int i = index; i < c * npoints; i += stride) {
56 | const int l = i / npoints;
57 | const int j = i % npoints;
58 | for (int k = 0; k < nsample; ++k) {
59 | int ii = idx[j * nsample + k];
60 | atomicAdd(grad_points + l * n + ii,
61 | grad_out[(l * npoints + j) * nsample + k]);
62 | }
63 | }
64 | }
65 |
66 | void group_points_grad_kernel_wrapper(int b, int c, int n, int npoints,
67 | int nsample, const float *grad_out,
68 | const int *idx, float *grad_points) {
69 | cudaStream_t stream = at::cuda::getCurrentCUDAStream();
70 |
71 | group_points_grad_kernel<<>>(
72 | b, c, n, npoints, nsample, grad_out, idx, grad_points);
73 |
74 | CUDA_CHECK_ERRORS();
75 | }
76 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/src/interpolate.cpp:
--------------------------------------------------------------------------------
1 | #include "interpolate.h"
2 | #include "utils.h"
3 |
4 | void three_nn_kernel_wrapper(int b, int n, int m, const float *unknown,
5 | const float *known, float *dist2, int *idx);
6 | void three_interpolate_kernel_wrapper(int b, int c, int m, int n,
7 | const float *points, const int *idx,
8 | const float *weight, float *out);
9 | void three_interpolate_grad_kernel_wrapper(int b, int c, int n, int m,
10 | const float *grad_out,
11 | const int *idx, const float *weight,
12 | float *grad_points);
13 |
14 | std::vector three_nn(at::Tensor unknowns, at::Tensor knows) {
15 | CHECK_CONTIGUOUS(unknowns);
16 | CHECK_CONTIGUOUS(knows);
17 | CHECK_IS_FLOAT(unknowns);
18 | CHECK_IS_FLOAT(knows);
19 |
20 | if (unknowns.is_cuda()) {
21 | CHECK_CUDA(knows);
22 | }
23 |
24 | at::Tensor idx =
25 | torch::zeros({unknowns.size(0), unknowns.size(1), 3},
26 | at::device(unknowns.device()).dtype(at::ScalarType::Int));
27 | at::Tensor dist2 =
28 | torch::zeros({unknowns.size(0), unknowns.size(1), 3},
29 | at::device(unknowns.device()).dtype(at::ScalarType::Float));
30 |
31 | if (unknowns.is_cuda()) {
32 | three_nn_kernel_wrapper(unknowns.size(0), unknowns.size(1), knows.size(1),
33 | unknowns.data_ptr(), knows.data_ptr(),
34 | dist2.data_ptr(), idx.data_ptr());
35 | } else {
36 | AT_ASSERT(false, "CPU not supported");
37 | }
38 |
39 | return {dist2, idx};
40 | }
41 |
42 | at::Tensor three_interpolate(at::Tensor points, at::Tensor idx,
43 | at::Tensor weight) {
44 | CHECK_CONTIGUOUS(points);
45 | CHECK_CONTIGUOUS(idx);
46 | CHECK_CONTIGUOUS(weight);
47 | CHECK_IS_FLOAT(points);
48 | CHECK_IS_INT(idx);
49 | CHECK_IS_FLOAT(weight);
50 |
51 | if (points.is_cuda()) {
52 | CHECK_CUDA(idx);
53 | CHECK_CUDA(weight);
54 | }
55 |
56 | at::Tensor output =
57 | torch::zeros({points.size(0), points.size(1), idx.size(1)},
58 | at::device(points.device()).dtype(at::ScalarType::Float));
59 |
60 | if (points.is_cuda()) {
61 | three_interpolate_kernel_wrapper(
62 | points.size(0), points.size(1), points.size(2), idx.size(1),
63 | points.data_ptr(), idx.data_ptr(), weight.data_ptr(),
64 | output.data_ptr());
65 | } else {
66 | AT_ASSERT(false, "CPU not supported");
67 | }
68 |
69 | return output;
70 | }
71 | at::Tensor three_interpolate_grad(at::Tensor grad_out, at::Tensor idx,
72 | at::Tensor weight, const int m) {
73 | CHECK_CONTIGUOUS(grad_out);
74 | CHECK_CONTIGUOUS(idx);
75 | CHECK_CONTIGUOUS(weight);
76 | CHECK_IS_FLOAT(grad_out);
77 | CHECK_IS_INT(idx);
78 | CHECK_IS_FLOAT(weight);
79 |
80 | if (grad_out.is_cuda()) {
81 | CHECK_CUDA(idx);
82 | CHECK_CUDA(weight);
83 | }
84 |
85 | at::Tensor output =
86 | torch::zeros({grad_out.size(0), grad_out.size(1), m},
87 | at::device(grad_out.device()).dtype(at::ScalarType::Float));
88 |
89 | if (grad_out.is_cuda()) {
90 | three_interpolate_grad_kernel_wrapper(
91 | grad_out.size(0), grad_out.size(1), grad_out.size(2), m,
92 | grad_out.data_ptr(), idx.data_ptr(),
93 | weight.data_ptr(), output.data_ptr());
94 | } else {
95 | AT_ASSERT(false, "CPU not supported");
96 | }
97 |
98 | return output;
99 | }
100 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_ext-src/src/sampling.cpp:
--------------------------------------------------------------------------------
1 | #include "sampling.h"
2 | #include "utils.h"
3 |
4 | void gather_points_kernel_wrapper(int b, int c, int n, int npoints,
5 | const float *points, const int *idx,
6 | float *out);
7 | void gather_points_grad_kernel_wrapper(int b, int c, int n, int npoints,
8 | const float *grad_out, const int *idx,
9 | float *grad_points);
10 |
11 | void furthest_point_sampling_kernel_wrapper(int b, int n, int m,
12 | const float *dataset, float *temp,
13 | int *idxs);
14 |
15 | at::Tensor gather_points(at::Tensor points, at::Tensor idx) {
16 | CHECK_CONTIGUOUS(points);
17 | CHECK_CONTIGUOUS(idx);
18 | CHECK_IS_FLOAT(points);
19 | CHECK_IS_INT(idx);
20 |
21 | if (points.is_cuda()) {
22 | CHECK_CUDA(idx);
23 | }
24 |
25 | at::Tensor output =
26 | torch::zeros({points.size(0), points.size(1), idx.size(1)},
27 | at::device(points.device()).dtype(at::ScalarType::Float));
28 |
29 | if (points.is_cuda()) {
30 | gather_points_kernel_wrapper(points.size(0), points.size(1), points.size(2),
31 | idx.size(1), points.data_ptr(),
32 | idx.data_ptr(), output.data_ptr());
33 | } else {
34 | AT_ASSERT(false, "CPU not supported");
35 | }
36 |
37 | return output;
38 | }
39 |
40 | at::Tensor gather_points_grad(at::Tensor grad_out, at::Tensor idx,
41 | const int n) {
42 | CHECK_CONTIGUOUS(grad_out);
43 | CHECK_CONTIGUOUS(idx);
44 | CHECK_IS_FLOAT(grad_out);
45 | CHECK_IS_INT(idx);
46 |
47 | if (grad_out.is_cuda()) {
48 | CHECK_CUDA(idx);
49 | }
50 |
51 | at::Tensor output =
52 | torch::zeros({grad_out.size(0), grad_out.size(1), n},
53 | at::device(grad_out.device()).dtype(at::ScalarType::Float));
54 |
55 | if (grad_out.is_cuda()) {
56 | gather_points_grad_kernel_wrapper(grad_out.size(0), grad_out.size(1), n,
57 | idx.size(1), grad_out.data_ptr(),
58 | idx.data_ptr(),
59 | output.data_ptr());
60 | } else {
61 | AT_ASSERT(false, "CPU not supported");
62 | }
63 |
64 | return output;
65 | }
66 | at::Tensor furthest_point_sampling(at::Tensor points, const int nsamples) {
67 | CHECK_CONTIGUOUS(points);
68 | CHECK_IS_FLOAT(points);
69 |
70 | at::Tensor output =
71 | torch::zeros({points.size(0), nsamples},
72 | at::device(points.device()).dtype(at::ScalarType::Int));
73 |
74 | at::Tensor tmp =
75 | torch::full({points.size(0), points.size(1)}, 1e10,
76 | at::device(points.device()).dtype(at::ScalarType::Float));
77 |
78 | if (points.is_cuda()) {
79 | furthest_point_sampling_kernel_wrapper(
80 | points.size(0), points.size(1), nsamples, points.data_ptr(),
81 | tmp.data_ptr(), output.data_ptr());
82 | } else {
83 | AT_ASSERT(false, "CPU not supported");
84 | }
85 |
86 | return output;
87 | }
88 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = "3.0.0"
2 |
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/pointnet2_ops/pytorch_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 5.2021. Yinyu Nie
2 | # License: MIT
3 | # Modified based on Ref: https://github.com/erikwijmans/Pointnet2_PyTorch '''
4 | import torch.nn as nn
5 |
6 | def set_bn_momentum_default(bn_momentum):
7 |
8 | def fn(m):
9 | if isinstance(m, (nn.BatchNorm1d, nn.BatchNorm2d, nn.BatchNorm3d)):
10 | m.momentum = bn_momentum
11 |
12 | return fn
13 |
14 |
15 | class BNMomentumScheduler(object):
16 |
17 | def __init__(
18 | self, cfg, model, bn_lambda, last_epoch=-1,
19 | setter=set_bn_momentum_default
20 | ):
21 | if not isinstance(model, nn.Module):
22 | raise RuntimeError(
23 | "Class '{}' is not a PyTorch nn Module".format(
24 | type(model).__name__
25 | )
26 | )
27 | self.cfg = cfg
28 | self.model = model
29 | self.setter = setter
30 | self.lmbd = bn_lambda
31 |
32 | self.step(last_epoch + 1)
33 | self.last_epoch = last_epoch
34 |
35 | def step(self, epoch=None):
36 | if epoch is None:
37 | epoch = self.last_epoch + 1
38 |
39 | self.last_epoch = epoch
40 | self.model.apply(self.setter(self.lmbd(epoch)))
41 |
42 | def show_momentum(self):
43 | self.cfg.log_string('Current BN decay momentum :%f.' % (self.lmbd(self.last_epoch)))
--------------------------------------------------------------------------------
/external/pointnet2_ops_lib/setup.py:
--------------------------------------------------------------------------------
1 | import glob
2 | import os
3 | import os.path as osp
4 |
5 | from setuptools import find_packages, setup
6 | from torch.utils.cpp_extension import BuildExtension, CUDAExtension
7 |
8 | this_dir = osp.dirname(osp.abspath(__file__))
9 | _ext_src_root = osp.join("pointnet2_ops", "_ext-src")
10 | _ext_sources = glob.glob(osp.join(_ext_src_root, "src", "*.cpp")) + glob.glob(
11 | osp.join(_ext_src_root, "src", "*.cu")
12 | )
13 | _ext_headers = glob.glob(osp.join(_ext_src_root, "include", "*"))
14 |
15 | requirements = ["torch>=1.4"]
16 |
17 | exec(open(osp.join("pointnet2_ops", "_version.py")).read())
18 |
19 | os.environ["TORCH_CUDA_ARCH_LIST"] = "3.7+PTX;5.0;6.0;6.1;6.2;7.0;7.5"
20 | setup(
21 | name="pointnet2_ops",
22 | version=__version__,
23 | author="Erik Wijmans",
24 | packages=find_packages(),
25 | install_requires=requirements,
26 | ext_modules=[
27 | CUDAExtension(
28 | name="pointnet2_ops._ext",
29 | sources=_ext_sources,
30 | extra_compile_args={
31 | "cxx": ["-O3"],
32 | "nvcc": ["-O3", "-Xfatbin", "-compress-all"],
33 | },
34 | include_dirs=[osp.join(this_dir, _ext_src_root, "include")],
35 | )
36 | ],
37 | cmdclass={"build_ext": BuildExtension},
38 | include_package_data=True,
39 | )
40 |
--------------------------------------------------------------------------------
/external/pyTorchChamferDistance/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | ._*
3 |
4 |
--------------------------------------------------------------------------------
/external/pyTorchChamferDistance/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [year] [fullname]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/external/pyTorchChamferDistance/README.md:
--------------------------------------------------------------------------------
1 | # Chamfer Distance for pyTorch
2 |
3 | This is an implementation of the Chamfer Distance as a module for pyTorch. It is written as a custom C++/CUDA extension.
4 |
5 | As it is using pyTorch's [JIT compilation](https://pytorch.org/tutorials/advanced/cpp_extension.html), there are no additional prerequisite steps that have to be taken. Simply import the module as shown below; CUDA and C++ code will be compiled on the first run.
6 |
7 | ### Usage
8 | ```python
9 | from chamfer_distance import ChamferDistance
10 | chamfer_dist = ChamferDistance()
11 |
12 | #...
13 | # points and points_reconstructed are n_points x 3 matrices
14 |
15 | dist1, dist2 = chamfer_dist(points, points_reconstructed)
16 | loss = (torch.mean(dist1)) + (torch.mean(dist2))
17 |
18 |
19 | #...
20 | ```
21 |
22 | ### Integration
23 | This code has been integrated into the [Kaolin](https://github.com/NVIDIAGameWorks/kaolin) library for 3D Deep Learning by NVIDIAGameWorks. You should probably take a look at it if you are working on anything 3D :)
24 |
--------------------------------------------------------------------------------
/external/pyTorchChamferDistance/chamfer_distance/__init__.py:
--------------------------------------------------------------------------------
1 | from .chamfer_distance import ChamferDistance
2 |
--------------------------------------------------------------------------------
/external/pyTorchChamferDistance/chamfer_distance/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/pyTorchChamferDistance/chamfer_distance/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/external/pyTorchChamferDistance/chamfer_distance/__pycache__/chamfer_distance.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/pyTorchChamferDistance/chamfer_distance/__pycache__/chamfer_distance.cpython-36.pyc
--------------------------------------------------------------------------------
/external/pyTorchChamferDistance/chamfer_distance/chamfer_distance.py:
--------------------------------------------------------------------------------
1 |
2 | import torch
3 |
4 | from torch.utils.cpp_extension import load
5 | cd = load(name="cd",
6 | sources=["external/pyTorchChamferDistance/chamfer_distance/chamfer_distance.cpp",
7 | "external/pyTorchChamferDistance/chamfer_distance/chamfer_distance.cu"])
8 |
9 | class ChamferDistanceFunction(torch.autograd.Function):
10 | @staticmethod
11 | def forward(ctx, xyz1, xyz2):
12 | batchsize, n, _ = xyz1.size()
13 | _, m, _ = xyz2.size()
14 | xyz1 = xyz1.contiguous()
15 | xyz2 = xyz2.contiguous()
16 | dist1 = torch.zeros(batchsize, n)
17 | dist2 = torch.zeros(batchsize, m)
18 |
19 | idx1 = torch.zeros(batchsize, n, dtype=torch.int)
20 | idx2 = torch.zeros(batchsize, m, dtype=torch.int)
21 |
22 | if not xyz1.is_cuda:
23 | cd.forward(xyz1, xyz2, dist1, dist2, idx1, idx2)
24 | else:
25 | dist1 = dist1.cuda()
26 | dist2 = dist2.cuda()
27 | idx1 = idx1.cuda()
28 | idx2 = idx2.cuda()
29 | cd.forward_cuda(xyz1, xyz2, dist1, dist2, idx1, idx2)
30 |
31 | ctx.save_for_backward(xyz1, xyz2, idx1, idx2)
32 |
33 | return dist1, dist2
34 |
35 | @staticmethod
36 | def backward(ctx, graddist1, graddist2):
37 | xyz1, xyz2, idx1, idx2 = ctx.saved_tensors
38 |
39 | graddist1 = graddist1.contiguous()
40 | graddist2 = graddist2.contiguous()
41 |
42 | gradxyz1 = torch.zeros(xyz1.size())
43 | gradxyz2 = torch.zeros(xyz2.size())
44 |
45 | if not graddist1.is_cuda:
46 | cd.backward(xyz1, xyz2, gradxyz1, gradxyz2, graddist1, graddist2, idx1, idx2)
47 | else:
48 | gradxyz1 = gradxyz1.cuda()
49 | gradxyz2 = gradxyz2.cuda()
50 | cd.backward_cuda(xyz1, xyz2, gradxyz1, gradxyz2, graddist1, graddist2, idx1, idx2)
51 |
52 | return gradxyz1, gradxyz2
53 |
54 |
55 | class ChamferDistance(torch.nn.Module):
56 | def forward(self, xyz1, xyz2):
57 | return ChamferDistanceFunction.apply(xyz1, xyz2)
58 |
--------------------------------------------------------------------------------
/external/pyfusion/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | cyfusion.so
3 | cyfusion.cpp
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/external/pyfusion/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, The OctNet authors
2 | # All rights reserved.
3 | #
4 | # Redistribution and use in source and binary forms, with or without
5 | # modification, are permitted provided that the following conditions are met:
6 | # * Redistributions of source code must retain the above copyright
7 | # notice, this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of the nor the
12 | # names of its contributors may be used to endorse or promote products
13 | # derived from this software without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL OCTNET AUTHORS BE LIABLE FOR ANY
19 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | cmake_minimum_required(VERSION 2.8)
27 | set(CMAKE_MACOSX_RPATH 1)
28 |
29 | set(CMAKE_CXX_STANDARD 11)
30 |
31 | # set(CMAKE_BUILD_TYPE Debug)
32 | set(CMAKE_BUILD_TYPE Release)
33 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3 -msse4.2 -fPIC")
34 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse -msse2 -msse3 -msse4.2 -fPIC")
35 |
36 | find_package(OpenMP)
37 | if (OPENMP_FOUND)
38 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
39 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
40 | endif()
41 |
42 | find_package(CUDA 6.5 REQUIRED)
43 | set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-std=c++11")
44 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORCE_INLINES -Wall")
45 |
46 | set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS}; -gencode=arch=compute_30,code=sm_30")
47 | set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS}; -gencode=arch=compute_30,code=compute_30")
48 |
49 | set(FUSION_CPU_SRC
50 | fusion.cpp
51 | )
52 |
53 | set(FUSION_GPU_SRC
54 | fusion.cu
55 | fusion_zach_tvl1.cu
56 | )
57 |
58 | cuda_add_library(fusion_cpu SHARED ${FUSION_CPU_SRC})
59 |
60 | cuda_add_library(fusion_gpu SHARED ${FUSION_GPU_SRC})
61 | target_link_libraries(fusion_gpu ${CUDA_LIBRARIES})
62 |
--------------------------------------------------------------------------------
/external/pyfusion/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, Gernot
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/external/pyfusion/README.md:
--------------------------------------------------------------------------------
1 | # PyFusion
2 |
3 | PyFusion is a Python framework for volumetric depth fusion.
4 | It contains simple occupancy and TSDF fusion methods that can be executed on a CPU as well as on a GPU.
5 |
6 | To use the code, first compile the native code via
7 |
8 | ```bash
9 | cd build
10 | cmake ..
11 | make
12 | ```
13 | Afterwards you can compile the Cython code via
14 |
15 | ```bash
16 | python setup.py build_ext --inplace
17 | ```
18 |
19 | You can then use the fusion functions
20 |
21 | ```python
22 | import pyfusion
23 |
24 | # create a views object
25 | # depthmaps: a NxHxW numpy float tensor of N depthmaps, invalid depth values are marked by negative numbers
26 | # Ks: the camera intric matrices, Nx3x3 float tensor
27 | # Rs: the camera rotation matrices, Nx3x3 float tensor
28 | # Ts: the camera translation vectors, Nx3 float tensor
29 | views = pyfusion.PyViews(depthmaps, Ks,Rs,Ts)
30 |
31 | # afterwards you can fuse the depth maps for example by
32 | # depth,height,width: number of voxels in each dimension
33 | # truncation: TSDF truncation value
34 | tsdf = pyfusion.tsdf_gpu(views, depth,height,width, vx_size, truncation, False)
35 |
36 | # the same code can also be run on the CPU
37 | tsdf = pyfusion.tsdf_cpu(views, depth,height,width, vx_size, truncation, False, n_threads=8)
38 | ```
39 |
40 | Make sure `pyfusion` is in your `$PYTHONPATH`.
41 |
--------------------------------------------------------------------------------
/external/pyfusion/__init__.py:
--------------------------------------------------------------------------------
1 | import ctypes
2 | import os
3 |
4 | pyfusion_dir = os.path.dirname(os.path.realpath(__file__))
5 |
6 | ctypes.cdll.LoadLibrary(os.path.join(pyfusion_dir, 'build', 'libfusion_cpu.so'))
7 | ctypes.cdll.LoadLibrary(os.path.join(pyfusion_dir, 'build', 'libfusion_gpu.so'))
8 | from external.pyfusion.cyfusion import *
9 |
--------------------------------------------------------------------------------
/external/pyfusion/cyfusion.cpython-36m-x86_64-linux-gnu.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/external/pyfusion/cyfusion.cpython-36m-x86_64-linux-gnu.so
--------------------------------------------------------------------------------
/external/pyfusion/fusion.cpp:
--------------------------------------------------------------------------------
1 | #include "fusion.h"
2 |
3 | #include
4 | #include
5 |
6 | #if defined(_OPENMP)
7 | #include
8 | #endif
9 |
10 |
11 | template
12 | void fusion_cpu(const Views& views, const FusionFunctorT functor, float vx_size, int n_threads, Volume& vol) {
13 | int vx_res3 = vol.depth_ * vol.height_ * vol.width_;
14 |
15 | #if defined(_OPENMP)
16 | omp_set_num_threads(n_threads);
17 | #endif
18 | #pragma omp parallel for
19 | for(int idx = 0; idx < vx_res3; ++idx) {
20 | int d,h,w;
21 | fusion_idx2dhw(idx, vol.width_,vol.height_, d,h,w);
22 | float x,y,z;
23 | fusion_dhw2xyz(d,h,w, vx_size, x,y,z);
24 |
25 | functor.before_sample(&vol, d,h,w);
26 | bool run = true;
27 | int n_valid_views = 0;
28 | for(int vidx = 0; vidx < views.n_views_ && run; ++vidx) {
29 | float ur, vr, vx_d;
30 | fusion_project(&views, vidx, x,y,z, ur,vr,vx_d);
31 |
32 | int u = int(ur + 0.5f);
33 | int v = int(vr + 0.5f);
34 | // printf(" vx %d,%d,%d has center %f,%f,%f and projects to uvd=%f,%f,%f\n", w,h,d, x,y,z, ur,vr,vx_d);
35 |
36 | if(u >= 0 && v >= 0 && u < views.cols_ && v < views.rows_) {
37 | int dm_idx = (vidx * views.rows_ + v) * views.cols_ + u;
38 | float dm_d = views.depthmaps_[dm_idx];
39 | // printf(" is on depthmap[%d,%d] with depth=%f, diff=%f\n", views.cols_,views.rows_, dm_d, dm_d - vx_d);
40 | run = functor.new_sample(&vol, vx_d, dm_d, d,h,w, &n_valid_views);
41 | }
42 | } // for vidx
43 | functor.after_sample(&vol, d,h,w, n_valid_views);
44 | }
45 | }
46 |
47 | void fusion_projectionmask_cpu(const Views& views, float vx_size, bool unknown_is_free, int n_threads, Volume& vol) {
48 | ProjectionMaskFusionFunctor functor(unknown_is_free);
49 | fusion_cpu(views, functor, vx_size, n_threads, vol);
50 | }
51 |
52 | void fusion_occupancy_cpu(const Views& views, float vx_size, float truncation, bool unknown_is_free, int n_threads, Volume& vol) {
53 | OccupancyFusionFunctor functor(truncation, unknown_is_free);
54 | fusion_cpu(views, functor, vx_size, n_threads, vol);
55 | }
56 |
57 | void fusion_tsdfmask_cpu(const Views& views, float vx_size, float truncation, bool unknown_is_free, int n_threads, Volume& vol) {
58 | TsdfMaskFusionFunctor functor(truncation, unknown_is_free);
59 | fusion_cpu(views, functor, vx_size, n_threads, vol);
60 | }
61 |
62 | void fusion_tsdf_cpu(const Views& views, float vx_size, float truncation, bool unknown_is_free, int n_threads, Volume& vol) {
63 | TsdfFusionFunctor functor(truncation, unknown_is_free);
64 | fusion_cpu(views, functor, vx_size, n_threads, vol);
65 | }
66 |
67 | void fusion_tsdf_hist_cpu(const Views& views, float vx_size, float truncation, bool unknown_is_free, float* bin_centers, int n_bins, bool unobserved_is_occupied, int n_threads, Volume& vol) {
68 | TsdfHistFusionFunctor functor(truncation, unknown_is_free, bin_centers, n_bins, unobserved_is_occupied);
69 | fusion_cpu(views, functor, vx_size, n_threads, vol);
70 | }
71 |
--------------------------------------------------------------------------------
/external/pyfusion/fusion.cu:
--------------------------------------------------------------------------------
1 | #include "gpu_common.h"
2 |
3 | #include
4 | #include
5 |
6 |
7 |
8 | template
9 | __global__ void kernel_fusion(int vx_res3, const Views views, const FusionFunctorT functor, float vx_size, Volume vol) {
10 | CUDA_KERNEL_LOOP(idx, vx_res3) {
11 | int d,h,w;
12 | fusion_idx2dhw(idx, vol.width_,vol.height_, d,h,w);
13 | float x,y,z;
14 | fusion_dhw2xyz(d,h,w, vx_size, x,y,z);
15 |
16 | functor.before_sample(&vol, d,h,w);
17 | bool run = true;
18 | int n_valid_views = 0;
19 | for(int vidx = 0; vidx < views.n_views_ && run; ++vidx) {
20 | float ur, vr, vx_d;
21 | fusion_project(&views, vidx, x,y,z, ur,vr,vx_d);
22 | //NOTE: ur,vr,vx_d might differ to CPP (subtle differences in precision)
23 |
24 | int u = int(ur + 0.5f);
25 | int v = int(vr + 0.5f);
26 |
27 | if(u >= 0 && v >= 0 && u < views.cols_ && v < views.rows_) {
28 | int dm_idx = (vidx * views.rows_ + v) * views.cols_ + u;
29 | float dm_d = views.depthmaps_[dm_idx];
30 | // if(d==103 && h==130 && w==153) printf(" dm_d=%f, dm_idx=%d, u=%d, v=%d, ur=%f, vr=%f\n", dm_d, dm_idx, u,v, ur,vr);
31 | run = functor.new_sample(&vol, vx_d, dm_d, d,h,w, &n_valid_views);
32 | }
33 | } // for vidx
34 | functor.after_sample(&vol, d,h,w, n_valid_views);
35 | }
36 | }
37 |
38 |
39 |
40 | template
41 | void fusion_gpu(const Views& views, const FusionFunctorT functor, float vx_size, Volume& vol) {
42 | Views views_gpu;
43 | views_to_gpu(views, views_gpu, true);
44 | Volume vol_gpu;
45 | volume_alloc_like_gpu(vol, vol_gpu);
46 |
47 | int vx_res3 = vol.depth_ * vol.height_ * vol.width_;
48 | kernel_fusion<<>>(
49 | vx_res3, views_gpu, functor, vx_size, vol_gpu
50 | );
51 | CUDA_POST_KERNEL_CHECK;
52 |
53 | volume_to_cpu(vol_gpu, vol, false);
54 |
55 | views_free_gpu(views_gpu);
56 | volume_free_gpu(vol_gpu);
57 | }
58 |
59 | void fusion_projectionmask_gpu(const Views& views, float vx_size, bool unknown_is_free, Volume& vol) {
60 | ProjectionMaskFusionFunctor functor(unknown_is_free);
61 | fusion_gpu(views, functor, vx_size, vol);
62 | }
63 |
64 | void fusion_occupancy_gpu(const Views& views, float vx_size, float truncation, bool unknown_is_free, Volume& vol) {
65 | OccupancyFusionFunctor functor(truncation, unknown_is_free);
66 | fusion_gpu(views, functor, vx_size, vol);
67 | }
68 |
69 | void fusion_tsdfmask_gpu(const Views& views, float vx_size, float truncation, bool unknown_is_free, Volume& vol) {
70 | TsdfMaskFusionFunctor functor(truncation, unknown_is_free);
71 | fusion_gpu(views, functor, vx_size, vol);
72 | }
73 |
74 | void fusion_tsdf_gpu(const Views& views, float vx_size, float truncation, bool unknown_is_free, Volume& vol) {
75 | TsdfFusionFunctor functor(truncation, unknown_is_free);
76 | fusion_gpu(views, functor, vx_size, vol);
77 | }
78 |
79 | void fusion_tsdf_hist_gpu(const Views& views, float vx_size, float truncation, bool unknown_is_free, float* bin_centers, int n_bins, bool unobserved_is_occupied, Volume& vol) {
80 | float* bin_centers_gpu = host_to_device_malloc(bin_centers, n_bins);
81 | TsdfHistFusionFunctor functor(truncation, unknown_is_free, bin_centers_gpu, n_bins, unobserved_is_occupied);
82 | fusion_gpu(views, functor, vx_size, vol);
83 | device_free(bin_centers_gpu);
84 | }
85 |
--------------------------------------------------------------------------------
/external/pyfusion/setup.py:
--------------------------------------------------------------------------------
1 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3 | # DISCLAIMED. IN NO EVENT SHALL OCTNET AUTHORS BE LIABLE FOR ANY
4 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
5 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
8 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
9 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10 |
11 | from distutils.core import setup
12 | from Cython.Build import cythonize
13 | from distutils.extension import Extension
14 | from Cython.Distutils import build_ext
15 | import numpy as np
16 | import platform
17 |
18 | extra_compile_args = ["-ffast-math", '-msse', '-msse2', '-msse3', '-msse4.2']
19 | extra_link_args = []
20 | if 'Linux' in platform.system():
21 | print('Added OpenMP')
22 | extra_compile_args.append('-fopenmp')
23 | extra_link_args.append('-fopenmp')
24 |
25 |
26 | setup(
27 | name="cyfusion",
28 | cmdclass= {'build_ext': build_ext},
29 | ext_modules=[
30 | Extension('cyfusion',
31 | ['cyfusion.pyx'],
32 | language='c++',
33 | library_dirs=['./build/'],
34 | libraries=['m', "fusion_cpu", "fusion_gpu"],
35 | include_dirs=[np.get_include()],
36 | extra_compile_args=extra_compile_args,
37 | extra_link_args=extra_link_args
38 | )
39 | ]
40 | )
41 |
--------------------------------------------------------------------------------
/external/pyrender/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | pyrender.cpp
3 | *.so
4 |
--------------------------------------------------------------------------------
/external/pyrender/README.md:
--------------------------------------------------------------------------------
1 | # PyRender
2 |
3 | This project contains a Cython version of [librender by Andreas Geiger and Chaohui Wang 2014](http://www.cvlibs.net/software/librender/).
4 | The code enables the efficient rendering of depth maps from 3D triangle meshes.
5 |
6 | To use the code, first compile the Cython code via
7 |
8 | ```bash
9 | python setup.py build_ext --inplace
10 | ```
11 |
12 | You can then use the rendering function
13 |
14 | ```python
15 | import pyrender
16 | ...
17 | # vertices: a Nx3 double numpy array
18 | # faces: a Nx3 int array (indices of vertices array)
19 | # cam_intr: (fx, fy, px, py) double vector
20 | # img_size: (height, width) int vector
21 | depth, mask = pyrender.render(vertices, faces, cam_intr, img_size)
22 | ```
23 |
24 | Make sure `pyrender` is in your `$PYTHONPATH`.
25 |
--------------------------------------------------------------------------------
/external/pyrender/offscreen.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBRENDER_OFFSCREEN_H
2 | #define LIBRENDER_OFFSCREEN_H
3 |
4 | #include
5 | #if defined(__APPLE__)
6 | #include
7 | #include
8 | #else
9 | #include
10 | #include
11 | #endif
12 | #include
13 |
14 | class OffscreenGL {
15 |
16 | public:
17 | OffscreenGL(int maxHeight, int maxWidth);
18 | ~OffscreenGL();
19 |
20 | private:
21 | static int glutWin;
22 | static bool glutInitialized;
23 | GLuint fb;
24 | GLuint renderTex;
25 | GLuint depthTex;
26 | };
27 |
28 |
29 | void renderDepthMesh(int *FM, int fNum, double *VM, int vNum, double *intrinsics, int *imgSizeV, double *zNearFarV, float *depthBuffer);
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/external/pyrender/pyrender.pyx:
--------------------------------------------------------------------------------
1 | cimport cython
2 | import numpy as np
3 | cimport numpy as np
4 |
5 | from libc.stdlib cimport free, malloc
6 | from libcpp cimport bool
7 | from cpython cimport PyObject, Py_INCREF
8 |
9 | CREATE_INIT = True # workaround, so cython builds a init function
10 |
11 | np.import_array()
12 |
13 |
14 | cdef extern from "offscreen.h":
15 | void renderDepthMesh(int *FM, int fNum, double *VM, int vNum, double *intrinsics, int *imgSizeV, double *zNearFarV, float *depthBuffer);
16 |
17 |
18 | def render(double[:,::1] vertices, int[:,::1] faces, double[::1] cam_intr, int[::1] img_size):
19 | if vertices.shape[1] != 3:
20 | raise Exception('vertices must be a Mx3 double array')
21 | if faces.shape[1] != 3:
22 | raise Exception('faces must be a Mx3 int array')
23 | if cam_intr.shape[0] != 4:
24 | raise Exception('cam_intr must be a 4x1 double vector')
25 | if img_size.shape[0] != 2:
26 | raise Exception('img_size must be a 2x1 int vector')
27 |
28 | cdef double* VM = &(vertices[0,0])
29 | cdef int vNum = vertices.shape[0]
30 | cdef int* FM = &(faces[0,0])
31 | cdef int fNum = faces.shape[0]
32 | cdef double* intrinsics = &(cam_intr[0])
33 | cdef int* imgSize = &(img_size[0])
34 |
35 | cdef double znf[2]
36 | znf[0] = 1e10
37 | znf[1] = -1e10
38 | cdef double z
39 | for i in range(vNum):
40 | z = VM[2*vNum+i]
41 | if (zznf[1]):
44 | znf[1] = z
45 |
46 | znf[0] -= 0.1;
47 | znf[1] += 0.1;
48 | znf[0] = max(znf[0],0.1);
49 | znf[1] = max(znf[1],znf[0]+0.1);
50 |
51 | depth = np.empty((img_size[0], img_size[1]), dtype=np.float32)
52 | cdef float[:,::1] depth_view = depth
53 | cdef float* depthBuffer = &(depth_view[0,0])
54 |
55 | renderDepthMesh(FM, fNum, VM, vNum, intrinsics, imgSize, znf, depthBuffer);
56 |
57 | return depth
58 |
--------------------------------------------------------------------------------
/external/pyrender/setup.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup
2 | from Cython.Build import cythonize
3 | from distutils.extension import Extension
4 | from Cython.Distutils import build_ext
5 | import numpy as np
6 | import platform
7 |
8 | extra_compile_args = ['-O3', '-std=c++11']
9 | extra_link_args = ['-lGLEW', '-lglut']
10 |
11 | if platform.system() == 'Darwin':
12 | extra_link_args.append('-F/System/Library/Frameworks')
13 | extra_compile_args.append('-stdlib=libc++')
14 | extra_link_args.append('-stdlib=libc++')
15 | else:
16 | extra_link_args.append('-lGL')
17 | extra_link_args.append('-lGLU')
18 | extra_link_args.append('-fopenmp')
19 | extra_compile_args.append('-fopenmp')
20 |
21 | setup(
22 | name="pyrender",
23 | cmdclass= {'build_ext': build_ext},
24 | ext_modules=[
25 | Extension('pyrender',
26 | ['pyrender.pyx',
27 | 'offscreen.cpp',
28 | ],
29 | language='c++',
30 | include_dirs=[np.get_include(),],
31 | extra_compile_args=extra_compile_args,
32 | extra_link_args=extra_link_args
33 | )
34 | ]
35 | )
36 |
37 |
38 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | # Main file for training and testing
2 | # author: ynie
3 | # date: July, 2020
4 |
5 | import argparse
6 | from configs.config_utils import CONFIG
7 |
8 | def parse_args():
9 | '''PARAMETERS'''
10 | parser = argparse.ArgumentParser('Instance Scene Completion.')
11 | parser.add_argument('--config', type=str, default='configs/config_files/ISCNet.yaml',
12 | help='configure file for training or testing.')
13 | parser.add_argument('--mode', type=str, default='train', help='train, test or demo.')
14 | parser.add_argument('--demo_path', type=str, default='demo/inputs/scene0549_00.off', help='Please specify the demo path.')
15 | return parser.parse_args()
16 |
17 | if __name__ == '__main__':
18 | args = parse_args()
19 | cfg = CONFIG(args.config)
20 | cfg.update_config(args.__dict__)
21 | from net_utils.utils import initiate_environment
22 | initiate_environment(cfg.config)
23 |
24 | '''Configuration'''
25 | cfg.log_string('Loading configurations.')
26 | cfg.log_string(cfg.config)
27 | cfg.write_config()
28 |
29 | '''Run'''
30 | if cfg.config['mode'] == 'train':
31 | import train
32 | train.run(cfg)
33 | if cfg.config['mode'] == 'test':
34 | import test
35 | test.run(cfg)
36 | if cfg.config['mode'] == 'demo':
37 | import demo
38 | demo.run(cfg)
39 |
40 |
--------------------------------------------------------------------------------
/models/__init__.py:
--------------------------------------------------------------------------------
1 | from . import iscnet
2 | from . import loss
3 |
4 | method_paths = {
5 | 'ISCNet': iscnet
6 | }
7 |
8 | __all__ = ['method_paths']
--------------------------------------------------------------------------------
/models/datasets.py:
--------------------------------------------------------------------------------
1 | # Base data of networks
2 | # author: ynie
3 | # date: Feb, 2020
4 | import os
5 | from torch.utils.data import Dataset
6 | import json
7 | from utils.read_and_write import read_json
8 |
9 | class ScanNet(Dataset):
10 | def __init__(self, cfg, mode):
11 | '''
12 | initiate SUNRGBD dataset for data loading
13 | :param cfg: config file
14 | :param mode: train/val/test mode
15 | '''
16 | self.config = cfg.config
17 | self.dataset_config = cfg.dataset_config
18 | self.mode = mode
19 | split_file = os.path.join(cfg.config['data']['split'], 'scannetv2_' + mode + '.json')
20 | self.split = read_json(split_file)
21 |
22 | def __len__(self):
23 | return len(self.split)
--------------------------------------------------------------------------------
/models/iscnet/__init__.py:
--------------------------------------------------------------------------------
1 | from . import modules, training, config, dataloader
2 |
3 | __all__ = ['modules', 'training', 'config', 'dataloader']
--------------------------------------------------------------------------------
/models/iscnet/config.py:
--------------------------------------------------------------------------------
1 | # Configure trainer and tester
2 | # author: ynie
3 | # date: Feb, 2020
4 | from .dataloader import ISCNet_dataloader
5 | from .testing import Tester
6 | from .training import Trainer
7 |
8 |
9 | def get_trainer(cfg, net, optimizer, device=None):
10 | return Trainer(cfg=cfg, net=net, optimizer=optimizer, device=device)
11 |
12 |
13 | def get_tester(cfg, net, device=None):
14 | return Tester(cfg=cfg, net=net, device=device)
15 |
16 |
17 | def get_dataloader(cfg, mode):
18 | return ISCNet_dataloader(cfg=cfg, mode=mode)
19 |
--------------------------------------------------------------------------------
/models/iscnet/modules/__init__.py:
--------------------------------------------------------------------------------
1 | from .network import ISCNet
2 | from .pointnet2backbone import Pointnet2Backbone
3 | from .proposal_module import ProposalModule
4 | from .vote_module import VotingModule
5 | from .occupancy_net import ONet
6 | from .skip_propagation import SkipPropagation
7 |
8 | __all__ = ['ISCNet', 'Pointnet2Backbone', 'ProposalModule', 'VotingModule', 'ONet', 'SkipPropagation']
--------------------------------------------------------------------------------
/models/iscnet/modules/encoder_latent.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | import torch.nn.functional as F
4 |
5 |
6 | # Max Pooling operation
7 | def maxpool(x, dim=-1, keepdim=False):
8 | out, _ = x.max(dim=dim, keepdim=keepdim)
9 | return out
10 |
11 |
12 | class Encoder_Latent(nn.Module):
13 | ''' Latent encoder class.
14 |
15 | It encodes the input points and returns mean and standard deviation for the
16 | posterior Gaussian distribution.
17 |
18 | Args:
19 | z_dim (int): dimension if output code z
20 | c_dim (int): dimension of latent conditioned code c
21 | dim (int): input dimension
22 | leaky (bool): whether to use leaky ReLUs
23 | '''
24 | def __init__(self, z_dim=128, c_dim=128, dim=3, leaky=False):
25 | super().__init__()
26 | self.z_dim = z_dim
27 | self.c_dim = c_dim
28 |
29 | # Submodules
30 | self.fc_pos = nn.Linear(dim, 128)
31 |
32 | if c_dim != 0:
33 | self.fc_c = nn.Linear(c_dim, 128)
34 |
35 | self.fc_0 = nn.Linear(1, 128)
36 | self.fc_1 = nn.Linear(128, 128)
37 | self.fc_2 = nn.Linear(256, 128)
38 | self.fc_3 = nn.Linear(256, 128)
39 | self.fc_mean = nn.Linear(128, z_dim)
40 | self.fc_logstd = nn.Linear(128, z_dim)
41 |
42 | if not leaky:
43 | self.actvn = F.relu
44 | self.pool = maxpool
45 | else:
46 | self.actvn = lambda x: F.leaky_relu(x, 0.2)
47 | self.pool = torch.mean
48 |
49 | def forward(self, p, x, c=None, **kwargs):
50 | # output size: B x T X F
51 | net = self.fc_0(x.unsqueeze(-1))
52 | net = net + self.fc_pos(p)
53 |
54 | if self.c_dim != 0:
55 | net = net + self.fc_c(c).unsqueeze(1)
56 |
57 | net = self.fc_1(self.actvn(net))
58 | pooled = self.pool(net, dim=1, keepdim=True).expand(net.size())
59 | net = torch.cat([net, pooled], dim=2)
60 |
61 | net = self.fc_2(self.actvn(net))
62 | pooled = self.pool(net, dim=1, keepdim=True).expand(net.size())
63 | net = torch.cat([net, pooled], dim=2)
64 |
65 | net = self.fc_3(self.actvn(net))
66 | # Reduce
67 | # to B x F
68 | net = self.pool(net, dim=1)
69 |
70 | mean = self.fc_mean(net)
71 | logstd = self.fc_logstd(net)
72 |
73 | return mean, logstd
74 |
--------------------------------------------------------------------------------
/models/iscnet/modules/occ_decoder.py:
--------------------------------------------------------------------------------
1 | import torch.nn as nn
2 | from .layers import (
3 | CResnetBlockConv1d,
4 | CBatchNorm1d, CBatchNorm1d_legacy,
5 | )
6 | import torch.nn.functional as F
7 | from models.iscnet.modules.layers import ResnetBlockFC
8 |
9 | class SimpleDecoder(nn.Module):
10 | ''' Decoder class.
11 |
12 | It does not perform any form of normalization.
13 |
14 | Args:
15 | dim (int): input dimension
16 | z_dim (int): dimension of latent code z
17 | c_dim (int): dimension of latent conditioned code c
18 | hidden_size (int): hidden size of Decoder network
19 | leaky (bool): whether to use leaky ReLUs
20 | '''
21 |
22 | def __init__(self, dim=3, z_dim=128, c_dim=128,
23 | hidden_size=128, leaky=False):
24 | super().__init__()
25 | self.z_dim = z_dim
26 | self.c_dim = c_dim
27 |
28 | # Submodules
29 | self.fc_p = nn.Linear(dim, hidden_size)
30 |
31 | if not z_dim == 0:
32 | self.fc_z = nn.Linear(z_dim, hidden_size)
33 |
34 | if not c_dim == 0:
35 | self.fc_c = nn.Linear(c_dim, hidden_size)
36 |
37 | self.block0 = ResnetBlockFC(hidden_size)
38 | self.block1 = ResnetBlockFC(hidden_size)
39 | self.block2 = ResnetBlockFC(hidden_size)
40 | self.block3 = ResnetBlockFC(hidden_size)
41 | self.block4 = ResnetBlockFC(hidden_size)
42 |
43 | self.fc_out = nn.Linear(hidden_size, 1)
44 |
45 | if not leaky:
46 | self.actvn = F.relu
47 | else:
48 | self.actvn = lambda x: F.leaky_relu(x, 0.2)
49 |
50 | def forward(self, p, z, c=None, **kwargs):
51 | net = self.fc_p(p)
52 |
53 | if self.z_dim != 0:
54 | net_z = self.fc_z(z).unsqueeze(1)
55 | net = net + net_z
56 |
57 | if self.c_dim != 0:
58 | net_c = self.fc_c(c).unsqueeze(1)
59 | net = net + net_c
60 |
61 | net = self.block0(net)
62 | net = self.block1(net)
63 | net = self.block2(net)
64 | net = self.block3(net)
65 | net = self.block4(net)
66 |
67 | out = self.fc_out(self.actvn(net))
68 | out = out.squeeze(-1)
69 |
70 | return out
71 |
72 | class DecoderCBatchNorm(nn.Module):
73 | ''' Decoder with conditional batch normalization (CBN) class.
74 |
75 | Args:
76 | dim (int): input dimension
77 | z_dim (int): dimension of latent code z
78 | c_dim (int): dimension of latent conditioned code c
79 | hidden_size (int): hidden size of Decoder network
80 | n_blocks (int): number of CResNet blocks.
81 | leaky (bool): whether to use leaky ReLUs
82 | legacy (bool): whether to use the legacy structure
83 | '''
84 |
85 | def __init__(self, dim=3, z_dim=128, c_dim=128,
86 | hidden_size=256, n_blocks=5, leaky=False, legacy=False):
87 | super().__init__()
88 | self.z_dim = z_dim
89 | if not z_dim == 0:
90 | self.fc_z = nn.Linear(z_dim, hidden_size)
91 |
92 | self.fc_p = nn.Conv1d(dim, hidden_size, 1)
93 |
94 | self.blocks = nn.ModuleList([
95 | CResnetBlockConv1d(c_dim, hidden_size) for i in range(n_blocks)
96 | ])
97 |
98 | if not legacy:
99 | self.bn = CBatchNorm1d(c_dim, hidden_size)
100 | else:
101 | self.bn = CBatchNorm1d_legacy(c_dim, hidden_size)
102 |
103 | self.fc_out = nn.Conv1d(hidden_size, 1, 1)
104 |
105 | if not leaky:
106 | self.actvn = nn.ReLU(inplace=True)
107 | else:
108 | self.actvn = nn.LeakyReLU(0.2, inplace=True)
109 |
110 | def forward(self, p, z, c, **kwargs):
111 | p = p.transpose(1, 2)
112 | net = self.fc_p(p)
113 |
114 | if self.z_dim != 0:
115 | net = net + self.fc_z(z).unsqueeze(2)
116 |
117 | for block in self.blocks:
118 | net = block(net, c)
119 |
120 | out = self.fc_out(self.actvn(self.bn(net, c)))
121 | out = out.squeeze(1)
122 |
123 | return out
--------------------------------------------------------------------------------
/models/iscnet/modules/pointnet2backbone.py:
--------------------------------------------------------------------------------
1 | # pointnet backbone
2 | # author: ynie
3 | # date: March, 2020
4 | # cite: VoteNet
5 | import torch
6 | import torch.nn as nn
7 | from models.registers import MODULES
8 | from external.pointnet2_ops_lib.pointnet2_ops.pointnet2_modules import PointnetSAModuleVotes, PointnetFPModule
9 |
10 | @MODULES.register_module
11 | class Pointnet2Backbone(nn.Module):
12 | def __init__(self, cfg, optim_spec = None):
13 | '''
14 | Skeleton Extraction Net to obtain partial skeleton from a partial scan (refer to PointNet++).
15 | :param cfg: configuration file.
16 | :param optim_spec: optimizer parameters.
17 | '''
18 | super(Pointnet2Backbone, self).__init__()
19 |
20 | '''Optimizer parameters used in training'''
21 | self.optim_spec = optim_spec
22 |
23 | '''Network parameters'''
24 | self.input_feature_dim = int(cfg.config['data']['use_color_detection']) * 3 + int(not cfg.config['data']['no_height']) * 1
25 |
26 | '''Modules'''
27 | self.sa1 = PointnetSAModuleVotes(
28 | npoint=2048,
29 | radius=0.2,
30 | nsample=64,
31 | mlp=[self.input_feature_dim, 64, 64, 128],
32 | use_xyz=True,
33 | normalize_xyz=True
34 | )
35 |
36 | self.sa2 = PointnetSAModuleVotes(
37 | npoint=1024,
38 | radius=0.4,
39 | nsample=32,
40 | mlp=[128, 128, 128, 256],
41 | use_xyz=True,
42 | normalize_xyz=True
43 | )
44 |
45 | self.sa3 = PointnetSAModuleVotes(
46 | npoint=512,
47 | radius=0.8,
48 | nsample=16,
49 | mlp=[256, 128, 128, 256],
50 | use_xyz=True,
51 | normalize_xyz=True
52 | )
53 |
54 | self.sa4 = PointnetSAModuleVotes(
55 | npoint=256,
56 | radius=1.2,
57 | nsample=16,
58 | mlp=[256, 128, 128, 256],
59 | use_xyz=True,
60 | normalize_xyz=True
61 | )
62 |
63 | self.fp1 = PointnetFPModule(mlp=[256+256,256,256])
64 | self.fp2 = PointnetFPModule(mlp=[256+256,256,256])
65 |
66 | def _break_up_pc(self, pc):
67 | xyz = pc[..., 0:3].contiguous()
68 | features = (
69 | pc[..., 3:3+self.input_feature_dim].transpose(1, 2).contiguous()
70 | if pc.size(-1) > 3 else None
71 | )
72 |
73 | return xyz, features
74 |
75 | def forward(self, pointcloud: torch.cuda.FloatTensor, end_points=None):
76 | r"""
77 | Forward pass of the network
78 |
79 | Parameters
80 | ----------
81 | pointcloud: Variable(torch.cuda.FloatTensor)
82 | (B, N, 3 + input_feature_dim) tensor
83 | Point cloud to run predicts on
84 | Each point in the point-cloud MUST
85 | be formated as (x, y, z, features...)
86 |
87 | Returns
88 | ----------
89 | end_points: {XXX_xyz, XXX_features, XXX_inds}
90 | XXX_xyz: float32 Tensor of shape (B,K,3)
91 | XXX_features: float32 Tensor of shape (B,K,D)
92 | XXX-inds: int64 Tensor of shape (B,K) values in [0,N-1]
93 | """
94 | if not end_points: end_points = {}
95 |
96 | xyz, features = self._break_up_pc(pointcloud)
97 |
98 | # --------- 4 SET ABSTRACTION LAYERS ---------
99 | xyz, features, fps_inds = self.sa1(xyz, features)
100 | end_points['sa1_inds'] = fps_inds
101 | end_points['sa1_xyz'] = xyz
102 | end_points['sa1_features'] = features
103 |
104 | xyz, features, fps_inds = self.sa2(xyz, features) # this fps_inds is just 0,1,...,1023
105 | end_points['sa2_inds'] = fps_inds
106 | end_points['sa2_xyz'] = xyz
107 | end_points['sa2_features'] = features
108 |
109 | xyz, features, fps_inds = self.sa3(xyz, features) # this fps_inds is just 0,1,...,511
110 | end_points['sa3_xyz'] = xyz
111 | end_points['sa3_features'] = features
112 |
113 | xyz, features, fps_inds = self.sa4(xyz, features) # this fps_inds is just 0,1,...,255
114 | end_points['sa4_xyz'] = xyz
115 | end_points['sa4_features'] = features
116 |
117 | # --------- 2 FEATURE UPSAMPLING LAYERS --------
118 | features = self.fp1(end_points['sa3_xyz'], end_points['sa4_xyz'], end_points['sa3_features'],
119 | end_points['sa4_features'])
120 | features = self.fp2(end_points['sa2_xyz'], end_points['sa3_xyz'], end_points['sa2_features'], features)
121 | end_points['fp2_features'] = features
122 | end_points['fp2_xyz'] = end_points['sa2_xyz']
123 | num_seed = end_points['fp2_xyz'].shape[1]
124 | end_points['fp2_inds'] = end_points['sa1_inds'][:, 0:num_seed] # indices among the entire input point clouds
125 | return end_points
126 |
127 |
--------------------------------------------------------------------------------
/models/iscnet/modules/vote_module.py:
--------------------------------------------------------------------------------
1 | # pointnet backbone
2 | # author: ynie
3 | # date: March, 2020
4 | # cite: VoteNet
5 | import torch
6 | import torch.nn as nn
7 | from models.registers import MODULES
8 | import torch.nn.functional as F
9 |
10 |
11 | @MODULES.register_module
12 | class VotingModule(nn.Module):
13 | def __init__(self, cfg, optim_spec = None):
14 | '''
15 | Skeleton Extraction Net to obtain partial skeleton from a partial scan (refer to PointNet++).
16 | :param config: configuration file.
17 | :param optim_spec: optimizer parameters.
18 | '''
19 | super(VotingModule, self).__init__()
20 |
21 | '''Optimizer parameters used in training'''
22 | self.optim_spec = optim_spec
23 |
24 | '''Modules'''
25 | self.vote_factor = cfg.config['data']['vote_factor']
26 | self.in_dim = 256
27 | self.out_dim = self.in_dim # due to residual feature, in_dim has to be == out_dim
28 | self.conv1 = torch.nn.Conv1d(self.in_dim, self.in_dim, 1)
29 | self.conv2 = torch.nn.Conv1d(self.in_dim, self.in_dim, 1)
30 | self.conv3 = torch.nn.Conv1d(self.in_dim, (3+self.out_dim) * self.vote_factor, 1)
31 | self.bn1 = torch.nn.BatchNorm1d(self.in_dim)
32 | self.bn2 = torch.nn.BatchNorm1d(self.in_dim)
33 |
34 | def forward(self, seed_xyz, seed_features):
35 | """ Forward pass.
36 |
37 | Arguments:
38 | seed_xyz: (batch_size, num_seed, 3) Pytorch tensor
39 | seed_features: (batch_size, feature_dim, num_seed) Pytorch tensor
40 | Returns:
41 | vote_xyz: (batch_size, num_seed*vote_factor, 3)
42 | vote_features: (batch_size, vote_feature_dim, num_seed*vote_factor)
43 | """
44 | batch_size = seed_xyz.shape[0]
45 | num_seed = seed_xyz.shape[1]
46 | num_vote = num_seed * self.vote_factor
47 | net = F.relu(self.bn1(self.conv1(seed_features)))
48 | net = F.relu(self.bn2(self.conv2(net)))
49 | net = self.conv3(net) # (batch_size, (3+out_dim)*vote_factor, num_seed)
50 |
51 | net = net.transpose(2, 1).view(batch_size, num_seed, self.vote_factor, 3 + self.out_dim)
52 | offset = net[:, :, :, 0:3]
53 | vote_xyz = seed_xyz.unsqueeze(2) + offset
54 | vote_xyz = vote_xyz.contiguous().view(batch_size, num_vote, 3)
55 |
56 | residual_features = net[:, :, :, 3:] # (batch_size, num_seed, vote_factor, out_dim)
57 | vote_features = seed_features.transpose(2, 1).unsqueeze(2) + residual_features
58 | vote_features = vote_features.contiguous().view(batch_size, num_vote, self.out_dim)
59 | vote_features = vote_features.transpose(2, 1).contiguous()
60 |
61 | return vote_xyz, vote_features
62 |
63 |
--------------------------------------------------------------------------------
/models/iscnet/training.py:
--------------------------------------------------------------------------------
1 | # Trainer for Total3D.
2 | # author: ynie
3 | # date: Feb, 2020
4 | from models.training import BaseTrainer
5 | import torch
6 | import numpy as np
7 | import os
8 | from net_utils import visualization as vis
9 |
10 | class Trainer(BaseTrainer):
11 | '''
12 | Trainer object for total3d.
13 | '''
14 |
15 | def eval_step(self, data):
16 | '''
17 | performs a step in evaluation
18 | :param data (dict): data dictionary
19 | :return:
20 | '''
21 | loss = self.compute_loss(data)
22 | loss['total'] = loss['total'].item()
23 | return loss
24 |
25 | def visualize_step(self, epoch, phase, iter, data):
26 | ''' Performs a visualization step.
27 | '''
28 | '''load input and ground-truth data'''
29 | data = self.to_device(data)
30 |
31 | with torch.no_grad():
32 | '''network forwarding'''
33 | est_data = self.net({**data, 'export_shape':True})
34 | voxels_out, proposal_to_gt_box_w_cls_list = est_data[2:4]
35 |
36 | if proposal_to_gt_box_w_cls_list is None:
37 | return
38 |
39 | sample_ids = np.random.choice(voxels_out.shape[0], 3, replace=False) if voxels_out.shape[0]>=3 else range(voxels_out.shape[0])
40 | n_shapes_per_batch = self.cfg.config['data']['completion_limit_in_train']
41 | for idx, i in enumerate(sample_ids):
42 | voxel_path = os.path.join(self.cfg.config['log']['vis_path'], '%s_%s_%s_%03d_pred.png' % (epoch, phase, iter, idx))
43 | vis.visualize_voxels(voxels_out[i].cpu().numpy(), voxel_path)
44 |
45 | batch_index = i // n_shapes_per_batch
46 | in_batch_id = i % n_shapes_per_batch
47 | box_id = proposal_to_gt_box_w_cls_list[batch_index][in_batch_id][1].item()
48 | cls_id = proposal_to_gt_box_w_cls_list[batch_index][in_batch_id][2].item()
49 |
50 | voxels_gt = data['object_voxels'][batch_index][box_id].cpu().numpy()
51 | voxel_path = os.path.join(self.cfg.config['log']['vis_path'], '%s_%s_%s_%03d_gt_cls%d.png' % (epoch, phase, iter, idx, cls_id))
52 | vis.visualize_voxels(voxels_gt, voxel_path)
53 |
54 | def to_device(self, data):
55 | device = self.device
56 | for key in data:
57 | if key not in ['object_voxels', 'shapenet_catids', 'shapenet_ids']:
58 | data[key] = data[key].to(device)
59 | return data
60 |
61 | def compute_loss(self, data):
62 | '''
63 | compute the overall loss.
64 | :param data (dict): data dictionary
65 | :return:
66 | '''
67 | '''load input and ground-truth data'''
68 | data = self.to_device(data)
69 |
70 | '''network forwarding'''
71 | est_data = self.net(data)
72 |
73 | '''computer losses'''
74 | loss = self.net.module.loss(est_data, data)
75 | return loss
76 |
--------------------------------------------------------------------------------
/models/network.py:
--------------------------------------------------------------------------------
1 | # Base Network for other networks.
2 | # author: ynie
3 | # date: Feb, 2020
4 |
5 | from models.registers import MODULES, LOSSES
6 | import torch.nn as nn
7 |
8 | def multi_getattr(layer, attr, default=None):
9 | attributes = attr.split(".")
10 | for i in attributes:
11 | try:
12 | layer = getattr(layer, i)
13 | except AttributeError:
14 | if default:
15 | return default
16 | else:
17 | raise
18 | return layer
19 |
20 | def multi_hasattr(layer, attr):
21 | attributes = attr.split(".")
22 | hasattr_flag = True
23 | for i in attributes:
24 | if hasattr(layer, i):
25 | layer = getattr(layer, i)
26 | else:
27 | hasattr_flag = False
28 | return hasattr_flag
29 |
30 | class BaseNetwork(nn.Module):
31 | '''
32 | Base Network Module for other networks
33 | '''
34 | def __init__(self, cfg):
35 | '''
36 | load submodules for the network.
37 | :param config: customized configurations.
38 | '''
39 | super(BaseNetwork, self).__init__()
40 | self.cfg = cfg
41 |
42 | '''load network blocks'''
43 | for phase_name, net_spec in cfg.config['model'].items():
44 | method_name = net_spec['method']
45 | # load specific optimizer parameters
46 | optim_spec = self.load_optim_spec(cfg.config, net_spec)
47 | subnet = MODULES.get(method_name)(cfg.config, optim_spec)
48 | self.add_module(phase_name, subnet)
49 |
50 | '''load corresponding loss functions'''
51 | setattr(self, phase_name + '_loss', LOSSES.get(self.cfg.config['model'][phase_name]['loss'], 'Null')(
52 | self.cfg.config['model'][phase_name].get('weight', 1)))
53 |
54 | '''freeze submodules or not'''
55 | self.freeze_modules(cfg)
56 |
57 | def freeze_modules(self, cfg):
58 | '''
59 | Freeze modules in training
60 | '''
61 | if cfg.config['mode'] == 'train':
62 | freeze_layers = cfg.config['train']['freeze']
63 | for layer in freeze_layers:
64 | if not multi_hasattr(self, layer):
65 | continue
66 | for param in multi_getattr(self, layer).parameters():
67 | param.requires_grad = False
68 | cfg.log_string('The module: %s is fixed.' % (layer))
69 |
70 | def set_mode(self):
71 | '''
72 | Set train/eval mode for the network.
73 | :param phase: train or eval
74 | :return:
75 | '''
76 | freeze_layers = self.cfg.config['train']['freeze']
77 | for name, child in self.named_children():
78 | if name in freeze_layers:
79 | child.train(False)
80 |
81 | def load_weight(self, pretrained_model):
82 | model_dict = self.state_dict()
83 | # remove the 'module' string.
84 | pretrained_dict = {'.'.join(k.split('.')[1:]): v for k, v in pretrained_model.items() if
85 | '.'.join(k.split('.')[1:]) in model_dict}
86 | self.cfg.log_string(
87 | str(set([key.split('.')[0] for key in model_dict if key not in pretrained_dict])) + ' subnet missed.')
88 | model_dict.update(pretrained_dict)
89 | self.load_state_dict(model_dict)
90 |
91 | def load_optim_spec(self, config, net_spec):
92 | # load specific optimizer parameters
93 | if config['mode'] == 'train':
94 | if 'optimizer' in net_spec.keys():
95 | optim_spec = net_spec['optimizer']
96 | else:
97 | optim_spec = config['optimizer'] # else load default optimizer
98 | else:
99 | optim_spec = None
100 |
101 | return optim_spec
102 |
103 | def forward(self, *args, **kwargs):
104 | ''' Performs a forward step.
105 | '''
106 | raise NotImplementedError
107 |
108 | def loss(self, *args, **kwargs):
109 | ''' calculate losses.
110 | '''
111 | raise NotImplementedError
--------------------------------------------------------------------------------
/models/optimizers.py:
--------------------------------------------------------------------------------
1 | # Optimizer definitions
2 | # author: ynie
3 | # date: Feb, 2020
4 | import torch
5 | from external.pointnet2_ops_lib.pointnet2_ops.pytorch_utils import BNMomentumScheduler
6 |
7 | def has_optim_in_children(subnet):
8 | '''
9 | check if there is specific optim parameters in a subnet.
10 | :param subnet:
11 | :return:
12 | '''
13 | label = False
14 | for module in subnet.children():
15 | if hasattr(module, 'optim_spec') and module.optim_spec:
16 | label = True
17 | break
18 | else:
19 | label = has_optim_in_children(module)
20 |
21 | return label
22 |
23 | def find_optim_module(net):
24 | '''
25 | classify modules in a net into has specific optim specs or not.
26 | :param net:
27 | :return:
28 | '''
29 | module_optim_pairs = []
30 | other_modules = []
31 | for module in net.children():
32 | if hasattr(module, 'optim_spec'):
33 | module_optim_pairs += [{'module':module, 'optim_spec':module.optim_spec}]
34 | elif not has_optim_in_children(module):
35 | other_modules += [module]
36 | else:
37 | module_optim_pairs += find_optim_module(module)[0]
38 | other_modules += find_optim_module(module)[1]
39 |
40 | return module_optim_pairs, other_modules
41 |
42 | def load_scheduler(config, optimizer):
43 | '''
44 | get scheduler for optimizer.
45 | :param config: configuration file
46 | :param optimizer: torch optimizer
47 | :return:
48 | '''
49 | scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min',
50 | factor=float(config['scheduler']['factor']),
51 | patience=config['scheduler']['patience'],
52 | threshold=float(config['scheduler']['threshold']),
53 | verbose=True)
54 | return scheduler
55 |
56 | def load_bnm_scheduler(cfg, net, start_epoch):
57 | bn_lbmd = lambda it: max(cfg.config['bnscheduler']['bn_momentum_init'] * cfg.config['bnscheduler']['bn_decay_rate'] ** (
58 | int(it / cfg.config['bnscheduler']['bn_decay_step'])), cfg.config['bnscheduler']['bn_momentum_max'])
59 | bnm_scheduler = BNMomentumScheduler(cfg, net, bn_lambda=bn_lbmd, last_epoch=start_epoch - 1)
60 | return bnm_scheduler
61 |
62 | def load_optimizer(config, net):
63 | '''
64 | get optimizer for networks
65 | :param config: configuration file
66 | :param model: nn.Module network
67 | :return:
68 | '''
69 |
70 | module_optim_pairs, other_modules = find_optim_module(net)
71 | default_optim_spec = config['optimizer']
72 |
73 | optim_params = []
74 |
75 | if config['optimizer']['method'] == 'Adam':
76 | '''collect parameters with specific optimizer spec'''
77 | for module in module_optim_pairs:
78 | optim_params.append({'params': filter(lambda p: p.requires_grad, module['module'].parameters()),
79 | 'lr': float(module['optim_spec']['lr']),
80 | 'betas': tuple(module['optim_spec']['betas']),
81 | 'eps': float(module['optim_spec']['eps']),
82 | 'weight_decay': float(module['optim_spec']['weight_decay'])})
83 |
84 | '''collect parameters with default optimizer spec'''
85 | other_params = list()
86 | for module in other_modules:
87 | other_params += list(module.parameters())
88 |
89 | optim_params.append({'params': filter(lambda p: p.requires_grad, other_params)})
90 |
91 | '''define optimizer'''
92 | optimizer = torch.optim.Adam(optim_params,
93 | lr=float(default_optim_spec['lr']),
94 | betas=tuple(default_optim_spec['betas']),
95 | eps=float(default_optim_spec['eps']),
96 | weight_decay=float(default_optim_spec['weight_decay']))
97 |
98 | else:
99 | # use SGD optimizer.
100 | for module in module_optim_pairs:
101 | optim_params.append({'params': filter(lambda p: p.requires_grad, module['module'].parameters()),
102 | 'lr': float(module['optim_spec']['lr'])})
103 |
104 | other_params = list()
105 | for module in other_modules:
106 | other_params += list(module.parameters())
107 |
108 | optim_params.append({'params': filter(lambda p: p.requires_grad, other_params)})
109 | optimizer = torch.optim.SGD(optim_params,
110 | lr=config['optimizer']['lr'],
111 | momentum=0.9)
112 |
113 | return optimizer
114 |
--------------------------------------------------------------------------------
/models/registers.py:
--------------------------------------------------------------------------------
1 | # Register different methods, and relevant modules
2 | # author: ynie
3 | # date: Feb, 2020
4 |
5 | from net_utils.registry import Registry
6 |
7 | METHODS = Registry('method')
8 | MODULES = Registry('module')
9 | LOSSES = Registry('loss')
--------------------------------------------------------------------------------
/models/testing.py:
--------------------------------------------------------------------------------
1 | # Base tester for methods.
2 | # author: ynie
3 | # date: April, 2020
4 |
5 | class BaseTester(object):
6 | '''
7 | Base tester for all networks.
8 | '''
9 | def __init__(self, cfg, net, device=None):
10 | self.cfg = cfg
11 | self.net = net
12 | self.device = device
13 |
14 | def visualize_step(self, *args, **kwargs):
15 | ''' Performs a visualization step.
16 | '''
17 | raise NotImplementedError
18 |
19 | def get_metric_values(self, est_data, gt_data):
20 | ''' Performs a evaluation step.
21 | '''
22 | # camera orientation error
23 | raise NotImplementedError
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/models/training.py:
--------------------------------------------------------------------------------
1 | # Base trainer for methods.
2 | # author: ynie
3 | # date: Feb, 2020
4 |
5 | class BaseTrainer(object):
6 | '''
7 | Base trainer for all networks.
8 | '''
9 | def __init__(self, cfg, net, optimizer, device=None):
10 | self.cfg = cfg
11 | self.net = net
12 | self.optimizer = optimizer
13 | self.device = device
14 |
15 | def show_lr(self):
16 | '''
17 | display current learning rates
18 | :return:
19 | '''
20 | lrs = [self.optimizer.param_groups[i]['lr'] for i in range(len(self.optimizer.param_groups))]
21 | self.cfg.log_string('Current learning rates are: ' + str(lrs) + '.')
22 |
23 | def train_step(self, data):
24 | '''
25 | performs a step training
26 | :param data (dict): data dictionary
27 | :return:
28 | '''
29 | self.optimizer.zero_grad()
30 | loss = self.compute_loss(data)
31 | if loss['total'].requires_grad:
32 | loss['total'].backward()
33 | self.optimizer.step()
34 |
35 | loss['total'] = loss['total'].item()
36 | return loss
37 |
38 | def eval_loss_parser(self, loss_recorder):
39 | '''
40 | get the eval
41 | :param loss_recorder: loss recorder for all losses.
42 | :return:
43 | '''
44 | return loss_recorder['total'].avg
45 |
46 | def compute_loss(self, *args, **kwargs):
47 | ''' Performs a training step.
48 | '''
49 | raise NotImplementedError
50 |
51 | def eval_step(self, *args, **kwargs):
52 | ''' Performs an evaluation step.
53 | '''
54 | raise NotImplementedError
55 |
56 | def visualize_step(self, *args, **kwargs):
57 | ''' Performs a visualization step.
58 | '''
59 | raise NotImplementedError
--------------------------------------------------------------------------------
/net_utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/net_utils/__init__.py
--------------------------------------------------------------------------------
/net_utils/metric_util.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Facebook, Inc. and its affiliates.
2 | #
3 | # This source code is licensed under the MIT license found in the
4 | # LICENSE file in the root directory of this source tree.
5 |
6 | """ Utility functions for metric evaluation.
7 |
8 | Author: Or Litany and Charles R. Qi
9 | """
10 | import numpy as np
11 |
12 | def calc_iou(box_a, box_b):
13 | """Computes IoU of two axis aligned bboxes.
14 | Args:
15 | box_a, box_b: 6D of center and lengths
16 | Returns:
17 | iou
18 | """
19 |
20 | max_a = box_a[0:3] + box_a[3:6] / 2
21 | max_b = box_b[0:3] + box_b[3:6] / 2
22 | min_max = np.array([max_a, max_b]).min(0)
23 |
24 | min_a = box_a[0:3] - box_a[3:6] / 2
25 | min_b = box_b[0:3] - box_b[3:6] / 2
26 | max_min = np.array([min_a, min_b]).max(0)
27 | if not ((min_max > max_min).all()):
28 | return 0.0
29 |
30 | intersection = (min_max - max_min).prod()
31 | vol_a = box_a[3:6].prod()
32 | vol_b = box_b[3:6].prod()
33 | union = vol_a + vol_b - intersection
34 | return 1.0 * intersection / union
--------------------------------------------------------------------------------
/net_utils/nms.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Facebook, Inc. and its affiliates.
2 | #
3 | # This source code is licensed under the MIT license found in the
4 | # LICENSE file in the root directory of this source tree.
5 | import numpy as np
6 |
7 | def nms_2d_faster(boxes, overlap_threshold, old_type=False):
8 | x1 = boxes[:,0]
9 | y1 = boxes[:,1]
10 | x2 = boxes[:,2]
11 | y2 = boxes[:,3]
12 | score = boxes[:,4]
13 | area = (x2-x1)*(y2-y1)
14 |
15 | I = np.argsort(score)
16 | pick = []
17 | while (I.size!=0):
18 | last = I.size
19 | i = I[-1]
20 | pick.append(i)
21 |
22 | xx1 = np.maximum(x1[i], x1[I[:last-1]])
23 | yy1 = np.maximum(y1[i], y1[I[:last-1]])
24 | xx2 = np.minimum(x2[i], x2[I[:last-1]])
25 | yy2 = np.minimum(y2[i], y2[I[:last-1]])
26 |
27 | w = np.maximum(0, xx2-xx1)
28 | h = np.maximum(0, yy2-yy1)
29 |
30 | if old_type:
31 | o = (w*h)/area[I[:last-1]]
32 | else:
33 | inter = w*h
34 | o = inter / (area[i] + area[I[:last-1]] - inter)
35 |
36 | I = np.delete(I, np.concatenate(([last-1], np.where(o>overlap_threshold)[0])))
37 |
38 | return pick
39 |
40 |
41 | def nms_3d_faster(boxes, overlap_threshold, old_type=False):
42 | x1 = boxes[:,0]
43 | y1 = boxes[:,1]
44 | z1 = boxes[:,2]
45 | x2 = boxes[:,3]
46 | y2 = boxes[:,4]
47 | z2 = boxes[:,5]
48 | score = boxes[:,6]
49 | area = (x2-x1)*(y2-y1)*(z2-z1)
50 |
51 | I = np.argsort(score)
52 | pick = []
53 | while (I.size!=0):
54 | last = I.size
55 | i = I[-1]
56 | pick.append(i)
57 |
58 | xx1 = np.maximum(x1[i], x1[I[:last-1]])
59 | yy1 = np.maximum(y1[i], y1[I[:last-1]])
60 | zz1 = np.maximum(z1[i], z1[I[:last-1]])
61 | xx2 = np.minimum(x2[i], x2[I[:last-1]])
62 | yy2 = np.minimum(y2[i], y2[I[:last-1]])
63 | zz2 = np.minimum(z2[i], z2[I[:last-1]])
64 |
65 | l = np.maximum(0, xx2-xx1)
66 | w = np.maximum(0, yy2-yy1)
67 | h = np.maximum(0, zz2-zz1)
68 |
69 | if old_type:
70 | o = (l*w*h)/area[I[:last-1]]
71 | else:
72 | inter = l*w*h
73 | o = inter / (area[i] + area[I[:last-1]] - inter)
74 |
75 | I = np.delete(I, np.concatenate(([last-1], np.where(o>overlap_threshold)[0])))
76 |
77 | return pick
78 |
79 | def nms_3d_faster_samecls(boxes, overlap_threshold, old_type=False):
80 | x1 = boxes[:,0]
81 | y1 = boxes[:,1]
82 | z1 = boxes[:,2]
83 | x2 = boxes[:,3]
84 | y2 = boxes[:,4]
85 | z2 = boxes[:,5]
86 | score = boxes[:,6]
87 | cls = boxes[:,7]
88 | area = (x2-x1)*(y2-y1)*(z2-z1)
89 |
90 | I = np.argsort(score)
91 | pick = []
92 | while (I.size!=0):
93 | last = I.size
94 | i = I[-1]
95 | pick.append(i)
96 |
97 | xx1 = np.maximum(x1[i], x1[I[:last-1]])
98 | yy1 = np.maximum(y1[i], y1[I[:last-1]])
99 | zz1 = np.maximum(z1[i], z1[I[:last-1]])
100 | xx2 = np.minimum(x2[i], x2[I[:last-1]])
101 | yy2 = np.minimum(y2[i], y2[I[:last-1]])
102 | zz2 = np.minimum(z2[i], z2[I[:last-1]])
103 | cls1 = cls[i]
104 | cls2 = cls[I[:last-1]]
105 |
106 | l = np.maximum(0, xx2-xx1)
107 | w = np.maximum(0, yy2-yy1)
108 | h = np.maximum(0, zz2-zz1)
109 |
110 | if old_type:
111 | o = (l*w*h)/area[I[:last-1]]
112 | else:
113 | inter = l*w*h
114 | o = inter / (area[i] + area[I[:last-1]] - inter)
115 | o = o * (cls1==cls2)
116 |
117 | I = np.delete(I, np.concatenate(([last-1], np.where(o>overlap_threshold)[0])))
118 |
119 | return pick
--------------------------------------------------------------------------------
/net_utils/nn_distance.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Facebook, Inc. and its affiliates.
2 | #
3 | # This source code is licensed under the MIT license found in the
4 | # LICENSE file in the root directory of this source tree.
5 |
6 | """ Chamfer distance in Pytorch.
7 | Author: Charles R. Qi
8 | """
9 |
10 | import torch
11 | import torch.nn as nn
12 | import numpy as np
13 |
14 |
15 | def huber_loss(error, delta=1.0):
16 | """
17 | Args:
18 | error: Torch tensor (d1,d2,...,dk)
19 | Returns:
20 | loss: Torch tensor (d1,d2,...,dk)
21 |
22 | x = error = pred - gt or dist(pred,gt)
23 | 0.5 * |x|^2 if |x|<=d
24 | 0.5 * d^2 + d * (|x|-d) if |x|>d
25 | Ref: https://github.com/charlesq34/frustum-pointnets/blob/master/models/model_util.py
26 | """
27 | abs_error = torch.abs(error)
28 | #quadratic = torch.min(abs_error, torch.FloatTensor([delta]))
29 | quadratic = torch.clamp(abs_error, max=delta)
30 | linear = (abs_error - quadratic)
31 | loss = 0.5 * quadratic**2 + delta * linear
32 | return loss
33 |
34 | def nn_distance(pc1, pc2, l1smooth=False, delta=1.0, l1=False):
35 | """
36 | Input:
37 | pc1: (B,N,C) torch tensor
38 | pc2: (B,M,C) torch tensor
39 | l1smooth: bool, whether to use l1smooth loss
40 | delta: scalar, the delta used in l1smooth loss
41 | Output:
42 | dist1: (B,N) torch float32 tensor
43 | idx1: (B,N) torch int64 tensor
44 | dist2: (B,M) torch float32 tensor
45 | idx2: (B,M) torch int64 tensor
46 | """
47 | N = pc1.shape[1]
48 | M = pc2.shape[1]
49 | pc1_expand_tile = pc1.unsqueeze(2).repeat(1,1,M,1)
50 | pc2_expand_tile = pc2.unsqueeze(1).repeat(1,N,1,1)
51 | pc_diff = pc1_expand_tile - pc2_expand_tile
52 |
53 | if l1smooth:
54 | pc_dist = torch.sum(huber_loss(pc_diff, delta), dim=-1) # (B,N,M)
55 | elif l1:
56 | pc_dist = torch.sum(torch.abs(pc_diff), dim=-1) # (B,N,M)
57 | else:
58 | pc_dist = torch.sum(pc_diff**2, dim=-1) # (B,N,M)
59 | dist1, idx1 = torch.min(pc_dist, dim=2) # (B,N)
60 | dist2, idx2 = torch.min(pc_dist, dim=1) # (B,M)
61 | return dist1, idx1, dist2, idx2
62 |
63 | def demo_nn_distance():
64 | np.random.seed(0)
65 | pc1arr = np.random.random((1,5,3))
66 | pc2arr = np.random.random((1,6,3))
67 | pc1 = torch.from_numpy(pc1arr.astype(np.float32))
68 | pc2 = torch.from_numpy(pc2arr.astype(np.float32))
69 | dist1, idx1, dist2, idx2 = nn_distance(pc1, pc2)
70 | print(dist1)
71 | print(idx1)
72 | dist = np.zeros((5,6))
73 | for i in range(5):
74 | for j in range(6):
75 | dist[i,j] = np.sum((pc1arr[0,i,:] - pc2arr[0,j,:]) ** 2)
76 | print(dist)
77 | print('-'*30)
78 | print('L1smooth dists:')
79 | dist1, idx1, dist2, idx2 = nn_distance(pc1, pc2, True)
80 | print(dist1)
81 | print(idx1)
82 | dist = np.zeros((5,6))
83 | for i in range(5):
84 | for j in range(6):
85 | error = np.abs(pc1arr[0,i,:] - pc2arr[0,j,:])
86 | quad = np.minimum(error, 1.0)
87 | linear = error - quad
88 | loss = 0.5*quad**2 + 1.0*linear
89 | dist[i,j] = np.sum(loss)
90 | print(dist)
91 |
92 |
93 | if __name__ == '__main__':
94 | demo_nn_distance()
95 |
--------------------------------------------------------------------------------
/net_utils/registry.py:
--------------------------------------------------------------------------------
1 | # registry networks for different methods
2 | # author: ynie
3 | # date: Feb, 2020
4 | import inspect
5 |
6 | class Registry(object):
7 |
8 | def __init__(self, name):
9 | self._name = name
10 | self._module_dict = dict()
11 |
12 | def __repr__(self):
13 | format_str = self.__class__.__name__ + '(name={}, items={})'.format(
14 | self._name, list(self._module_dict.keys()))
15 | return format_str
16 |
17 | @property
18 | def name(self):
19 | return self._name
20 |
21 | @property
22 | def module_dict(self):
23 | return self._module_dict
24 |
25 | def get(self, key, alter_key = None):
26 | if key in self._module_dict:
27 | return self._module_dict.get(key)
28 | else:
29 | return self._module_dict.get(alter_key, None)
30 |
31 | def _register_module(self, module_class):
32 | '''
33 | register a module.
34 | :param module_class (`nn.Module`): Module to be registered.
35 | :return:
36 | '''
37 | if not inspect.isclass(module_class):
38 | raise TypeError('module must be a class, but got {}'.format(
39 | type(module_class)))
40 | module_name = module_class.__name__
41 | if module_name in self._module_dict:
42 | raise KeyError('{} is already registered in {}'.format(
43 | module_name, self.name))
44 | self._module_dict[module_name] = module_class
45 |
46 | def register_module(self, cls):
47 | self._register_module(cls)
48 | return cls
--------------------------------------------------------------------------------
/net_utils/transforms.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | class SubsamplePoints(object):
4 | ''' Points subsampling transformation class.
5 |
6 | It subsamples the points data.
7 |
8 | Args:
9 | N (int): number of points to be subsampled
10 | '''
11 | def __init__(self, N, mode):
12 | self.N = N
13 | self.mode = mode
14 |
15 | def __call__(self, data):
16 | ''' Calls the transformation.
17 |
18 | Args:
19 | data (dictionary): data dictionary
20 | '''
21 | points = data['points']
22 | occ = data['occ']
23 |
24 | data_out = data.copy()
25 | if isinstance(self.N, int):
26 | if self.mode == 'test':
27 | idx = np.arange(0, self.N)
28 | else:
29 | idx = np.random.randint(points.shape[0], size=self.N)
30 | data_out.update({
31 | 'points': points[idx, :],
32 | 'occ': occ[idx],
33 | })
34 | else:
35 | Nt_out, Nt_in = self.N
36 | occ_binary = (occ >= 0.5)
37 | points0 = points[~occ_binary]
38 | points1 = points[occ_binary]
39 |
40 | if self.mode == 'test':
41 | idx0 = np.arange(0, Nt_out)
42 | idx1 = np.arange(0, Nt_in)
43 | else:
44 | idx0 = np.random.randint(points0.shape[0], size=Nt_out)
45 | idx1 = np.random.randint(points1.shape[0], size=Nt_in)
46 |
47 | points0 = points0[idx0, :]
48 | points1 = points1[idx1, :]
49 | points = np.concatenate([points0, points1], axis=0)
50 |
51 | occ0 = np.zeros(Nt_out, dtype=np.float32)
52 | occ1 = np.ones(Nt_in, dtype=np.float32)
53 | occ = np.concatenate([occ0, occ1], axis=0)
54 |
55 | volume = occ_binary.sum() / len(occ_binary)
56 | volume = volume.astype(np.float32)
57 |
58 | data_out.update({
59 | 'points': points,
60 | 'occ': occ,
61 | 'volume': volume,
62 | })
63 | return data_out
--------------------------------------------------------------------------------
/net_utils/visualization.py:
--------------------------------------------------------------------------------
1 | # Visualization functions
2 | # author: ynie
3 | # date: Feb, 2020
4 |
5 | import numpy as np
6 | from matplotlib import pyplot as plt
7 | plt.switch_backend('agg')
8 | from mpl_toolkits.mplot3d import Axes3D
9 | from torchvision.utils import save_image
10 |
11 | def visualize_voxels(voxels, out_file=None, show=False):
12 | '''
13 | Visualizes voxel data.
14 | :param voxels (tensor): voxel data
15 | :param out_file (string): output file
16 | :param show (bool): whether the plot should be shown
17 | :return:
18 | '''
19 | # Use numpy
20 | voxels = np.asarray(voxels)
21 | # Create plot
22 | fig = plt.figure()
23 | ax = fig.gca(projection=Axes3D.name)
24 | voxels = voxels.transpose(2, 0, 1)
25 | ax.voxels(voxels, edgecolor='k')
26 | ax.set_xlabel('Z')
27 | ax.set_ylabel('X')
28 | ax.set_zlabel('Y')
29 | ax.view_init(elev=30, azim=45)
30 | if out_file is not None:
31 | plt.savefig(out_file)
32 | if show:
33 | plt.show()
34 | plt.close(fig)
35 |
36 | def visualize_pointcloud(points, normals=None,
37 | out_file=None, show=False):
38 | '''
39 | Visualizes point cloud data.
40 | :param points (tensor): point data
41 | :param normals (tensor): normal data (if existing)
42 | :param out_file (string): output file
43 | :param show (bool): whether the plot should be shown
44 | :return:
45 | '''
46 | # Use numpy
47 | points = np.asarray(points)
48 | # Create plot
49 | fig = plt.figure()
50 | ax = fig.gca(projection=Axes3D.name)
51 | ax.scatter(points[:, 0], points[:, 1], points[:, 2], s=1)
52 | if normals is not None:
53 | ax.quiver(
54 | points[:, 0], points[:, 1], points[:, 2],
55 | normals[:, 0], normals[:, 1], normals[:, 2],
56 | length=0.1, color='k'
57 | )
58 | ax.set_xlabel('X')
59 | ax.set_ylabel('Y')
60 | ax.set_zlabel('Z')
61 | ax.set_xlim(-0.5, 0.5)
62 | ax.set_ylim(-0.5, 0.5)
63 | ax.set_zlim(-0.5, 0.5)
64 | ax.view_init(elev=30, azim=45)
65 | if out_file is not None:
66 | plt.savefig(out_file)
67 | if show:
68 | plt.show()
69 | plt.close(fig)
70 |
71 | def visualize_data(data, data_type, out_file):
72 | '''
73 | Visualizes the data with regard to its type.
74 | :param data (tensor): batch of data
75 | :param data_type (string): data type (img, voxels or pointcloud)
76 | :param out_file (string): output file
77 | :return:
78 | '''
79 | if data_type == 'img':
80 | if data.dim() == 3:
81 | data = data.unsqueeze(0)
82 | save_image(data, out_file, nrow=4)
83 | elif data_type == 'voxels':
84 | visualize_voxels(data, out_file=out_file)
85 | elif data_type == 'pointcloud':
86 | visualize_pointcloud(data, out_file=out_file)
87 | elif data_type is None or data_type == 'idx':
88 | pass
89 | else:
90 | raise ValueError('Invalid data_type "%s"' % data_type)
--------------------------------------------------------------------------------
/out/samples/scene0001_00/verify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/out/samples/scene0001_00/verify.png
--------------------------------------------------------------------------------
/out/samples/scene0549_00/camera_center:
--------------------------------------------------------------------------------
1 | 0.000000000000000000e+00
2 | -3.000000000000000000e+00
3 | 3.000000000000000000e+00
4 |
--------------------------------------------------------------------------------
/out/samples/scene0549_00/gt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/out/samples/scene0549_00/gt.png
--------------------------------------------------------------------------------
/out/samples/scene0549_00/points.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/out/samples/scene0549_00/points.png
--------------------------------------------------------------------------------
/out/samples/scene0549_00/pred.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/out/samples/scene0549_00/pred.png
--------------------------------------------------------------------------------
/out/samples/scene0549_00/verify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GAP-LAB-CUHK-SZ/RfDNet/241d698bf5f2bd4fc076bc2dc18dfa9cc925c703/out/samples/scene0549_00/verify.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | absl-py==0.12.0
2 | cachetools==4.2.1
3 | certifi==2020.12.5
4 | chardet==4.0.0
5 | cycler==0.10.0
6 | Cython==0.29.22
7 | dataclasses @ file:///tmp/build/80754af9/dataclasses_1614363715916/work
8 | decorator==4.4.2
9 | google-auth==1.28.0
10 | google-auth-oauthlib==0.4.3
11 | grpcio==1.36.1
12 | idna==2.10
13 | imageio==2.9.0
14 | importlib-metadata==3.7.3
15 | kiwisolver==1.3.1
16 | llvmlite==0.36.0
17 | Markdown==3.3.4
18 | matplotlib==3.3.4
19 | mkl-fft==1.3.0
20 | mkl-random==1.1.1
21 | mkl-service==2.3.0
22 | networkx==2.5
23 | numba==0.53.0
24 | numpy @ file:///tmp/build/80754af9/numpy_and_numpy_base_1603487797006/work
25 | numpy-quaternion==2021.3.17.16.51.43
26 | oauthlib==3.1.0
27 | olefile==0.46
28 | pandas==1.1.5
29 | Pillow @ file:///tmp/build/80754af9/pillow_1615224027575/work
30 | plyfile==0.7.3
31 | pointnet2-ops @ file:///home/ynie/Project/RfDNet/external/pointnet2_ops_lib
32 | protobuf==3.15.6
33 | pyasn1==0.4.8
34 | pyasn1-modules==0.2.8
35 | PyMCubes==0.1.2
36 | pyparsing==2.4.7
37 | python-dateutil==2.8.1
38 | pytz==2021.1
39 | PyWavelets==1.1.1
40 | PyYAML==5.4.1
41 | requests==2.25.1
42 | requests-oauthlib==1.3.0
43 | rsa==4.7.2
44 | scikit-image==0.17.2
45 | scipy==1.5.4
46 | seaborn==0.11.1
47 | Shapely==1.7.1
48 | six @ file:///tmp/build/80754af9/six_1605205335545/work
49 | tensorboard==2.4.1
50 | tensorboard-plugin-wit==1.8.0
51 | tifffile==2020.9.3
52 | torch==1.7.1
53 | torchaudio==0.7.0a0+a853dff
54 | torchvision==0.8.2
55 | tqdm==4.59.0
56 | trimesh==3.9.9
57 | typing-extensions @ file:///home/ktietz/src/ci_mi/typing_extensions_1612808209620/work
58 | urllib3==1.26.4
59 | vtk==9.0.1
60 | Werkzeug==1.0.1
61 | zipp==3.4.1
62 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | try:
2 | from setuptools import setup
3 | except ImportError:
4 | from distutils.core import setup
5 | from distutils.extension import Extension
6 | from Cython.Build import cythonize
7 | from setuptools.command.build_ext import build_ext
8 | import numpy
9 | numpy_include_dir = numpy.get_include()
10 |
11 | # Extensions
12 | # triangle hash (efficient mesh intersection)
13 | triangle_hash_module = Extension(
14 | 'external.libmesh.triangle_hash',
15 | sources=[
16 | 'external/libmesh/triangle_hash.pyx'
17 | ],
18 | libraries=['m'], # Unix-like specific
19 | include_dirs=[numpy_include_dir]
20 | )
21 |
22 | # voxelization (efficient mesh voxelization)
23 | voxelize_module = Extension(
24 | 'external.libvoxelize.voxelize',
25 | sources=[
26 | 'external/libvoxelize/voxelize.pyx'
27 | ],
28 | libraries=['m'] # Unix-like specific
29 | )
30 |
31 | # pykdtree (kd tree)
32 | pykdtree = Extension(
33 | 'external.libkdtree.pykdtree.kdtree',
34 | sources=[
35 | 'external/libkdtree/pykdtree/kdtree.c',
36 | 'external/libkdtree/pykdtree/_kdtree_core.c'
37 | ],
38 | language='c',
39 | extra_compile_args=['-std=c99', '-O3', '-fopenmp'],
40 | extra_link_args=['-lgomp'],
41 | include_dirs=[numpy_include_dir]
42 | )
43 |
44 | # simplify (efficient mesh simplification)
45 | simplify_mesh_module = Extension(
46 | 'external.libsimplify.simplify_mesh',
47 | sources=[
48 | 'external/libsimplify/simplify_mesh.pyx'
49 | ],
50 | include_dirs=[numpy_include_dir]
51 | )
52 |
53 | # mise (efficient mesh extraction)
54 | mise_module = Extension(
55 | 'external.libmise.mise',
56 | sources=[
57 | 'external/libmise/mise.pyx'
58 | ],
59 | )
60 |
61 | # Gather all extension modules
62 | ext_modules = [
63 | pykdtree,
64 | triangle_hash_module,
65 | voxelize_module,
66 | simplify_mesh_module,
67 | mise_module
68 | ]
69 |
70 | def set_builtin(name, value):
71 | if isinstance(__builtins__, dict):
72 | __builtins__[name] = value
73 | else:
74 | setattr(__builtins__, name, value)
75 |
76 |
77 | class build_ext_subclass(build_ext):
78 | def build_extensions(self):
79 | comp = self.compiler.compiler_type
80 | if comp in ('unix', 'cygwin', 'mingw32'):
81 | # Check if build is with OpenMP
82 | extra_compile_args = ['-std=c99', '-O3', '-fopenmp']
83 | extra_link_args=['-lgomp']
84 | elif comp == 'msvc':
85 | extra_compile_args = ['/Ox']
86 | extra_link_args = []
87 | extra_compile_args.append('/openmp')
88 | else:
89 | # Add support for more compilers here
90 | raise ValueError('Compiler flags undefined for %s. Please modify setup.py and add compiler flags'
91 | % comp)
92 | self.extensions[0].extra_compile_args = extra_compile_args
93 | self.extensions[0].extra_link_args = extra_link_args
94 | build_ext.build_extensions(self)
95 |
96 | def finalize_options(self):
97 | '''
98 | In order to avoid premature import of numpy before it gets installed as a dependency
99 | get numpy include directories during the extensions building process
100 | http://stackoverflow.com/questions/19919905/how-to-bootstrap-numpy-installation-in-setup-py
101 | '''
102 | build_ext.finalize_options(self)
103 | # Prevent numpy from thinking it is still in its setup process:
104 | set_builtin('__NUMPY_SETUP__', False)
105 | import numpy
106 | self.include_dirs.append(numpy.get_include())
107 |
108 | setup(
109 | ext_modules=cythonize(ext_modules),
110 | cmdclass={
111 | 'build_ext': build_ext_subclass
112 | }
113 | )
114 |
--------------------------------------------------------------------------------
/test.py:
--------------------------------------------------------------------------------
1 | # Testing script.
2 | # author: ynie
3 | # date: Feb, 2020
4 | from net_utils.utils import load_device, load_model, load_tester, load_dataloader
5 | from net_utils.utils import CheckpointIO
6 | from test_epoch import test
7 | from configs.config_utils import mount_external_config
8 |
9 | def run(cfg):
10 | '''Begin to run network.'''
11 | checkpoint = CheckpointIO(cfg)
12 |
13 | '''Mount external config data'''
14 | cfg = mount_external_config(cfg)
15 |
16 | '''Load save path'''
17 | cfg.log_string('Data save path: %s' % (cfg.save_path))
18 |
19 | '''Load device'''
20 | cfg.log_string('Loading device settings.')
21 | device = load_device(cfg)
22 |
23 | '''Load data'''
24 | cfg.log_string('Loading dataset.')
25 | test_loader = load_dataloader(cfg, mode='test')
26 |
27 | '''Load net'''
28 | cfg.log_string('Loading model.')
29 | net = load_model(cfg, device=device)
30 | checkpoint.register_modules(net=net)
31 | cfg.log_string(net)
32 |
33 | '''Load existing checkpoint'''
34 | checkpoint.parse_checkpoint()
35 |
36 | '''Load tester'''
37 | cfg.log_string('Loading tester.')
38 | tester = load_tester(cfg=cfg, net=net, device=device)
39 |
40 | '''Start to test'''
41 | cfg.log_string('Start to test.')
42 | cfg.log_string('Total number of parameters in {0:s}: {1:d}.'.format(cfg.config['method'], sum(p.numel() for p in net.parameters())))
43 |
44 | test(cfg=cfg, tester=tester, test_loader=test_loader)
45 |
46 | cfg.write_config()
47 | cfg.log_string('Testing finished.')
48 |
49 |
50 |
--------------------------------------------------------------------------------
/test_epoch.py:
--------------------------------------------------------------------------------
1 | # Testing functions.
2 | # author: ynie
3 | # date: April, 2020
4 | from net_utils.utils import LossRecorder
5 | from time import time
6 | import torch
7 | from net_utils.ap_helper import APCalculator
8 | import numpy as np
9 |
10 | def test_func(cfg, tester, test_loader):
11 | '''
12 | test function.
13 | :param cfg: configuration file
14 | :param tester: specific tester for networks
15 | :param test_loader: dataloader for testing
16 | :return:
17 | '''
18 | mode = cfg.config['mode']
19 | batch_size = cfg.config[mode]['batch_size']
20 | loss_recorder = LossRecorder(batch_size)
21 | AP_IOU_THRESHOLDS = cfg.config[mode]['ap_iou_thresholds']
22 | evaluate_mesh_mAP = True if cfg.config[mode]['phase'] == 'completion' and cfg.config['generation'][
23 | 'generate_mesh'] and cfg.config[mode]['evaluate_mesh_mAP'] else False
24 | ap_calculator_list = [APCalculator(iou_thresh, cfg.dataset_config.class2type, evaluate_mesh_mAP) for iou_thresh in
25 | AP_IOU_THRESHOLDS]
26 | cfg.log_string('-'*100)
27 | for iter, data in enumerate(test_loader):
28 | loss, est_data = tester.test_step(data)
29 | eval_dict = est_data[4]
30 | for ap_calculator in ap_calculator_list:
31 | ap_calculator.step(eval_dict['batch_pred_map_cls'], eval_dict['batch_gt_map_cls'])
32 | # visualize intermediate results.
33 | if cfg.config['generation']['dump_results']:
34 | tester.visualize_step(mode, iter, data, est_data, eval_dict)
35 |
36 | loss_recorder.update_loss(loss)
37 |
38 | if ((iter + 1) % cfg.config['log']['print_step']) == 0:
39 | cfg.log_string('Process: Phase: %s. Epoch %d: %d/%d. Current loss: %s.' % (
40 | mode, 0, iter + 1, len(test_loader), str({key: np.mean(item) for key, item in loss.items()})))
41 |
42 | return loss_recorder.loss_recorder, ap_calculator_list
43 |
44 | def test(cfg, tester, test_loader):
45 | '''
46 | train epochs for network
47 | :param cfg: configuration file
48 | :param tester: specific tester for networks
49 | :param test_loader: dataloader for testing
50 | :return:
51 | '''
52 | cfg.log_string('-' * 100)
53 | # set mode
54 | mode = cfg.config['mode']
55 | tester.net.train(mode == 'train')
56 | start = time()
57 | test_loss_recoder, ap_calculator_list = test_func(cfg, tester, test_loader)
58 | cfg.log_string('Test time elapsed: (%f).' % (time()-start))
59 | for key, test_loss in test_loss_recoder.items():
60 | cfg.log_string('Test loss (%s): %f' % (key, test_loss.avg))
61 |
62 | # Evaluate average precision
63 | AP_IOU_THRESHOLDS = cfg.config[mode]['ap_iou_thresholds']
64 | for i, ap_calculator in enumerate(ap_calculator_list):
65 | cfg.log_string(('-'*10 + 'iou_thresh: %f' + '-'*10) % (AP_IOU_THRESHOLDS[i]))
66 | metrics_dict = ap_calculator.compute_metrics()
67 | for key in metrics_dict:
68 | cfg.log_string('eval %s: %f' % (key, metrics_dict[key]))
--------------------------------------------------------------------------------
/train.py:
--------------------------------------------------------------------------------
1 | # Training script
2 | # author: ynie
3 | # date: Feb, 2020
4 | from models.optimizers import load_optimizer, load_scheduler, load_bnm_scheduler
5 | from net_utils.utils import load_device, load_model, load_trainer, load_dataloader
6 | from net_utils.utils import CheckpointIO
7 | from train_epoch import train
8 | from configs.config_utils import mount_external_config
9 |
10 | def run(cfg):
11 | '''Begin to run network.'''
12 | checkpoint = CheckpointIO(cfg)
13 |
14 | '''Mount external config data'''
15 | cfg = mount_external_config(cfg)
16 |
17 | '''Load save path'''
18 | cfg.log_string('Data save path: %s' % (cfg.save_path))
19 |
20 | '''Load device'''
21 | cfg.log_string('Loading device settings.')
22 | device = load_device(cfg)
23 |
24 | '''Load data'''
25 | cfg.log_string('Loading dataset.')
26 | train_loader = load_dataloader(cfg, mode='train')
27 | val_loader = load_dataloader(cfg, mode='val')
28 |
29 | '''Load net'''
30 | cfg.log_string('Loading model.')
31 | net = load_model(cfg, device=device)
32 | checkpoint.register_modules(net=net)
33 | cfg.log_string(net)
34 |
35 | '''Load optimizer'''
36 | cfg.log_string('Loading optimizer.')
37 | optimizer = load_optimizer(config=cfg.config, net=net)
38 | checkpoint.register_modules(optimizer=optimizer)
39 |
40 | '''Load scheduler'''
41 | cfg.log_string('Loading optimizer scheduler.')
42 | scheduler = load_scheduler(config=cfg.config, optimizer=optimizer)
43 | checkpoint.register_modules(scheduler=scheduler)
44 |
45 | '''Check existing checkpoint (resume or finetune)'''
46 | checkpoint.parse_checkpoint()
47 |
48 | '''BN momentum scheduler'''
49 | bnm_scheduler = load_bnm_scheduler(cfg=cfg, net=net, start_epoch=scheduler.last_epoch)
50 |
51 | '''Load trainer'''
52 | cfg.log_string('Loading trainer.')
53 | trainer = load_trainer(cfg=cfg, net=net, optimizer=optimizer, device=device)
54 |
55 | '''Start to train'''
56 | cfg.log_string('Start to train.')
57 | cfg.log_string('Total number of parameters in {0:s}: {1:d}.'.format(cfg.config['method'], sum(p.numel() for p in net.parameters())))
58 |
59 | train(cfg=cfg, trainer=trainer, scheduler=scheduler, bnm_scheduler=bnm_scheduler, checkpoint=checkpoint, train_loader=train_loader, val_loader=val_loader)
60 |
61 | cfg.log_string('Training finished.')
--------------------------------------------------------------------------------
/train_epoch.py:
--------------------------------------------------------------------------------
1 | # Training functions.
2 | # author: ynie
3 | # date: Feb, 2020
4 |
5 | from net_utils.utils import LossRecorder, LogBoard
6 | from time import time
7 | log_board = LogBoard()
8 |
9 | def train_epoch(cfg, epoch, trainer, dataloaders):
10 | '''
11 | train by epoch
12 | :param cfg: configuration file
13 | :param epoch: epoch id.
14 | :param trainer: specific trainer for networks
15 | :param dataloaders: dataloader for training and validation
16 | :return:
17 | '''
18 | for phase in ['train', 'val']:
19 | dataloader = dataloaders[phase]
20 | batch_size = cfg.config[phase]['batch_size']
21 | loss_recorder = LossRecorder(batch_size)
22 | # set mode
23 | trainer.net.train(phase == 'train')
24 | # set subnet mode
25 | trainer.net.module.set_mode()
26 | cfg.log_string('-' * 100)
27 | cfg.log_string('Switch Phase to %s.' % (phase))
28 | cfg.log_string('-'*100)
29 | for iter, data in enumerate(dataloader):
30 | if phase == 'train':
31 | loss = trainer.train_step(data)
32 | else:
33 | loss = trainer.eval_step(data)
34 |
35 | # visualize intermediate results.
36 | if ((iter + 1) % cfg.config['log']['vis_step']) == 0:
37 | trainer.visualize_step(epoch, phase, iter, data)
38 |
39 | loss_recorder.update_loss(loss)
40 |
41 | if ((iter + 1) % cfg.config['log']['print_step']) == 0:
42 | cfg.log_string('Process: Phase: %s. Epoch %d: %d/%d. Current loss: %s.' % (phase, epoch, iter + 1, len(dataloader), str(loss)))
43 | log_board.update(loss, cfg.config['log']['print_step'], phase)
44 |
45 | cfg.log_string('=' * 100)
46 | for loss_name, loss_value in loss_recorder.loss_recorder.items():
47 | cfg.log_string('Currently the last %s loss (%s) is: %f' % (phase, loss_name, loss_value.avg))
48 | cfg.log_string('=' * 100)
49 |
50 | return loss_recorder.loss_recorder
51 |
52 | def train(cfg, trainer, scheduler, bnm_scheduler, checkpoint, train_loader, val_loader):
53 | '''
54 | train epochs for network
55 | :param cfg: configuration file
56 | :param scheduler: scheduler for optimizer
57 | :param bnm_scheduler: scheduler for batch normalization module
58 | :param trainer: specific trainer for networks
59 | :param checkpoint: network weights.
60 | :param train_loader: dataloader for training
61 | :param val_loader: dataloader for validation
62 | :return:
63 | '''
64 | start_epoch = scheduler.last_epoch
65 | total_epochs = cfg.config['train']['epochs']
66 | min_eval_loss = checkpoint.get('min_loss')
67 |
68 | dataloaders = {'train': train_loader, 'val': val_loader}
69 |
70 | for epoch in range(start_epoch, total_epochs):
71 | cfg.log_string('-' * 100)
72 | cfg.log_string('Epoch (%d/%s):' % (epoch + 1, total_epochs))
73 | trainer.show_lr()
74 | bnm_scheduler.show_momentum()
75 | start = time()
76 | eval_loss_recorder = train_epoch(cfg, epoch + 1, trainer, dataloaders)
77 | eval_loss = trainer.eval_loss_parser(eval_loss_recorder)
78 | scheduler.step(eval_loss)
79 | bnm_scheduler.step()
80 | cfg.log_string('Epoch (%d/%s) Time elapsed: (%f).' % (epoch + 1, total_epochs, time()-start))
81 |
82 | # save checkpoint
83 | checkpoint.register_modules(epoch=epoch, min_loss=eval_loss)
84 | checkpoint.save('last')
85 | cfg.log_string('Saved the latest checkpoint.')
86 | if epoch==0 or eval_loss
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/utils/shapenet/tools.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | def pc_from_dep(depth_maps, cam_Ks, cam_Rs, znf, store_camera=False):
4 | '''
5 | get point cloud from depth maps
6 | :param depth_maps: depth map list
7 | :param cam_Ks: corresponding camera intrinsics
8 | :param cam_RTs: corresponding camera rotations and translations
9 | :param znf: [nearest camera distance, furthest distance]
10 | :param store_camera: if calculate camera position and orientations.
11 | :return: aligned point clouds in the canonical system with color intensities.
12 | '''
13 | point_list_canonical = []
14 | camera_positions = []
15 |
16 | for depth_map, cam_K, cam_R in zip(depth_maps, cam_Ks, cam_Rs):
17 | cam_RT = np.hstack([cam_R, np.array([[0, 0, 1]]).T])
18 |
19 | u, v = np.meshgrid(range(depth_map.shape[1]), range(depth_map.shape[0]))
20 | u = u.reshape([1, -1])[0]
21 | v = v.reshape([1, -1])[0]
22 |
23 | z = depth_map[v, u]
24 |
25 | # remove infinitive pixels
26 | non_inf_indices = np.argwhere(z < znf[1]).T[0]
27 |
28 | z = z[non_inf_indices]
29 | u = u[non_inf_indices]
30 | v = v[non_inf_indices]
31 |
32 | # calculate coordinates
33 | x = (u - cam_K[0][2]) * z / cam_K[0][0]
34 | y = (v - cam_K[1][2]) * z / cam_K[1][1]
35 |
36 | point_cam = np.vstack([x, y, z]).T
37 |
38 | point_canonical = (point_cam - cam_RT[:, -1]).dot(cam_RT[:, :-1])
39 |
40 | if store_camera:
41 | cam_pos = - cam_RT[:, -1].dot(cam_RT[:, :-1])
42 | focal_point = ([0, 0, 1] - cam_RT[:, -1]).dot(cam_RT[:, :-1])
43 | up = np.array([0, -1, 0]).dot(cam_RT[:, :-1])
44 | cam_pos = {'pos': cam_pos, 'fp': focal_point, 'up': up}
45 | else:
46 | cam_pos = {}
47 |
48 | point_list_canonical.append(point_canonical)
49 | camera_positions.append(cam_pos)
50 |
51 | output = {'pc': point_list_canonical}
52 |
53 | if store_camera:
54 | output['cam'] = camera_positions
55 |
56 | return output
--------------------------------------------------------------------------------