├── latent_3d_points ├── __init__.py ├── python_plyfile │ └── __init__.py ├── readme.txt ├── structural_losses │ ├── __init__.py │ ├── tf_nndistance_compile.sh │ ├── tf_approxmatch_compile.sh │ ├── tf_nndistance.py │ ├── tf_approxmatch.py │ ├── tf_nndistance_g.cu │ ├── approxmatch.cu │ ├── approxmatch.cpp │ └── tf_approxmatch_g.cu ├── tf_utils.py ├── LICENSE ├── neural_net.py └── gan.py ├── .gitignore ├── pointnet_plusplus ├── tf_ops │ ├── sampling │ │ ├── .gitignore │ │ ├── tf_sampling_compile.sh │ │ ├── tf_sampling.py │ │ ├── tf_sampling_g.cu │ │ └── tf_sampling.cpp │ ├── grouping │ │ ├── .gitignore │ │ ├── compile.sh │ │ ├── tf_grouping_compile.sh │ │ ├── test_knn.py │ │ ├── tf_grouping_op_test.py │ │ ├── selection_sort.cu │ │ ├── selection_sort_const.cu │ │ ├── selection_sort.cpp │ │ ├── query_ball_point.cpp │ │ ├── tf_grouping.py │ │ ├── query_ball_point_block.cu │ │ ├── query_ball_point.cu │ │ ├── query_ball_point_grid.cu │ │ └── tf_grouping_g.cu │ └── 3d_interpolation │ │ ├── tf_interpolate_compile.sh │ │ ├── tf_interpolate_op_test.py │ │ ├── visu_interpolation.py │ │ ├── tf_interpolate.py │ │ └── interpolate.cpp ├── readme.txt ├── LICENSE └── utils │ └── provider.py ├── CMD_sh ├── jointSynthesis_test_onRealOutput_Mug.sh ├── jointSynthesis_test_onRealOutput_chair.sh ├── jointSynthesis_test_onRealOutput_airplane.sh ├── partAlign_train_chair.sh ├── partAlign_train_Mug.sh ├── partAlign_train_airplane.sh ├── jointSynthesis_train_Mug.sh ├── jointSynthesis_train_airplane.sh ├── jointSynthesis_train_chair.sh ├── partAE_train_mug12.sh ├── partAE_train_airplane1234.sh └── partAE_train_chair1234.sh ├── LICENSE ├── latent_3d_points_tf_utils.py ├── partAE.py ├── partAlign.py ├── data-preprocess ├── README.MD ├── 3_merge_subset.py ├── 4_sort_points.py └── 1_extract_parts2048_ply_erodedX_withnormal.py ├── README.md ├── jointSynthesis.py ├── ops.py ├── poisson-blending ├── README.md ├── blend │ └── poisson_blend.py └── prepare │ ├── 03797390_vox.txt │ └── get_part_mesh.py ├── latent_3d_points_decoder.py ├── pointnet_plusplus_encoder_1B.py └── pointnet_plusplus_encoder.py /latent_3d_points/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.pyc 4 | *.bak -------------------------------------------------------------------------------- /latent_3d_points/python_plyfile/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/sampling/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | -------------------------------------------------------------------------------- /pointnet_plusplus/readme.txt: -------------------------------------------------------------------------------- 1 | Note: 2 | the code in this folder was downloaded in *September 2017* 3 | from https://github.com/charlesq34/pointnet2 4 | 5 | later version was not tested 6 | -------------------------------------------------------------------------------- /latent_3d_points/readme.txt: -------------------------------------------------------------------------------- 1 | Note: 2 | the code in this folder was downloaded in *September 2018* 3 | from https://github.com/optas/latent_3d_points 4 | 5 | later version was not tested 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /latent_3d_points/structural_losses/__init__.py: -------------------------------------------------------------------------------- 1 | import traceback 2 | 3 | try: 4 | from .tf_approxmatch import approx_match, match_cost 5 | except Exception as e: 6 | traceback.print_exc() 7 | 8 | print('External Losses (Chamfer-EMD) were not loaded.') 9 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | query_ball_point 3 | query_ball_point_block 4 | query_ball_point_cuda 5 | query_ball_point_grid 6 | tf_grouping_g.cu.o 7 | tf_grouping_so.so 8 | selection_sort 9 | selection_sort_cuda 10 | selection_sort_const_cuda 11 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/3d_interpolation/tf_interpolate_compile.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())') 4 | TF_LIB=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_lib())') 5 | 6 | g++ -std=c++11 tf_interpolate.cpp -o tf_interpolate_so.so -shared -fPIC -I$TF_INC -I$TF_INC/external/nsync/public -L$TF_LIB -ltensorflow_framework -I /usr/local/cuda-10.1/include -lcudart -L /usr/local/cuda-10.1/lib64/ -O2 -D_GLIBCXX_USE_CXX11_ABI=0 7 | 8 | 9 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/compile.sh: -------------------------------------------------------------------------------- 1 | g++ query_ball_point.cpp -o query_ball_point 2 | /usr/local/cuda-10.1/bin/nvcc query_ball_point.cu -o query_ball_point_cuda 3 | /usr/local/cuda-10.1/bin/nvcc query_ball_point_block.cu -o query_ball_point_block 4 | /usr/local/cuda-10.1/bin/nvcc query_ball_point_grid.cu -o query_ball_point_grid 5 | #/usr/local/cuda-10.1/bin/nvcc query_ball_point_grid_count.cu -o query_ball_point_grid_count 6 | g++ -Wall selection_sort.cpp -o selection_sort 7 | /usr/local/cuda-10.1/bin/nvcc selection_sort.cu -o selection_sort_cuda 8 | -------------------------------------------------------------------------------- /latent_3d_points/structural_losses/tf_nndistance_compile.sh: -------------------------------------------------------------------------------- 1 | 2 | TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())') 3 | TF_LIB=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_lib())') 4 | 5 | /usr/local/cuda-10.1/bin/nvcc -std=c++11 -c -o tf_nndistance_g.cu.o tf_nndistance_g.cu -I $TF_INC -L$TF_LIB -ltensorflow_framework -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC -O2 && g++ -std=c++11 tf_nndistance.cpp tf_nndistance_g.cu.o -o tf_nndistance_so.so -shared -fPIC -I $TF_INC -L$TF_LIB -ltensorflow_framework -L /usr/local/cuda-10.1/lib64 -O2 -D_GLIBCXX_USE_CXX11_ABI=0 6 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/tf_grouping_compile.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | 4 | 5 | TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())') 6 | TF_LIB=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_lib())') 7 | /usr/local/cuda-10.1/bin/nvcc tf_grouping_g.cu -o tf_grouping_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC 8 | g++ -std=c++11 tf_grouping.cpp tf_grouping_g.cu.o -o tf_grouping_so.so -shared -fPIC -I$TF_INC -I$TF_INC/external/nsync/public -L$TF_LIB -ltensorflow_framework -I /usr/local/cuda-10.1/include -lcudart -L /usr/local/cuda-10.1/lib64/ -O2 -D_GLIBCXX_USE_CXX11_ABI=0 9 | 10 | -------------------------------------------------------------------------------- /CMD_sh/jointSynthesis_test_onRealOutput_Mug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | DataDir="./03797390_Mug/03797390_sampling_erode0.05_256_ptsSorted" 8 | wordir="03797390_Mug" 9 | gpu_id="0" 10 | dataset="03797390_vox" 11 | 12 | num_of_parts="2" 13 | 14 | folderDiff="03797390_Mug/test_res_partAlign_Epoch200_diffshapes" 15 | 16 | echo $DataDir 17 | echo $gpu_id 18 | echo $wordir 19 | echo $num_of_parts 20 | 21 | 22 | python -u jointSynthesis.py --epoch 240 --num_of_parts $num_of_parts --gpu $gpu_id --data_dir $DataDir --dataset $dataset --test_input_dir $folderDiff --testStartID 0 --testEndID 1000 23 | 24 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/sampling/tf_sampling_compile.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | 4 | TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())') 5 | TF_LIB=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_lib())') 6 | 7 | /usr/local/cuda-10.1/bin/nvcc tf_sampling_g.cu -o tf_sampling_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC 8 | g++ -std=c++11 tf_sampling.cpp tf_sampling_g.cu.o -o tf_sampling_so.so -shared -fPIC -I$TF_INC -I$TF_INC/external/nsync/public -L$TF_LIB -ltensorflow_framework -I /usr/local/cuda-10.1/include -lcudart -L /usr/local/cuda-10.1/lib64/ -O2 -D_GLIBCXX_USE_CXX11_ABI=0 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /latent_3d_points/structural_losses/tf_approxmatch_compile.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | echo 'nvcc' 4 | /usr/local/cuda-10.1/bin/nvcc tf_approxmatch_g.cu -o tf_approxmatch_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC 5 | 6 | 7 | 8 | TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())') 9 | TF_LIB=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_lib())') 10 | 11 | echo 'g++' 12 | g++ -std=c++11 tf_approxmatch.cpp tf_approxmatch_g.cu.o -o tf_approxmatch_so.so -shared -fPIC -I $TF_INC -I /usr/local/cuda-10.1/include -L /usr/local/cuda-10.1/lib64/ -L$TF_LIB -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0 13 | 14 | -------------------------------------------------------------------------------- /CMD_sh/jointSynthesis_test_onRealOutput_chair.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | 8 | 9 | 10 | DataDir="./03001627_Chair/03001627_sampling_erode0.05_256_ptsSorted" 11 | wordir="03001627_Chair" 12 | gpu_id="0" 13 | dataset="03001627_vox" 14 | num_of_parts="4" 15 | 16 | folderDiff="03001627_Chair/test_res_partAlign_Epoch200_diffshapes" 17 | 18 | echo $DataDir 19 | echo $gpu_id 20 | echo $wordir 21 | echo $diffShape 22 | echo $num_of_parts 23 | 24 | 25 | python -u jointSynthesis.py --epoch 160 --num_of_parts $num_of_parts --gpu $gpu_id --data_dir $DataDir --dataset $dataset --test_input_dir $folderDiff --testStartID 0 --testEndID 1000 26 | 27 | 28 | -------------------------------------------------------------------------------- /CMD_sh/jointSynthesis_test_onRealOutput_airplane.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | 8 | 9 | DataDir="./02691156_Airplane/02691156_sampling_erode0.025_256_ptsSorted" 10 | wordir="02691156_Airplane" 11 | gpu_id="0" 12 | dataset="02691156_vox" 13 | num_of_parts="4" 14 | 15 | folderDiff="02691156_Airplane/test_res_partAlign_Epoch200_diffshapes" 16 | 17 | echo $DataDir 18 | echo $gpu_id 19 | echo $wordir 20 | echo $diffShape 21 | echo $num_of_parts 22 | 23 | 24 | 25 | 26 | python -u jointSynthesis.py --epoch 160 --num_of_parts $num_of_parts --gpu $gpu_id --data_dir $DataDir --dataset $dataset --test_input_dir $folderDiff --testStartID 0 --testEndID 1000 27 | 28 | -------------------------------------------------------------------------------- /CMD_sh/partAlign_train_chair.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | DataDir="./03001627_Chair/03001627_sampling_erode0.05_256_ptsSorted" 7 | wordir="03001627_Chair" 8 | gpu_id="0" 9 | dataset="03001627_vox" 10 | 11 | diffShape="0" 12 | num_of_parts="4" 13 | 14 | erodeRadius="0.05" 15 | 16 | echo $DataDir 17 | echo $gpu_id 18 | echo $dataset 19 | echo $erodeRadius 20 | 21 | 22 | python -u partAlign.py --train --epoch 200 --num_of_parts $num_of_parts --gpu $gpu_id --reWei 0 --data_dir $DataDir --dataset $dataset --learning_rate 0.001 --shapeBatchSize 8 23 | 24 | 25 | if [ $diffShape -eq "0" ]; then 26 | echo "diffShape is 0" 27 | else 28 | echo "diffShape is not 0" 29 | fi 30 | 31 | 32 | python -u partAlign.py --epoch 200 --num_of_parts $num_of_parts --gpu $gpu_id --reWei 0 --data_dir $DataDir --dataset $dataset --diffShape $diffShape 33 | -------------------------------------------------------------------------------- /CMD_sh/partAlign_train_Mug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | DataDir="./03797390_Mug/03797390_sampling_erode0.05_256_ptsSorted" 7 | wordir="03797390_Mug" 8 | gpu_id="0" 9 | dataset="03797390_vox" 10 | 11 | diffShape="0" 12 | num_of_parts="2" 13 | 14 | erodeRadius="0.05" 15 | 16 | echo $DataDir 17 | echo $gpu_id 18 | echo $dataset 19 | echo $erodeRadius 20 | 21 | 22 | python -u partAlign.py --train --epoch 200 --num_of_parts $num_of_parts --gpu $gpu_id --reWei 0 --data_dir $DataDir --dataset $dataset --learning_rate 0.001 --shapeBatchSize 8 23 | 24 | 25 | if [ $diffShape -eq "0" ]; then 26 | echo "diffShape is 0" 27 | else 28 | echo "diffShape is not 0" 29 | fi 30 | 31 | 32 | python -u partAlign.py --epoch 200 --num_of_parts $num_of_parts --gpu $gpu_id --reWei 0 --data_dir $DataDir --dataset $dataset --diffShape $diffShape 33 | 34 | 35 | -------------------------------------------------------------------------------- /CMD_sh/partAlign_train_airplane.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | DataDir="./02691156_Airplane/02691156_sampling_erode0.025_256_ptsSorted" 7 | wordir="02691156_Airplane" 8 | gpu_id="0" 9 | dataset="02691156_vox" 10 | 11 | diffShape="0" 12 | num_of_parts="4" 13 | 14 | erodeRadius="0.025" 15 | 16 | echo $DataDir 17 | echo $gpu_id 18 | echo $dataset 19 | echo $erodeRadius 20 | 21 | 22 | python -u partAlign.py --train --epoch 200 --num_of_parts $num_of_parts --gpu $gpu_id --reWei 0 --data_dir $DataDir --dataset $dataset --learning_rate 0.001 --shapeBatchSize 8 23 | 24 | 25 | if [ $diffShape -eq "0" ]; then 26 | echo "diffShape is 0" 27 | else 28 | echo "diffShape is not 0" 29 | fi 30 | 31 | 32 | python -u partAlign.py --epoch 200 --num_of_parts $num_of_parts --gpu $gpu_id --reWei 0 --data_dir $DataDir --dataset $dataset --diffShape $diffShape 33 | 34 | 35 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/3d_interpolation/tf_interpolate_op_test.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | from tf_interpolate import three_nn, three_interpolate 4 | 5 | class GroupPointTest(tf.test.TestCase): 6 | def test(self): 7 | pass 8 | 9 | def test_grad(self): 10 | with self.test_session(): 11 | points = tf.constant(np.random.random((1,8,16)).astype('float32')) 12 | print(points) 13 | xyz1 = tf.constant(np.random.random((1,128,3)).astype('float32')) 14 | xyz2 = tf.constant(np.random.random((1,8,3)).astype('float32')) 15 | dist, idx = three_nn(xyz1, xyz2) 16 | weight = tf.ones_like(dist)/3.0 17 | interpolated_points = three_interpolate(points, idx, weight) 18 | print(interpolated_points) 19 | err = tf.test.compute_gradient_error(points, (1,8,16), interpolated_points, (1,128,16)) 20 | print(err) 21 | self.assertLess(err, 1e-4) 22 | 23 | if __name__=='__main__': 24 | tf.test.main() 25 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/test_knn.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | 4 | np.random.seed(0) 5 | 6 | 7 | a_val = np.random.random((2,5,3)) 8 | b_val = np.random.random((2,2,3)) 9 | for b in range(2): 10 | print('--- ', b) 11 | t1 = a_val[b,:,:] 12 | t2 = b_val[b,:,:] 13 | for i in range(2): #npoint in b 14 | print('-- point b: ', i) 15 | for j in range(5): # npoint in a 16 | d = np.sum((t2[i,:]-t1[j,:])**2) 17 | print(d) 18 | 19 | 20 | 21 | a = tf.constant(a_val) 22 | b = tf.constant(b_val) 23 | print(a.get_shape()) 24 | k = 3 25 | 26 | a = tf.tile(tf.reshape(a, (2,1,5,3)), [1,2,1,1]) 27 | b = tf.tile(tf.reshape(b, (2,2,1,3)), [1,1,5,1]) 28 | 29 | dist = -tf.reduce_sum((a-b)**2, -1) 30 | print(dist) 31 | 32 | val, idx = tf.nn.top_k(dist, k=k) 33 | print(val, idx) 34 | sess = tf.Session() 35 | print(sess.run(a)) 36 | print(sess.run(b)) 37 | print(sess.run(dist)) 38 | print(sess.run(val)) 39 | print(sess.run(idx)) 40 | print(sess.run(idx).shape) 41 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/tf_grouping_op_test.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | from tf_grouping import query_ball_point, group_point 4 | 5 | class GroupPointTest(tf.test.TestCase): 6 | def test(self): 7 | pass 8 | 9 | def test_grad(self): 10 | with tf.device('/gpu:0'): 11 | points = tf.constant(np.random.random((1,128,16)).astype('float32')) 12 | print(points) 13 | xyz1 = tf.constant(np.random.random((1,128,3)).astype('float32')) 14 | xyz2 = tf.constant(np.random.random((1,8,3)).astype('float32')) 15 | radius = 0.3 16 | nsample = 32 17 | idx, pts_cnt = query_ball_point(radius, nsample, xyz1, xyz2) 18 | grouped_points = group_point(points, idx) 19 | print(grouped_points) 20 | 21 | with self.test_session(): 22 | print("---- Going to compute gradient error") 23 | err = tf.test.compute_gradient_error(points, (1,128,16), grouped_points, (1,8,32,16)) 24 | print(err) 25 | self.assertLess(err, 1e-4) 26 | 27 | if __name__=='__main__': 28 | tf.test.main() 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kangxue Yin 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 | -------------------------------------------------------------------------------- /latent_3d_points/tf_utils.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on November 26, 2017 3 | 4 | @author: optas 5 | ''' 6 | 7 | import tensorflow as tf 8 | import numpy as np 9 | 10 | 11 | def expand_scope_by_name(scope, name): 12 | """ expand tf scope by given name. 13 | """ 14 | 15 | if isinstance(scope, str): 16 | scope += '/' + name 17 | return scope 18 | 19 | if scope is not None: 20 | return scope.name + '/' + name 21 | else: 22 | return scope 23 | 24 | 25 | def replicate_parameter_for_all_layers(parameter, n_layers): 26 | if parameter is not None and len(parameter) != n_layers: 27 | if len(parameter) != 1: 28 | raise ValueError() 29 | parameter = np.array(parameter) 30 | parameter = parameter.repeat(n_layers).tolist() 31 | return parameter 32 | 33 | 34 | def reset_tf_graph(): 35 | ''' Reset's all variables of default-tf graph. Useful for jupyter. 36 | ''' 37 | if 'sess' in globals() and sess: 38 | sess.close() 39 | tf.reset_default_graph() 40 | 41 | 42 | def leaky_relu(alpha): 43 | if not (alpha < 1 and alpha > 0): 44 | raise ValueError() 45 | 46 | return lambda x: tf.maximum(alpha * x, x) 47 | 48 | 49 | def safe_log(x, eps=1e-12): 50 | return tf.log(tf.maximum(x, eps)) -------------------------------------------------------------------------------- /latent_3d_points_tf_utils.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on November 26, 2017 3 | 4 | @author: optas 5 | ''' 6 | 7 | import tensorflow as tf 8 | import numpy as np 9 | 10 | 11 | def expand_scope_by_name(scope, name): 12 | """ expand tf scope by given name. 13 | """ 14 | 15 | if isinstance(scope, str): 16 | scope += '/' + name 17 | return scope 18 | 19 | if scope is not None: 20 | return scope.name + '/' + name 21 | else: 22 | return scope 23 | 24 | 25 | def replicate_parameter_for_all_layers(parameter, n_layers): 26 | if parameter is not None and len(parameter) != n_layers: 27 | if len(parameter) != 1: 28 | raise ValueError() 29 | parameter = np.array(parameter) 30 | parameter = parameter.repeat(n_layers).tolist() 31 | return parameter 32 | 33 | 34 | def reset_tf_graph(): 35 | ''' Reset's all variables of default-tf graph. Useful for jupyter. 36 | ''' 37 | if 'sess' in globals() and sess: 38 | sess.close() 39 | tf.reset_default_graph() 40 | 41 | 42 | def leaky_relu(alpha): 43 | if not (alpha < 1 and alpha > 0): 44 | raise ValueError() 45 | 46 | return lambda x: tf.maximum(alpha * x, x) 47 | 48 | 49 | def safe_log(x, eps=1e-12): 50 | return tf.log(tf.maximum(x, eps)) -------------------------------------------------------------------------------- /latent_3d_points/LICENSE: -------------------------------------------------------------------------------- 1 | Learning Representations And Generative Models For 3D Point Clouds 2 | 3 | Copyright (c) 2017, Geometric Computation Group of Stanford University 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2017 Panos Achlioptas 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /pointnet_plusplus/LICENSE: -------------------------------------------------------------------------------- 1 | PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space. 2 | 3 | Copyright (c) 2017, Geometric Computation Group of Stanford University 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2017 Charles R. Qi 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /CMD_sh/jointSynthesis_train_Mug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | DataDir="./03797390_Mug/03797390_sampling_erode0.05_256_ptsSorted" 8 | gpu_id="0" 9 | dataset="03797390_vox" 10 | num_of_parts="2" 11 | 12 | 13 | echo $DataDir 14 | echo $gpu_id 15 | echo $dataset 16 | echo $num_of_parts 17 | 18 | 19 | 20 | python -u jointSynthesis.py --train --epoch 20 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 2048 21 | python -u jointSynthesis.py --train --epoch 40 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 4096 22 | python -u jointSynthesis.py --train --epoch 60 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 8192 23 | python -u jointSynthesis.py --train --epoch 80 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 16384 24 | python -u jointSynthesis.py --train --epoch 240 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 16384 25 | 26 | python -u jointSynthesis.py --epoch 240 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --outputHdf5 1 --FTSteps 0 27 | 28 | 29 | -------------------------------------------------------------------------------- /CMD_sh/jointSynthesis_train_airplane.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | DataDir="./02691156_Airplane/02691156_sampling_erode0.025_256_ptsSorted" 8 | gpu_id="0" 9 | dataset="02691156_vox" 10 | num_of_parts="4" 11 | 12 | 13 | echo $DataDir 14 | echo $gpu_id 15 | echo $dataset 16 | echo $num_of_parts 17 | 18 | 19 | 20 | python -u jointSynthesis.py --train --epoch 20 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 2048 21 | python -u jointSynthesis.py --train --epoch 40 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 4096 22 | python -u jointSynthesis.py --train --epoch 60 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 8192 23 | python -u jointSynthesis.py --train --epoch 80 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 16384 24 | python -u jointSynthesis.py --train --epoch 160 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 16384 25 | 26 | python -u jointSynthesis.py --epoch 160 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --outputHdf5 1 --FTSteps 0 27 | 28 | -------------------------------------------------------------------------------- /CMD_sh/jointSynthesis_train_chair.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | DataDir="./03001627_Chair/03001627_sampling_erode0.05_256_ptsSorted" 8 | gpu_id="0" 9 | dataset="03001627_vox" 10 | num_of_parts="4" 11 | 12 | 13 | echo $DataDir 14 | echo $gpu_id 15 | echo $dataset 16 | echo $num_of_parts 17 | 18 | 19 | 20 | 21 | python -u jointSynthesis.py --train --epoch 20 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 2048 22 | python -u jointSynthesis.py --train --epoch 40 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 4096 23 | python -u jointSynthesis.py --train --epoch 60 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 8192 24 | python -u jointSynthesis.py --train --epoch 80 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 16384 25 | python -u jointSynthesis.py --train --epoch 160 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --learning_rate 0.0001 --ptsBatchSize 16384 26 | 27 | python -u jointSynthesis.py --epoch 160 --num_of_parts $num_of_parts --gpu $gpu_id -data_dir $DataDir --dataset $dataset --outputHdf5 1 --FTSteps 0 28 | 29 | -------------------------------------------------------------------------------- /latent_3d_points/neural_net.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on August 28, 2017 3 | 4 | @author: optas 5 | ''' 6 | 7 | import os.path as osp 8 | import tensorflow as tf 9 | 10 | MODEL_SAVER_ID = 'models.ckpt' 11 | 12 | 13 | class Neural_Net(object): 14 | 15 | def __init__(self, name, graph): 16 | if graph is None: 17 | graph = tf.get_default_graph() 18 | 19 | self.graph = graph 20 | self.name = name 21 | 22 | with tf.variable_scope(name): 23 | with tf.device('/cpu:0'): 24 | self.epoch = tf.get_variable('epoch', [], initializer=tf.constant_initializer(0), trainable=False) 25 | self.increment_epoch = self.epoch.assign_add(tf.constant(1.0)) 26 | 27 | self.no_op = tf.no_op() 28 | 29 | def is_training(self): 30 | is_training_op = self.graph.get_collection('is_training') 31 | return self.sess.run(is_training_op)[0] 32 | 33 | def restore_model(self, model_path, epoch, verbose=False): 34 | '''Restore all the variables of a saved model. 35 | ''' 36 | self.saver.restore(self.sess, osp.join(model_path, MODEL_SAVER_ID + '-' + str(int(epoch)))) 37 | 38 | if self.epoch.eval(session=self.sess) != epoch: 39 | warnings.warn('Loaded model\'s epoch doesn\'t match the requested one.') 40 | else: 41 | if verbose: 42 | print('Model restored in epoch {0}.'.format(epoch)) 43 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/3d_interpolation/visu_interpolation.py: -------------------------------------------------------------------------------- 1 | ''' Visualize part segmentation ''' 2 | import os 3 | import sys 4 | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 | sys.path.append('/home/rqi/Projects/toolkits/visualization') 6 | from show3d_balls import showpoints 7 | import numpy as np 8 | from tf_interpolate import three_nn, three_interpolate 9 | import tensorflow as tf 10 | 11 | 12 | pts2 = np.array([[0,0,1],[1,0,0],[0,1,0],[1,1,0]]).astype('float32') 13 | xyz1 = np.random.random((100,3)).astype('float32') 14 | xyz2 = np.array([[0,0,0],[1,0,0],[0,1,0],[1,1,1]]).astype('float32') 15 | 16 | def fun(xyz1,xyz2,pts2): 17 | with tf.device('/cpu:0'): 18 | points = tf.constant(np.expand_dims(pts2,0)) 19 | xyz1 = tf.constant(np.expand_dims(xyz1,0)) 20 | xyz2 = tf.constant(np.expand_dims(xyz2,0)) 21 | dist, idx = three_nn(xyz1, xyz2) 22 | #weight = tf.ones_like(dist)/3.0 23 | dist = tf.maximum(dist, 1e-10) 24 | norm = tf.reduce_sum((1.0/dist),axis=2,keep_dims=True) 25 | norm = tf.tile(norm, [1,1,3]) 26 | print(norm) 27 | weight = (1.0/dist) / norm 28 | interpolated_points = three_interpolate(points, idx, weight) 29 | with tf.Session('') as sess: 30 | tmp,pts1,d,w = sess.run([xyz1, interpolated_points, dist, weight]) 31 | #print w 32 | pts1 = pts1.squeeze() 33 | return pts1 34 | 35 | pts1 = fun(xyz1,xyz2,pts2) 36 | all_pts = np.zeros((104,3)) 37 | all_pts[0:100,:] = pts1 38 | all_pts[100:,:] = pts2 39 | all_xyz = np.zeros((104,3)) 40 | all_xyz[0:100,:]=xyz1 41 | all_xyz[100:,:]=xyz2 42 | showpoints(xyz2, pts2, ballradius=8) 43 | showpoints(xyz1, pts1, ballradius=8) 44 | showpoints(all_xyz, all_pts, ballradius=8) 45 | -------------------------------------------------------------------------------- /CMD_sh/partAE_train_mug12.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | 8 | 9 | DataDir="./03797390_Mug/03797390_sampling_erode0.05_256_ptsSorted" 10 | gpu_id="0" 11 | dataset="03797390_vox" 12 | echo $DataDir 13 | echo $gpu_id 14 | echo $dataset 15 | 16 | 17 | ################### 18 | ################### 19 | 20 | python -u partAE.py --train --epoch 20 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 21 | python -u partAE.py --train --epoch 40 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 22 | python -u partAE.py --train --epoch 60 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 23 | python -u partAE.py --train --epoch 100 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 24 | python -u partAE.py --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 25 | python -u partAE.py --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 26 | 27 | 28 | 29 | 30 | 31 | ################### 32 | ################### 33 | 34 | python -u partAE.py --train --epoch 20 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 35 | python -u partAE.py --train --epoch 40 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 36 | python -u partAE.py --train --epoch 60 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 37 | python -u partAE.py --train --epoch 100 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 38 | python -u partAE.py --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 39 | python -u partAE.py --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 40 | 41 | 42 | -------------------------------------------------------------------------------- /partAE.py: -------------------------------------------------------------------------------- 1 | import os 2 | import scipy.misc 3 | import numpy as np 4 | 5 | from partAE_model import PAE 6 | 7 | import tensorflow as tf 8 | import h5py 9 | 10 | flags = tf.app.flags 11 | flags.DEFINE_integer("epoch", 100, "Epoch to train") 12 | flags.DEFINE_float("learning_rate", 0.001, "Learning rate for adam") 13 | flags.DEFINE_float("beta1", 0.5, "Momentum term of adam [0.5]") 14 | flags.DEFINE_string("dataset", "03001627_vox", "The name of dataset") 15 | flags.DEFINE_string("checkpoint_dir", "checkpoint", "Directory name to save the checkpoints [checkpoint]") 16 | flags.DEFINE_string("data_dir", "./03001627_Chair/03001627_sampling_erode0.05_256", "Root directory of dataset [data]") 17 | flags.DEFINE_boolean("train", False, "True for training, False for testing [False]") 18 | flags.DEFINE_boolean("FeedforwardTrainSet", False, "feed Training Set as test input") 19 | 20 | flags.DEFINE_integer("ptsBatchSize", 16384, "point samples batch size") 21 | 22 | flags.DEFINE_integer("partLabel", 1, "") 23 | 24 | flags.DEFINE_string("gpu", '0', "") 25 | ## 26 | flags.DEFINE_boolean("debug", False, "") 27 | ### 28 | flags.DEFINE_string("workdir", "./default", "") 29 | 30 | 31 | FLAGS = flags.FLAGS 32 | 33 | 34 | os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID" 35 | os.environ["CUDA_VISIBLE_DEVICES"]=FLAGS.gpu 36 | 37 | print(FLAGS) 38 | 39 | 40 | def main(_): 41 | 42 | 43 | run_config = tf.ConfigProto() 44 | run_config.gpu_options.allow_growth=True 45 | 46 | with tf.Session(config=run_config) as sess: 47 | pae = PAE( 48 | sess, 49 | 256, 50 | FLAGS, 51 | is_training = FLAGS.train, 52 | dataset_name=FLAGS.dataset, 53 | checkpoint_dir=FLAGS.checkpoint_dir, 54 | data_dir=FLAGS.data_dir, 55 | partLabel=FLAGS.partLabel, 56 | ptsBatchSize=FLAGS.ptsBatchSize ) 57 | 58 | if FLAGS.train: 59 | pae.train(learning_rate=FLAGS.learning_rate, 60 | beta1=FLAGS.beta1, 61 | for_debug=FLAGS.debug, 62 | epochNum=FLAGS.epoch ) 63 | else: 64 | pae.test( specEpoch=FLAGS.epoch ) 65 | 66 | if __name__ == '__main__': 67 | tf.app.run() 68 | -------------------------------------------------------------------------------- /partAlign.py: -------------------------------------------------------------------------------- 1 | import os 2 | import scipy.misc 3 | import numpy as np 4 | import tensorflow as tf 5 | import h5py 6 | 7 | from partAlign_model import partAlignModel 8 | 9 | flags = tf.app.flags 10 | flags.DEFINE_integer("epoch", 200, "Epoch to train") 11 | flags.DEFINE_float("learning_rate", 0.001, "Learning rate for adam") 12 | flags.DEFINE_float("beta1", 0.5, "Momentum term of adam") 13 | flags.DEFINE_string("dataset", "03001627_vox", "The name of dataset") 14 | flags.DEFINE_string("checkpoint_dir", "checkpoint", "Directory name to save the checkpoints [checkpoint]") 15 | flags.DEFINE_string("data_dir", "./03001627_Chair/03001627_sampling_erode0.05_256", "Root directory of dataset [data]") 16 | flags.DEFINE_boolean("train", False, "True for training, False for testing") 17 | flags.DEFINE_integer("num_of_parts", 4, "") 18 | flags.DEFINE_integer("shapeBatchSize", 64, "") 19 | flags.DEFINE_integer("reWei", 0, "whether or not to assign different weights to different points") 20 | flags.DEFINE_integer("diffShape", 0, "") 21 | flags.DEFINE_string("gpu", '0', "") 22 | flags.DEFINE_boolean("debug", False, "") 23 | flags.DEFINE_string("workdir", "./default", "") 24 | 25 | FLAGS = flags.FLAGS 26 | 27 | os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID" 28 | os.environ["CUDA_VISIBLE_DEVICES"]=FLAGS.gpu 29 | 30 | print(FLAGS) 31 | 32 | 33 | def main(_): 34 | 35 | run_config = tf.ConfigProto() 36 | run_config.gpu_options.allow_growth=True 37 | 38 | with tf.Session(config=run_config) as sess: 39 | PAM = partAlignModel( 40 | sess, 41 | 256, 42 | is_training = FLAGS.train, 43 | dataset_name=FLAGS.dataset, 44 | checkpoint_dir=FLAGS.checkpoint_dir, 45 | data_dir=FLAGS.data_dir, 46 | num_of_parts=FLAGS.num_of_parts, 47 | reWei=FLAGS.reWei, 48 | shapeBatchSize=FLAGS.shapeBatchSize, 49 | FLAGS=FLAGS ) 50 | 51 | if FLAGS.train: 52 | PAM.train(learning_rate=FLAGS.learning_rate, 53 | beta1=FLAGS.beta1, 54 | for_debug=FLAGS.debug, 55 | epochNum=FLAGS.epoch ) 56 | else: 57 | PAM.test(specEpoch=FLAGS.epoch, differentShapes=FLAGS.diffShape) 58 | 59 | if __name__ == '__main__': 60 | tf.app.run() 61 | -------------------------------------------------------------------------------- /latent_3d_points/gan.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 3, 2017 3 | 4 | @author: optas 5 | ''' 6 | 7 | import os.path as osp 8 | import warnings 9 | import tensorflow as tf 10 | 11 | from .neural_net import Neural_Net 12 | from .tf_utils import safe_log 13 | 14 | class GAN(Neural_Net): 15 | 16 | def __init__(self, name, graph): 17 | Neural_Net.__init__(self, name, graph) 18 | 19 | def save_model(self, tick): 20 | self.saver.save(self.sess, self.MODEL_SAVER_ID, global_step=tick) 21 | 22 | def restore_model(self, model_path, epoch, verbose=False): 23 | '''Restore all the variables of a saved model. 24 | ''' 25 | self.saver.restore(self.sess, osp.join(model_path, self.MODEL_SAVER_ID + '-' + str(int(epoch)))) 26 | 27 | if self.epoch.eval(session=self.sess) != epoch: 28 | warnings.warn('Loaded model\'s epoch doesn\'t match the requested one.') 29 | else: 30 | if verbose: 31 | print('Model restored in epoch {0}.'.format(epoch)) 32 | 33 | def optimizer(self, learning_rate, beta, loss, var_list): 34 | initial_learning_rate = learning_rate 35 | optimizer = tf.train.AdamOptimizer(initial_learning_rate, beta1=beta).minimize(loss, var_list=var_list) 36 | return optimizer 37 | 38 | def generate(self, n_samples, noise_params): 39 | noise = self.generator_noise_distribution(n_samples, self.noise_dim, **noise_params) 40 | feed_dict = {self.noise: noise} 41 | return self.sess.run([self.generator_out], feed_dict=feed_dict)[0] 42 | 43 | def vanilla_gan_objective(self, real_prob, synthetic_prob, use_safe_log=True): 44 | if use_safe_log: 45 | log = safe_log 46 | else: 47 | log = tf.log 48 | 49 | loss_d = tf.reduce_mean(-log(real_prob) - log(1 - synthetic_prob)) 50 | loss_g = tf.reduce_mean(-log(synthetic_prob)) 51 | return loss_d, loss_g 52 | 53 | def w_gan_objective(self, real_logit, synthetic_logit): 54 | loss_d = tf.reduce_mean(synthetic_logit) - tf.reduce_mean(real_logit) 55 | loss_g = -tf.reduce_mean(synthetic_logit) 56 | return loss_d, loss_g -------------------------------------------------------------------------------- /data-preprocess/README.MD: -------------------------------------------------------------------------------- 1 | In this folder we provide the code for sampling points for training our networks. Note that you don't need to run code in this folder to test our method. The processed dataset used in the paper has been provided in this LINK. 2 | 3 | 4 | If you need to process your own dataset, you can follow the following steps. 5 | 6 | # step 0 7 | 8 | 9 | - Download surface point samples of shapeNet meshes here, strore them under "../densePointCloud". You can use Poisson disk sampling to get similar samples for your own meshes, and store them in same way. 10 | 11 | - download the shapenet part dataset here, extract the data, and store it under the folder "../yi2016" 12 | 13 | - downlaod the 256^3 voxel dataset here (link originally from HSP), extract the folder "modelBlockedVoxels256", and store it under "../modelBlockedVoxels256" 14 | 15 | 16 | 17 | # step 1 18 | 19 | Get segmented and eroded input point cloud with the script 20 | ``` 1_extract_parts2048_ply_erodedX_withnormal.py ``` 21 | 22 | # step 2 23 | 24 | Sample query point samples for implicit function with this script: 25 | ```2_point_sampling_for_joint_synsthsis_256.py``` 26 | 27 | # step 3 28 | 29 | In the above script, you can use the two arguments '--pstart', '--pend' to specify the starting and ending position in the processing list, so that the data processing can be parallelized. This will give you result folders such as "03001627_sampling_erode0.025_256_0_500", 30 | "03001627_sampling_erode0.025_256_500_1000", ... 31 | 32 | You can use the script ```3_merge_subset.py``` to merge them into one single hdf5. 33 | 34 | 35 | # step 4 36 | 37 | run ```4_sort_points.py``` to sort point clouds stored in hdf5 according to their distance to part boundaries. 38 | 39 | 40 | # Part mesh processing 41 | 42 | the code is provided under ```../poisson-blending``` -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/selection_sort.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | 18 | // input: k (1), distance matrix dist (b,m,n) 19 | // output: idx (b,m,k), val (b,m,k) 20 | __global__ void selection_sort_gpu(int b, int n, int m, int k, float *dist, int *idx, float *val) { 21 | int batch_index = blockIdx.x; 22 | dist+=m*n*batch_index; 23 | idx+=m*k*batch_index; 24 | val+=m*k*batch_index; 25 | 26 | int index = threadIdx.x; 27 | int stride = blockDim.x; 28 | 29 | float *p_dist; 30 | for (int j=index;j>>(b,n,m,k,dist,idx,val); 68 | cudaDeviceSynchronize(); 69 | printf("selection sort cpu time %f\n",get_time()-t0); 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/3d_interpolation/tf_interpolate.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from tensorflow.python.framework import ops 3 | import sys 4 | import os 5 | BASE_DIR = os.path.dirname(__file__) 6 | sys.path.append(BASE_DIR) 7 | interpolate_module=tf.load_op_library(os.path.join(BASE_DIR, 'tf_interpolate_so.so')) 8 | def three_nn(xyz1, xyz2): 9 | ''' 10 | Input: 11 | xyz1: (b,n,3) float32 array, unknown points 12 | xyz2: (b,m,3) float32 array, known points 13 | Output: 14 | dist: (b,n,3) float32 array, distances to known points 15 | idx: (b,n,3) int32 array, indices to known points 16 | ''' 17 | return interpolate_module.three_nn(xyz1, xyz2) 18 | ops.NoGradient('ThreeNN') 19 | def three_interpolate(points, idx, weight): 20 | ''' 21 | Input: 22 | points: (b,m,c) float32 array, known points 23 | idx: (b,n,3) int32 array, indices to known points 24 | weight: (b,n,3) float32 array, weights on known points 25 | Output: 26 | out: (b,n,c) float32 array, interpolated point values 27 | ''' 28 | return interpolate_module.three_interpolate(points, idx, weight) 29 | @tf.RegisterGradient('ThreeInterpolate') 30 | def _three_interpolate_grad(op, grad_out): 31 | points = op.inputs[0] 32 | idx = op.inputs[1] 33 | weight = op.inputs[2] 34 | return [interpolate_module.three_interpolate_grad(points, idx, weight, grad_out), None, None] 35 | 36 | if __name__=='__main__': 37 | import numpy as np 38 | import time 39 | np.random.seed(100) 40 | pts = np.random.random((32,128,64)).astype('float32') 41 | tmp1 = np.random.random((32,512,3)).astype('float32') 42 | tmp2 = np.random.random((32,128,3)).astype('float32') 43 | with tf.device('/cpu:0'): 44 | points = tf.constant(pts) 45 | xyz1 = tf.constant(tmp1) 46 | xyz2 = tf.constant(tmp2) 47 | dist, idx = three_nn(xyz1, xyz2) 48 | weight = tf.ones_like(dist)/3.0 49 | interpolated_points = three_interpolate(points, idx, weight) 50 | with tf.Session('') as sess: 51 | now = time.time() 52 | for _ in range(100): 53 | ret = sess.run(interpolated_points) 54 | print(time.time() - now) 55 | print(ret.shape, ret.dtype) 56 | #print ret 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Prerequisites 2 | 3 | - Linux (tested under Ubuntu 16.04 ) 4 | - Python (tested under 3.6.2) 5 | - TensorFlow (tested under 1.13.1-GPU ) 6 | - numpy, scipy, h5py, scipy, open3d, PyMCubes, tflearn, etc. 7 | 8 | The code reuses some components from 9 | latent_3d_points, 10 | pointnet2 11 | and IM-NET. Before run the code, please compile the customized TensorFlow operators under the folders "latent\_3d\_points/structural\_losses" and 12 | "pointnet\_plusplus/tf\_ops". 13 | 14 | ### Dataset 15 | 16 | - Download the dataset and pretained models HERE. 17 | 18 | 19 | ### Usage 20 | 21 | The commond lines for training and testing the models are all under the folder "./CMD_sh". You may need to open, read and modify the .sh files. 22 | 23 | To train and test part alignment: 24 | ``` 25 | bash ./CMD_sh/partAlign_train_chair.sh 26 | ``` 27 | 28 | To train and test joint synthesis: 29 | ``` 30 | % first pretrain part encoders 31 | bash ./CMD_sh/partAE_train_chair1234.sh 32 | 33 | % then train the joint synthesis network and test it on input parts with GT joints 34 | bash ./CMD_sh/jointSynthesis_train_chair.sh 35 | ``` 36 | 37 | To test joint synthesis for given parts from different objects: 38 | 39 | First set ```diffShape="1"``` in ```"./CMD_sh/partAlign_train_chair.sh"```. And run it to export aligned parts randomly selected from different objects. 40 | 41 | Then run the test on the aligned parts: 42 | ``` 43 | bash ./CMD_sh/jointSynthesis_test_onRealOutput_chair.sh 44 | ``` 45 | 46 | ### Poisson blending 47 | Take a look at the folder "poisson-blending" 48 | 49 | ### Point samping and data preprocessing 50 | Take a look at the folder "data-preprocess" 51 | 52 | ### Citation 53 | If you find our work useful in your research, please consider citing: 54 | 55 | @inproceedings{yin2020coalesce, 56 | author = {Kangxue Yin, Zhiqin Chen, Siddhartha Chaudhuri, Matthew Fisher, Vladimir Kim and Hao Zhang} 57 | title = {COALESCE: Component Assembly by Learning to Synthesize Connections} 58 | booktitle = {Proc. of 3DV} 59 | year = {2020} 60 | } 61 | 62 | -------------------------------------------------------------------------------- /jointSynthesis.py: -------------------------------------------------------------------------------- 1 | import os 2 | import scipy.misc 3 | import numpy as np 4 | import tensorflow as tf 5 | import h5py 6 | 7 | from jointSynthesis_model import JSM 8 | 9 | 10 | flags = tf.app.flags 11 | flags.DEFINE_integer("epoch", 160, "Epoch to train") 12 | flags.DEFINE_float("learning_rate", 0.0001, "Learning rate of for adam") 13 | flags.DEFINE_float("beta1", 0.5, "Momentum term of adam [0.5]") 14 | flags.DEFINE_string("dataset", "03001627_vox", "The name of dataset") 15 | flags.DEFINE_integer("test_outputDim", 128, "output point-value voxel grid size in training") 16 | flags.DEFINE_string("checkpoint_dir", "checkpoint", "Directory name to save the checkpoints [checkpoint]") 17 | flags.DEFINE_string("data_dir", "./03001627_Chair/03001627_sampling_erode0.05_256", "Root directory of dataset [data]") 18 | flags.DEFINE_boolean("train", False, "True for training, False for testing [False]") 19 | flags.DEFINE_boolean("FeedforwardTrainSet", False, "feed Training Set as test input") 20 | 21 | flags.DEFINE_integer("testStartID", 0, "") 22 | flags.DEFINE_integer("testEndID", 1000, "") 23 | flags.DEFINE_integer("outputHdf5", 0, "") 24 | flags.DEFINE_integer("FTSteps", 50, "") 25 | flags.DEFINE_integer("ptsBatchSize", 16384, "") 26 | flags.DEFINE_integer("num_of_parts", 4, "") 27 | flags.DEFINE_string("gpu", '0', "") 28 | flags.DEFINE_boolean("debug", False, "") 29 | flags.DEFINE_string("workdir", "./default", "") 30 | flags.DEFINE_string("test_input_dir", "", "Root directory of dataset [data]") 31 | 32 | ### 33 | FLAGS = flags.FLAGS 34 | 35 | 36 | os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID" 37 | os.environ["CUDA_VISIBLE_DEVICES"]=FLAGS.gpu 38 | 39 | print(FLAGS) 40 | 41 | 42 | def main(_): 43 | 44 | run_config = tf.ConfigProto() 45 | run_config.gpu_options.allow_growth=True 46 | 47 | with tf.Session(config=run_config) as sess: 48 | JSModel = JSM( 49 | sess, 50 | 256, 51 | is_training = FLAGS.train, 52 | dataset_name=FLAGS.dataset, 53 | checkpoint_dir=FLAGS.checkpoint_dir, 54 | data_dir=FLAGS.data_dir, 55 | num_of_parts=FLAGS.num_of_parts, 56 | FLAGS=FLAGS ) 57 | 58 | if FLAGS.train: 59 | JSModel.train(learning_rate=FLAGS.learning_rate, 60 | beta1=FLAGS.beta1, 61 | for_debug=FLAGS.debug, 62 | epochNum=FLAGS.epoch ) 63 | else: 64 | JSModel.test( specEpoch=FLAGS.epoch, FLAGS=FLAGS ) 65 | 66 | 67 | if __name__ == '__main__': 68 | tf.app.run() 69 | -------------------------------------------------------------------------------- /ops.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import tensorflow as tf 3 | 4 | def init_weights(shape, name): 5 | return tf.get_variable(name, shape=shape, initializer=tf.contrib.layers.xavier_initializer()) 6 | 7 | def init_biases(shape): 8 | return tf.Variable(tf.zeros(shape)) 9 | 10 | def lrelu(x, leak=0.02): 11 | return tf.maximum(x, leak*x) 12 | 13 | def batch_norm(input, phase_train): 14 | return tf.contrib.layers.batch_norm(input, decay=0.999, updates_collections=None, epsilon=1e-5, scale=True, is_training=phase_train) 15 | # better using instance normalization since the batch size is 1 16 | #return tf.contrib.layers.instance_norm(input) 17 | 18 | def linear(input_, output_size, scope): 19 | shape = input_.get_shape().as_list() 20 | with tf.variable_scope(scope): 21 | matrix = tf.get_variable("Matrix", [shape[1], output_size], tf.float32, tf.random_normal_initializer(stddev=0.02)) 22 | bias = tf.get_variable("bias", [output_size], initializer=tf.zeros_initializer()) 23 | print("linear","in",shape,"out",(shape[0],output_size)) 24 | return tf.matmul(input_, matrix) + bias 25 | 26 | def conv2d(input_, shape, strides, scope, padding="SAME"): 27 | with tf.variable_scope(scope): 28 | matrix = tf.get_variable('Matrix', shape, initializer=tf.truncated_normal_initializer(stddev=0.02)) 29 | bias = tf.get_variable('bias', [shape[-1]], initializer=tf.zeros_initializer()) 30 | conv = tf.nn.conv2d(input_, matrix, strides=strides, padding=padding) 31 | conv = tf.nn.bias_add(conv, bias) 32 | print("conv2d","in",input_.shape,"out",conv.shape) 33 | return conv 34 | 35 | def conv3d(input_, shape, strides, scope, padding="SAME"): #dilations=[1, 1, 1, 1, 1], 36 | with tf.variable_scope(scope): 37 | matrix = tf.get_variable("Matrix", shape, initializer=tf.contrib.layers.xavier_initializer()) 38 | bias = tf.get_variable("bias", [shape[-1]], initializer=tf.zeros_initializer()) 39 | conv = tf.nn.conv3d(input_, matrix, strides=strides, padding=padding ) 40 | conv = tf.nn.bias_add(conv, bias) 41 | print("conv3d","in",input_.shape,"out",conv.shape) 42 | return conv 43 | 44 | def deconv3d(input_, shape, out_shape, strides, scope, padding="SAME"): 45 | with tf.variable_scope(scope): 46 | matrix = tf.get_variable("Matrix", shape, initializer=tf.contrib.layers.xavier_initializer()) 47 | bias = tf.get_variable("bias", [shape[-2]], initializer=tf.zeros_initializer()) 48 | conv = tf.nn.conv3d_transpose(input_, matrix, out_shape, strides=strides, padding=padding) 49 | conv = tf.nn.bias_add(conv, bias) 50 | print("deconv3d","in",input_.shape,"out",conv.shape) 51 | return conv 52 | 53 | 54 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/selection_sort_const.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | 18 | // input: k (1), distance matrix dist (b,m,n) 19 | // output: idx (b,m,n), dist_out (b,m,n) 20 | __global__ void selection_sort_gpu(int b, int n, int m, int k, const float *dist, int *outi, float *out) { 21 | int batch_index = blockIdx.x; 22 | dist+=m*n*batch_index; 23 | outi+=m*n*batch_index; 24 | out+=m*n*batch_index; 25 | 26 | int index = threadIdx.x; 27 | int stride = blockDim.x; 28 | 29 | // copy from dist to dist_out 30 | for (int j=index;j>>(b,n,m,k,dist,idx,dist_out); 84 | cudaDeviceSynchronize(); 85 | printf("selection sort cpu time %f\n",get_time()-t0); 86 | 87 | //for (int i=0;i 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | 18 | // input: k (1), distance matrix dist (b,m,n) 19 | // output: idx (b,m,n), val (b,m,n) 20 | void selection_sort_cpu(int b, int n, int m, int k, const float *dist, int *idx, float *val) { 21 | float *p_dist; 22 | float tmp; 23 | int tmpi; 24 | for (int i=0;i*: a list of object names for pre-processing. See the text files in *prepare* folder for some examples. 12 | - **: a folder containing normalized and re-oriented shapes in obj format. 13 | - **: a folder containing segmented and noise-removed point clouds and labels. 14 | 15 | 16 | Open *prepare/get_part_mesh.py* and modify the directories to point to the above folders/files. Also change *part_names* and *part_list* if you are not using the predefined categories. 17 | 18 | 19 | Open *prepare/utils.py* and modify the erosion radius. The default radius is 0.05: 20 | ``` 21 | erode_threshold = 0.05 22 | erode_threshold_in = 0.04 23 | erode_threshold_out = 0.06 24 | ``` 25 | *erode_threshold* is the erosion radius, *erode_threshold_in* and *erode_threshold_out* define two boundaries for mesh subdivision. If you want to change the radius to 0.025: 26 | ``` 27 | erode_threshold = 0.025 28 | erode_threshold_in = 0.015 29 | erode_threshold_out = 0.035 30 | ``` 31 | 32 | 33 | Next, go to the *prepare* folder and run the code. Since the code is written in python, the execution is rather slow. We recommend using multiple processes: 34 | ``` 35 | python get_part_mesh.py 36 | ``` 37 | for instance, open 4 terminals and run one of the following commands in each terminal: 38 | ``` 39 | python get_part_mesh.py 0 4 40 | python get_part_mesh.py 1 4 41 | python get_part_mesh.py 2 4 42 | python get_part_mesh.py 3 4 43 | ``` 44 | The output part meshes and edges are written to a folder **. 45 | 46 | ## 2. Poisson blending 47 | 48 | After running the network, the aligned parts and synthesized joints are written to a folder **. The data preparation step also produces a folder **. 49 | 50 | Create a folder and copy the *blend* folder inside. 51 | 52 | Open *blend/poisson_blend.py* and modify the directories to point to the above ** and **. Change the *part_name_list* according to the category. 53 | 54 | Next, go to the *blend* folder and run the code. Since the code is written in python, the execution is rather slow. We recommend using multiple processes: 55 | ``` 56 | python poisson_blend.py 57 | ``` 58 | for instance, open 4 terminals and run one of the following commands in each terminal: 59 | ``` 60 | python poisson_blend.py 0 4 61 | python poisson_blend.py 1 4 62 | python poisson_blend.py 2 4 63 | python poisson_blend.py 3 4 64 | ``` 65 | The outputs are written to a folder **. 66 | 67 | For each shape, there will be several outputs: 68 | - *combined_nojoint.ply*: combining aligned parts without the synthesized joint. 69 | - *combined_beforeblend.ply*: combining aligned parts with the synthesized joint, but before Poisson blending. 70 | - *joint.ply*: the synthesized joint after removing redundant portions. 71 | - *combined_blended.ply*: the blended result which blends both open and close boundaries. 72 | - *combined_blended_2.ply*: the blended result which blends only close boundaries. 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /data-preprocess/3_merge_subset.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import os 4 | import h5py 5 | from scipy.io import loadmat 6 | import random 7 | import json 8 | import io 9 | 10 | import argparse 11 | 12 | parser = argparse.ArgumentParser() 13 | FLAGS = parser.parse_args() 14 | 15 | src_folders = [\ 16 | "03001627_sampling_erode0.025_256_0_500", \ 17 | "03001627_sampling_erode0.025_256_500_1000", \ 18 | "03001627_sampling_erode0.025_256_1000_1500", \ 19 | "03001627_sampling_erode0.025_256_1500_2000", \ 20 | "03001627_sampling_erode0.025_256_2000_2500", \ 21 | "03001627_sampling_erode0.025_256_2500_3000", \ 22 | "03001627_sampling_erode0.025_256_3000_3500", \ 23 | "03001627_sampling_erode0.025_256_3500_4000" \ 24 | ] 25 | 26 | dstFolder = "03001627_sampling_erode0.025_256" 27 | dataFname = "03001627_vox" 28 | 29 | 30 | 31 | dstFilePrefix = dstFolder + '/' + dataFname 32 | 33 | 34 | if not os.path.exists( dstFolder ): 35 | os.makedirs( dstFolder ) 36 | 37 | 38 | ########## get list of Objs 39 | 40 | objlist_merged = [] 41 | sub_counts = [] 42 | 43 | for srcFolder in src_folders: 44 | objlist_path = srcFolder + '/' + dataFname +'_obj_list.txt' 45 | 46 | if os.path.exists( objlist_path ): 47 | text_file = open( objlist_path, "r") 48 | objlist = text_file.readlines() 49 | 50 | for i in range(len(objlist)): 51 | objlist[i] = objlist[i].rstrip('\r\n') 52 | objlist_merged.append( objlist[i] ) 53 | 54 | sub_counts.append( len( objlist ) ) 55 | 56 | text_file.close() 57 | else: 58 | print("error: cannot load "+ objlist_path) 59 | exit(0) 60 | 61 | name_num = len( objlist_merged ) 62 | 63 | print("sub_counts = ", sub_counts) 64 | print("name_num = ", name_num) 65 | 66 | assert( sum(sub_counts) == name_num ) 67 | 68 | ########### write list of objs 69 | fout = open( dstFilePrefix +'_obj_list.txt', 'w', newline='') 70 | for name_list_idx in objlist_merged: 71 | fout.write(name_list_idx+"\n") 72 | fout.close() 73 | 74 | 75 | ########### create datasets 76 | 77 | hdf5_path = dstFilePrefix + '.hdf5' 78 | hdf5_file = h5py.File(hdf5_path, 'w') 79 | 80 | srcpath_0 = src_folders[0] + '/' + dataFname +'.hdf5' 81 | datasetNames = [] 82 | with h5py.File( srcpath_0, 'r') as data_dict_0: 83 | datasetNames = list( data_dict_0.keys() ) 84 | 85 | for dname in datasetNames: 86 | 87 | dataShape = list( data_dict_0[dname].shape ) 88 | dataShape[0] = name_num 89 | 90 | hdf5_file.create_dataset( dname, dataShape , data_dict_0[dname].dtype, compression=4) 91 | 92 | 93 | print(datasetNames) 94 | 95 | ################## start merging datasets 96 | sp = 0 97 | for ii in range(len(src_folders)): 98 | 99 | srcFolder = src_folders[ii] 100 | dataCount = sub_counts[ii] 101 | 102 | print("srcFolder = ", srcFolder) 103 | print("dataCount = ", dataCount) 104 | 105 | srcpath = srcFolder + '/' + dataFname +'.hdf5' 106 | data_dict = h5py.File( srcpath, 'r') 107 | 108 | 109 | for dname in datasetNames: 110 | hdf5_file[ dname ][sp : sp + dataCount ] = data_dict[ dname ][:dataCount] 111 | print( '----------- ', dname, ': ', data_dict[ dname ][:dataCount].shape ) 112 | 113 | sp = sp + dataCount 114 | 115 | print("sp = ", sp) 116 | 117 | hdf5_file.close() 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /latent_3d_points_decoder.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on February 4, 2017 3 | 4 | @author: optas 5 | 6 | ''' 7 | 8 | 9 | import tensorflow as tf 10 | import numpy as np 11 | import warnings 12 | 13 | from tflearn.layers.conv import conv_1d, avg_pool_1d 14 | from tflearn.layers.normalization import batch_normalization 15 | from tflearn.layers.core import fully_connected, dropout 16 | 17 | from latent_3d_points_tf_utils import expand_scope_by_name, replicate_parameter_for_all_layers 18 | 19 | 20 | def decoder_with_fc_only(latent_signal, layer_sizes=[], b_norm=True, non_linearity=tf.nn.relu, 21 | regularizer=None, weight_decay=0.001, reuse=False, scope=None, dropout_prob=None, 22 | b_norm_finish=False, verbose=False): 23 | '''A decoding network which maps points from the latent space back onto the data space. 24 | ''' 25 | if verbose: 26 | print( 'Building Decoder' ) 27 | 28 | n_layers = len(layer_sizes) 29 | dropout_prob = replicate_parameter_for_all_layers(dropout_prob, n_layers) 30 | 31 | if n_layers < 2: 32 | raise ValueError('For an FC decoder with single a layer use simpler code.') 33 | 34 | for i in range(0, n_layers - 1): 35 | name = 'decoder_fc_' + str(i) 36 | scope_i = expand_scope_by_name(scope, name) 37 | 38 | if i == 0: 39 | layer = latent_signal 40 | 41 | layer = fully_connected(layer, layer_sizes[i], activation='linear', weights_init='xavier', name=name, regularizer=regularizer, weight_decay=weight_decay, reuse=reuse, scope=scope_i) 42 | 43 | if verbose: 44 | print( name, 'FC params = ', np.prod(layer.W.get_shape().as_list()) + np.prod(layer.b.get_shape().as_list()) ) 45 | 46 | if b_norm: 47 | name += '_bnorm' 48 | scope_i = expand_scope_by_name(scope, name) 49 | layer = batch_normalization(layer, name=name, reuse=reuse, scope=scope_i) 50 | if verbose: 51 | print( 'bnorm params = ', np.prod(layer.beta.get_shape().as_list()) + np.prod(layer.gamma.get_shape().as_list()) ) 52 | 53 | if non_linearity is not None: 54 | layer = non_linearity(layer) 55 | 56 | if dropout_prob is not None and dropout_prob[i] > 0: 57 | layer = dropout(layer, 1.0 - dropout_prob[i]) 58 | 59 | if verbose: 60 | print( layer ) 61 | print( 'output size:', np.prod(layer.get_shape().as_list()[1:]), '\n' ) 62 | 63 | # Last decoding layer never has a non-linearity. 64 | name = 'decoder_fc_' + str(n_layers - 1) 65 | scope_i = expand_scope_by_name(scope, name) 66 | layer = fully_connected(layer, layer_sizes[n_layers - 1], activation='linear', weights_init='xavier', name=name, regularizer=regularizer, weight_decay=weight_decay, reuse=reuse, scope=scope_i) 67 | if verbose: 68 | print( name, 'FC params = ', np.prod(layer.W.get_shape().as_list()) + np.prod(layer.b.get_shape().as_list()) ) 69 | 70 | if b_norm_finish: 71 | name += '_bnorm' 72 | scope_i = expand_scope_by_name(scope, name) 73 | layer = batch_normalization(layer, name=name, reuse=reuse, scope=scope_i) 74 | if verbose: 75 | print( 'bnorm params = ', np.prod(layer.beta.get_shape().as_list()) + np.prod(layer.gamma.get_shape().as_list()) ) 76 | 77 | if verbose: 78 | print( layer ) 79 | print( 'output size:', np.prod(layer.get_shape().as_list()[1:]), '\n' ) 80 | 81 | return layer 82 | 83 | 84 | -------------------------------------------------------------------------------- /data-preprocess/4_sort_points.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import os 4 | import h5py 5 | from scipy.io import loadmat 6 | import random 7 | import json 8 | import io 9 | import shutil 10 | 11 | 12 | from utils import * 13 | 14 | from sklearn.neighbors import KDTree as skKDtree 15 | 16 | import argparse 17 | 18 | parser = argparse.ArgumentParser() 19 | FLAGS = parser.parse_args() 20 | 21 | 22 | ################################## 23 | srcFolder = "03001627_sampling_erode0.05_256" 24 | dstFolder = srcFolder + "_ptsSorted" 25 | dataFname = "03001627_vox" 26 | num_of_parts = 4 27 | ################################## 28 | 29 | 30 | 31 | if os.path.exists( dstFolder ) and os.path.isdir(dstFolder): 32 | shutil.rmtree(dstFolder) 33 | shutil.copytree(srcFolder, dstFolder) 34 | 35 | 36 | if not os.path.exists( dstFolder+'/smoothed_label_ply' ): 37 | os.makedirs( dstFolder+'/smoothed_label_ply' ) 38 | 39 | 40 | ########### modify datasets 41 | 42 | dstFilePrefix = dstFolder + '/' + dataFname 43 | 44 | hdf5_path = dstFilePrefix + '.hdf5' 45 | hdf5_file = h5py.File(hdf5_path, 'r+') 46 | 47 | datasetNames =hdf5_file.keys() 48 | print(datasetNames) 49 | 50 | 51 | 52 | ### sort point cloud 53 | 54 | allpartPts2048_ori = hdf5_file['allpartPts2048_ori'][:, :, :] 55 | allpartPts2048_ori_normal = hdf5_file['allpartPts2048_ori_normal'][:, :, :] 56 | allpartPts2048_ori_dis = hdf5_file['allpartPts2048_ori_dis'][:, : ] 57 | 58 | name_num = allpartPts2048_ori.shape[0] 59 | for mid in range(name_num): 60 | 61 | print( "mid = ", mid ) 62 | 63 | for pid in range(num_of_parts): 64 | 65 | pc = allpartPts2048_ori[ mid, pid*2048:(pid+1)*2048, : ] 66 | nml = allpartPts2048_ori_normal[ mid, pid*2048:(pid+1)*2048, : ] 67 | dis = allpartPts2048_ori_dis[ mid, pid*2048:(pid+1)*2048 ] 68 | 69 | indices = np.argsort(dis) 70 | 71 | allpartPts2048_ori[ mid, pid*2048:(pid+1)*2048, : ] = pc[indices, :] 72 | allpartPts2048_ori_normal[ mid, pid*2048:(pid+1)*2048, : ] = nml[indices, :] 73 | allpartPts2048_ori_dis[ mid, pid*2048:(pid+1)*2048 ] = dis[indices ] 74 | 75 | 76 | if mid < 5: 77 | 78 | pc_list = [] 79 | nml_list = [] 80 | dis_list = [] 81 | for pid in range(num_of_parts): 82 | pc = allpartPts2048_ori[ mid, pid*2048:(pid*2048+512), : ] 83 | nml = allpartPts2048_ori_normal[ mid, pid*2048:(pid*2048+512), : ] 84 | dis = allpartPts2048_ori_dis[ mid, pid*2048:(pid*2048+512) ] 85 | 86 | pc_list.append( pc ) 87 | nml_list.append( nml ) 88 | dis_list.append( dis ) 89 | 90 | pc = np.concatenate( pc_list, axis=0 ) 91 | nml = np.concatenate( nml_list, axis=0 ) 92 | dis = np.concatenate( dis_list, axis=0 ) 93 | 94 | outplyPath = dstFolder+'/smoothed_label_ply/' + str(mid) + '_first512.ply' 95 | output_point_cloud_valued_ply_withNormal( outplyPath, pc, nml, dis*10 ) 96 | 97 | 98 | hdf5_file.create_dataset( "allpartPts2048_ori_sorted", data=allpartPts2048_ori, compression=9 ) 99 | hdf5_file.create_dataset( "allpartPts2048_ori_normal_sorted", data=allpartPts2048_ori_normal, compression=9 ) 100 | hdf5_file.create_dataset( "allpartPts2048_ori_dis_sorted", data=allpartPts2048_ori_dis, compression=9 ) 101 | 102 | 103 | hdf5_file.close() 104 | 105 | -------------------------------------------------------------------------------- /latent_3d_points/structural_losses/tf_nndistance.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from tensorflow.python.framework import ops 3 | import os.path as osp 4 | 5 | base_dir = osp.dirname(osp.abspath(__file__)) 6 | 7 | nn_distance_module = tf.load_op_library(osp.join(base_dir, 'tf_nndistance_so.so')) 8 | 9 | 10 | def nn_distance(xyz1, xyz2): 11 | ''' 12 | Computes the distance of nearest neighbors for a pair of point clouds 13 | input: xyz1: (batch_size,#points_1,3) the first point cloud 14 | input: xyz2: (batch_size,#points_2,3) the second point cloud 15 | output: dist1: (batch_size,#point_1) distance from first to second 16 | output: idx1: (batch_size,#point_1) nearest neighbor from first to second 17 | output: dist2: (batch_size,#point_2) distance from second to first 18 | output: idx2: (batch_size,#point_2) nearest neighbor from second to first 19 | ''' 20 | 21 | return nn_distance_module.nn_distance(xyz1,xyz2) 22 | 23 | #@tf.RegisterShape('NnDistance') 24 | @ops.RegisterShape('NnDistance') 25 | def _nn_distance_shape(op): 26 | shape1=op.inputs[0].get_shape().with_rank(3) 27 | shape2=op.inputs[1].get_shape().with_rank(3) 28 | return [tf.TensorShape([shape1.dims[0],shape1.dims[1]]),tf.TensorShape([shape1.dims[0],shape1.dims[1]]), 29 | tf.TensorShape([shape2.dims[0],shape2.dims[1]]),tf.TensorShape([shape2.dims[0],shape2.dims[1]])] 30 | @ops.RegisterGradient('NnDistance') 31 | def _nn_distance_grad(op,grad_dist1,grad_idx1,grad_dist2,grad_idx2): 32 | xyz1=op.inputs[0] 33 | xyz2=op.inputs[1] 34 | idx1=op.outputs[1] 35 | idx2=op.outputs[3] 36 | return nn_distance_module.nn_distance_grad(xyz1,xyz2,grad_dist1,idx1,grad_dist2,idx2) 37 | 38 | 39 | if __name__=='__main__': 40 | import numpy as np 41 | import random 42 | import time 43 | from tensorflow.python.kernel_tests.gradient_checker import compute_gradient 44 | random.seed(100) 45 | np.random.seed(100) 46 | with tf.Session('') as sess: 47 | xyz1=np.random.randn(32,16384,3).astype('float32') 48 | xyz2=np.random.randn(32,1024,3).astype('float32') 49 | with tf.device('/gpu:0'): 50 | inp1=tf.Variable(xyz1) 51 | inp2=tf.constant(xyz2) 52 | reta,retb,retc,retd=nn_distance(inp1,inp2) 53 | loss=tf.reduce_sum(reta)+tf.reduce_sum(retc) 54 | train=tf.train.GradientDescentOptimizer(learning_rate=0.05).minimize(loss) 55 | sess.run(tf.initialize_all_variables()) 56 | t0=time.time() 57 | t1=t0 58 | best=1e100 59 | for i in range(100): 60 | trainloss,_=sess.run([loss,train]) 61 | newt=time.time() 62 | best=min(best,newt-t1) 63 | #print i,trainloss,(newt-t0)/(i+1),best 64 | t1=newt 65 | #print sess.run([inp1,retb,inp2,retd]) 66 | #grads=compute_gradient([inp1,inp2],[(16,32,3),(16,32,3)],loss,(1,),[xyz1,xyz2]) 67 | #for i,j in grads: 68 | #print i.shape,j.shape,np.mean(np.abs(i-j)),np.mean(np.abs(i)),np.mean(np.abs(j)) 69 | #for i in xrange(10): 70 | #t0=time.time() 71 | #a,b,c,d=sess.run([reta,retb,retc,retd],feed_dict={inp1:xyz1,inp2:xyz2}) 72 | #print 'time',time.time()-t0 73 | #print a.shape,b.shape,c.shape,d.shape 74 | #print a.dtype,b.dtype,c.dtype,d.dtype 75 | #samples=np.array(random.sample(range(xyz2.shape[1]),100),dtype='int32') 76 | #dist1=((xyz1[:,samples,None,:]-xyz2[:,None,:,:])**2).sum(axis=-1).min(axis=-1) 77 | #idx1=((xyz1[:,samples,None,:]-xyz2[:,None,:,:])**2).sum(axis=-1).argmin(axis=-1) 78 | #print np.abs(dist1-a[:,samples]).max() 79 | #print np.abs(idx1-b[:,samples]).max() 80 | #dist2=((xyz2[:,samples,None,:]-xyz1[:,None,:,:])**2).sum(axis=-1).min(axis=-1) 81 | #idx2=((xyz2[:,samples,None,:]-xyz1[:,None,:,:])**2).sum(axis=-1).argmin(axis=-1) 82 | #print np.abs(dist2-c[:,samples]).max() 83 | #print np.abs(idx2-d[:,samples]).max() 84 | 85 | -------------------------------------------------------------------------------- /CMD_sh/partAE_train_airplane1234.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | 8 | 9 | DataDir="./02691156_Airplane/02691156_sampling_erode0.025_256_ptsSorted" 10 | gpu_id="0" 11 | dataset="02691156_vox" 12 | 13 | echo $DataDir 14 | echo $gpu_id 15 | echo $dataset 16 | 17 | ################### 18 | ################### 19 | 20 | python -u partAE.py --train --epoch 20 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 21 | python -u partAE.py --train --epoch 40 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 22 | python -u partAE.py --train --epoch 60 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 23 | python -u partAE.py --train --epoch 100 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 24 | python -u partAE.py --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 25 | python -u partAE.py --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 26 | 27 | 28 | ################### 29 | ################### 30 | 31 | python -u partAE.py --train --epoch 20 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 32 | python -u partAE.py --train --epoch 40 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 33 | python -u partAE.py --train --epoch 60 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 34 | python -u partAE.py --train --epoch 100 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 35 | python -u partAE.py --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 36 | python -u partAE.py --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 37 | 38 | 39 | 40 | ################### 41 | ################### 42 | 43 | python -u partAE.py --train --epoch 20 --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 44 | python -u partAE.py --train --epoch 40 --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 45 | python -u partAE.py --train --epoch 60 --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 46 | python -u partAE.py --train --epoch 100 --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 47 | python -u partAE.py --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 48 | python -u partAE.py --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 49 | 50 | ################### 51 | ################### 52 | python -u partAE.py --train --epoch 20 --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 53 | python -u partAE.py --train --epoch 40 --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 54 | python -u partAE.py --train --epoch 60 --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 55 | python -u partAE.py --train --epoch 100 --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 56 | python -u partAE.py --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 57 | python -u partAE.py --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 58 | 59 | 60 | -------------------------------------------------------------------------------- /CMD_sh/partAE_train_chair1234.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | set -x #echo on 5 | 6 | 7 | 8 | 9 | DataDir="./03001627_Chair/03001627_sampling_erode0.05_256_ptsSorted" 10 | gpu_id="0" 11 | dataset="03001627_vox" 12 | 13 | echo $DataDir 14 | echo $gpu_id 15 | echo $dataset 16 | 17 | ################### 18 | ################### 19 | 20 | python -u partAE.py --train --epoch 20 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 21 | python -u partAE.py --train --epoch 40 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 22 | python -u partAE.py --train --epoch 60 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 23 | python -u partAE.py --train --epoch 100 --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 24 | python -u partAE.py --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 25 | python -u partAE.py --partLabel 1 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 26 | 27 | 28 | 29 | ################### 30 | ################### 31 | 32 | python -u partAE.py --train --epoch 20 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 33 | python -u partAE.py --train --epoch 40 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 34 | python -u partAE.py --train --epoch 60 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 35 | python -u partAE.py --train --epoch 100 --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 36 | python -u partAE.py --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 37 | python -u partAE.py --partLabel 2 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 38 | 39 | 40 | 41 | 42 | ################### 43 | ################### 44 | 45 | python -u partAE.py --train --epoch 20 --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 46 | python -u partAE.py --train --epoch 40 --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 47 | python -u partAE.py --train --epoch 60 --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 48 | python -u partAE.py --train --epoch 100 --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 49 | python -u partAE.py --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 50 | python -u partAE.py --partLabel 3 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 51 | 52 | 53 | 54 | 55 | ################### 56 | ################### 57 | python -u partAE.py --train --epoch 20 --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.001 58 | python -u partAE.py --train --epoch 40 --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.0005 59 | python -u partAE.py --train --epoch 60 --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.00025 60 | python -u partAE.py --train --epoch 100 --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --learning_rate 0.000125 61 | python -u partAE.py --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 62 | python -u partAE.py --partLabel 4 --gpu $gpu_id --data_dir $DataDir --dataset $dataset --epoch 100 --FeedforwardTrainSet Ture 63 | 64 | 65 | -------------------------------------------------------------------------------- /pointnet_plusplus_encoder_1B.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on February 4, 2017 3 | 4 | @author: optas 5 | 6 | ''' 7 | 8 | import tensorflow as tf 9 | import numpy as np 10 | import warnings 11 | 12 | from tflearn.layers.core import fully_connected, dropout 13 | from tflearn.layers.conv import conv_1d, avg_pool_1d 14 | from tflearn.layers.normalization import batch_normalization 15 | from tflearn.layers.core import fully_connected, dropout 16 | 17 | import os 18 | import sys 19 | import collections 20 | 21 | BASE_DIR = os.path.dirname(__file__) 22 | sys.path.append(BASE_DIR) 23 | sys.path.append(BASE_DIR + "/pointnet_plusplus/utils") 24 | sys.path.append(BASE_DIR + "/pointnet_plusplus/tf_ops") 25 | sys.path.append(BASE_DIR + "/pointnet_plusplus/tf_ops/3d_interpolation") 26 | sys.path.append(BASE_DIR + "/pointnet_plusplus/tf_ops/grouping") 27 | sys.path.append(BASE_DIR + "/pointnet_plusplus/tf_ops/sampling") 28 | from pointnet_util import pointnet_sa_module, pointnet_fp_module 29 | 30 | 31 | 32 | def getEncoder_oneBranch(partPoints_input, dis2Joint, Sigma, is_training, reuse, scope_predix="part_1", verbose=True,bn_decay=None): 33 | 34 | scname = scope_predix+"_pointNetPP_encoder" 35 | with tf.variable_scope( scname ) as sc: 36 | if reuse: 37 | sc.reuse_variables() 38 | 39 | is_training = tf.constant(is_training, dtype=tf.bool) 40 | 41 | 42 | l0_xyz = partPoints_input 43 | l0_points = None 44 | 45 | 46 | print( "partPoints_input.shape = ", partPoints_input.shape ) 47 | if partPoints_input.shape[2] == 6: 48 | l0_xyz = partPoints_input[:,:, 0:3] 49 | l0_points = partPoints_input[:,:, 3:6] 50 | 51 | 52 | 53 | # assume self.shapeBatchSize==1 54 | inputDims = tf.reduce_max(l0_xyz , axis=[0, 1] ) - tf.reduce_min( l0_xyz , axis=[0, 1] ) 55 | print( "inputDims.shape = ",inputDims.shape ) 56 | does_part_exist = tf.dtypes.cast( tf.reduce_mean( tf.abs(inputDims) ) > 0.01, tf.float32 ) 57 | 58 | 59 | # Set Abstraction layers 60 | l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=256, radius=0.1*2, nsample=128, 61 | mlp=[64, 64, 128], mlp2=None, group_all=False, 62 | is_training=is_training, bn_decay=bn_decay, scope='layer1', bn=False) 63 | 64 | l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=128, radius=0.2*2, nsample=128, 65 | mlp=[128, 128, 128], mlp2=None, group_all=False, 66 | is_training=is_training, bn_decay=bn_decay, scope='layer2', bn=False) 67 | 68 | l4_xyz, l4_points, l4_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=None, radius=None, nsample=None, 69 | mlp=[128, 128, 128], mlp2=None, group_all=True, 70 | is_training=is_training, bn_decay=bn_decay, scope='layerxxx', bn=False) 71 | 72 | 73 | output_4 = tf.reshape(l4_points, [l0_xyz.shape[0], 128] ) 74 | 75 | 76 | print(('output_4.shape = %s', output_4.shape)) 77 | 78 | return output_4 * does_part_exist 79 | 80 | 81 | 82 | def get_pointNet_code_of_singlePart(partPoints_input, dis2Joint, is_training, reuse, scope_predix="part_1", verbose=True, bn_decay=None): 83 | 84 | if len(partPoints_input.shape)==2: 85 | partPoints_input = tf.expand_dims(partPoints_input, 0) 86 | 87 | if len(dis2Joint.shape)==1: 88 | dis2Joint = tf.expand_dims(dis2Joint, 0) 89 | 90 | partPoints_input_local = partPoints_input[:, :512, :] 91 | dis2Joint_local = dis2Joint[:, :512 ] 92 | 93 | latent_code_2 = getEncoder_oneBranch( partPoints_input , dis2Joint, 2048, is_training, reuse, scope_predix+"_B2", verbose, bn_decay) 94 | 95 | 96 | return latent_code_2 97 | 98 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/query_ball_point.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 18 | // output: idx (b,m,nsample) 19 | void query_ball_point_cpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) { 20 | for (int i=0;i 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 18 | // output: idx (b,m,nsample) 19 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) { 20 | int index = threadIdx.x; 21 | xyz1 += n*3*index; 22 | xyz2 += m*3*index; 23 | idx += m*nsample*index; 24 | 25 | for (int j=0;j>>(b,n,m,radius,nsample,xyz1,xyz2,idx); 113 | cudaDeviceSynchronize(); 114 | printf("query_ball_point gpu time %f\n",get_time()-t0); 115 | 116 | t0=get_time(); 117 | group_point_gpu<<<1,b>>>(b,n,c,m,nsample,points,idx,out); 118 | cudaDeviceSynchronize(); 119 | printf("grou_point gpu time %f\n",get_time()-t0); 120 | 121 | t0=get_time(); 122 | group_point_grad_gpu<<<1,b>>>(b,n,c,m,nsample,grad_out,idx,grad_points); 123 | cudaDeviceSynchronize(); 124 | printf("grou_point_grad gpu time %f\n",get_time()-t0); 125 | 126 | cudaFree(xyz1); 127 | cudaFree(xyz2); 128 | cudaFree(points); 129 | cudaFree(idx); 130 | cudaFree(out); 131 | cudaFree(grad_out); 132 | cudaFree(grad_points); 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/query_ball_point.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 18 | // output: idx (b,m,nsample) 19 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) { 20 | for (int i=0;i>>(b,n,m,radius,nsample,xyz1,xyz2,idx); 113 | cudaDeviceSynchronize(); 114 | printf("query_ball_point gpu time %f\n",get_time()-t0); 115 | 116 | t0=get_time(); 117 | group_point_gpu<<<1,1>>>(b,n,c,m,nsample,points,idx,out); 118 | cudaDeviceSynchronize(); 119 | printf("grou_point gpu time %f\n",get_time()-t0); 120 | 121 | t0=get_time(); 122 | group_point_grad_gpu<<<1,1>>>(b,n,c,m,nsample,grad_out,idx,grad_points); 123 | cudaDeviceSynchronize(); 124 | printf("grou_point_grad gpu time %f\n",get_time()-t0); 125 | 126 | cudaFree(xyz1); 127 | cudaFree(xyz2); 128 | cudaFree(points); 129 | cudaFree(idx); 130 | cudaFree(out); 131 | cudaFree(grad_out); 132 | cudaFree(grad_points); 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/query_ball_point_grid.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 18 | // output: idx (b,m,nsample) 19 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) { 20 | int batch_index = blockIdx.x; 21 | xyz1 += n*3*batch_index; 22 | xyz2 += m*3*batch_index; 23 | idx += m*nsample*batch_index; 24 | 25 | int index = threadIdx.x; 26 | int stride = blockDim.x; 27 | 28 | for (int j=index;j>>(b,n,m,radius,nsample,xyz1,xyz2,idx); 123 | cudaDeviceSynchronize(); 124 | printf("query_ball_point gpu time %f\n",get_time()-t0); 125 | 126 | t0=get_time(); 127 | group_point_gpu<<>>(b,n,c,m,nsample,points,idx,out); 128 | cudaDeviceSynchronize(); 129 | printf("grou_point gpu time %f\n",get_time()-t0); 130 | 131 | t0=get_time(); 132 | group_point_grad_gpu<<>>(b,n,c,m,nsample,grad_out,idx,grad_points); 133 | cudaDeviceSynchronize(); 134 | printf("grou_point_grad gpu time %f\n",get_time()-t0); 135 | 136 | cudaFree(xyz1); 137 | cudaFree(xyz2); 138 | cudaFree(points); 139 | cudaFree(idx); 140 | cudaFree(out); 141 | cudaFree(grad_out); 142 | cudaFree(grad_points); 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /latent_3d_points/structural_losses/tf_nndistance_g.cu: -------------------------------------------------------------------------------- 1 | #if GOOGLE_CUDA 2 | #define EIGEN_USE_GPU 3 | #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" 4 | 5 | __global__ void NmDistanceKernel(int b,int n,const float * xyz,int m,const float * xyz2,float * result,int * result_i){ 6 | const int batch=512; 7 | __shared__ float buf[batch*3]; 8 | for (int i=blockIdx.x;ibest){ 120 | result[(i*n+j)]=best; 121 | result_i[(i*n+j)]=best_i; 122 | } 123 | } 124 | __syncthreads(); 125 | } 126 | } 127 | } 128 | void NmDistanceKernelLauncher(int b,int n,const float * xyz,int m,const float * xyz2,float * result,int * result_i,float * result2,int * result2_i){ 129 | NmDistanceKernel<<>>(b,n,xyz,m,xyz2,result,result_i); 130 | NmDistanceKernel<<>>(b,m,xyz2,n,xyz,result2,result2_i); 131 | } 132 | __global__ void NmDistanceGradKernel(int b,int n,const float * xyz1,int m,const float * xyz2,const float * grad_dist1,const int * idx1,float * grad_xyz1,float * grad_xyz2){ 133 | for (int i=blockIdx.x;i>>(b,n,xyz1,m,xyz2,grad_dist1,idx1,grad_xyz1,grad_xyz2); 156 | NmDistanceGradKernel<<>>(b,m,xyz2,n,xyz1,grad_dist2,idx2,grad_xyz2,grad_xyz1); 157 | } 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/grouping/tf_grouping_g.cu: -------------------------------------------------------------------------------- 1 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3) 2 | // output: idx (b,m,nsample), pts_cnt (b,m) 3 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx, int *pts_cnt) { 4 | int batch_index = blockIdx.x; 5 | xyz1 += n*3*batch_index; 6 | xyz2 += m*3*batch_index; 7 | idx += m*nsample*batch_index; 8 | pts_cnt += m*batch_index; // counting how many unique points selected in local region 9 | 10 | int index = threadIdx.x; 11 | int stride = blockDim.x; 12 | 13 | for (int j=index;j>>(b,n,m,radius,nsample,xyz1,xyz2,idx,pts_cnt); 127 | //cudaDeviceSynchronize(); 128 | } 129 | void selectionSortLauncher(int b, int n, int m, int k, const float *dist, int *outi, float *out) { 130 | selection_sort_gpu<<>>(b,n,m,k,dist,outi,out); 131 | //cudaDeviceSynchronize(); 132 | } 133 | void groupPointLauncher(int b, int n, int c, int m, int nsample, const float *points, const int *idx, float *out){ 134 | group_point_gpu<<>>(b,n,c,m,nsample,points,idx,out); 135 | //cudaDeviceSynchronize(); 136 | } 137 | void groupPointGradLauncher(int b, int n, int c, int m, int nsample, const float *grad_out, const int *idx, float *grad_points){ 138 | group_point_grad_gpu<<>>(b,n,c,m,nsample,grad_out,idx,grad_points); 139 | //group_point_grad_gpu<<<1,1>>>(b,n,c,m,nsample,grad_out,idx,grad_points); 140 | //cudaDeviceSynchronize(); 141 | } 142 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/3d_interpolation/interpolate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // memset 4 | #include // rand, RAND_MAX 5 | #include // sqrtf 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | 18 | // Find three nearest neigbors with square distance 19 | // input: xyz1 (b,n,3), xyz2(b,m,3) 20 | // output: dist (b,n,3), idx (b,n,3) 21 | void threenn_cpu(int b, int n, int m, const float *xyz1, const float *xyz2, float *dist, int *idx) { 22 | for (int i=0;i 0) 108 | jittered_data = np.clip(sigma * np.random.randn(B, N, C), -1*clip, clip) 109 | jittered_data += batch_data 110 | return jittered_data 111 | 112 | def shift_point_cloud(batch_data, shift_range=0.1): 113 | """ Randomly shift point cloud. Shift is per point cloud. 114 | Input: 115 | BxNx3 array, original batch of point clouds 116 | Return: 117 | BxNx3 array, shifted batch of point clouds 118 | """ 119 | B, N, C = batch_data.shape 120 | shifts = np.random.uniform(-shift_range, shift_range, (B,3)) 121 | for batch_index in range(B): 122 | batch_data[batch_index,:,:] += shifts[batch_index,:] 123 | return batch_data 124 | 125 | 126 | def random_scale_point_cloud(batch_data, scale_low=0.8, scale_high=1.25): 127 | """ Randomly scale the point cloud. Scale is per point cloud. 128 | Input: 129 | BxNx3 array, original batch of point clouds 130 | Return: 131 | BxNx3 array, scaled batch of point clouds 132 | """ 133 | B, N, C = batch_data.shape 134 | scales = np.random.uniform(scale_low, scale_high, B) 135 | for batch_index in range(B): 136 | batch_data[batch_index,:,:] *= scales[batch_index] 137 | return batch_data 138 | 139 | def getDataFiles(list_filename): 140 | return [line.rstrip() for line in open(list_filename)] 141 | 142 | def load_h5(h5_filename): 143 | f = h5py.File(h5_filename) 144 | data = f['data'][:] 145 | label = f['label'][:] 146 | return (data, label) 147 | 148 | def loadDataFile(filename): 149 | return load_h5(filename) 150 | 151 | -------------------------------------------------------------------------------- /latent_3d_points/structural_losses/approxmatch.cu: -------------------------------------------------------------------------------- 1 | //n<=4096, m<=1024 2 | __global__ void approxmatch(int b,int n,int m,const float * __restrict__ xyz1,const float * __restrict__ xyz2,float * __restrict__ match){ 3 | const int MaxN=4096,MaxM=1024; 4 | __shared__ float remainL[MaxN],remainR[MaxM],ratioR[MaxM],ratioL[MaxN]; 5 | __shared__ int listR[MaxM],lc; 6 | float multiL,multiR; 7 | if (n>=m){ 8 | multiL=1; 9 | multiR=n/m; 10 | }else{ 11 | multiL=m/n; 12 | multiR=1; 13 | } 14 | for (int i=blockIdx.x;i=-2;j--){ 23 | float level=-powf(4.0f,j); 24 | if (j==-2){ 25 | level=0; 26 | } 27 | if (threadIdx.x==0){ 28 | lc=0; 29 | for (int k=0;k0) 31 | listR[lc++]=k; 32 | } 33 | __syncthreads(); 34 | int _lc=lc; 35 | for (int k=threadIdx.x;k>>(b,n,m,xyz1,xyz2,match); 94 | } 95 | __global__ void matchcost(int b,int n,int m,const float * __restrict__ xyz1,const float * __restrict__ xyz2,const float * __restrict__ match,float * __restrict__ out){ 96 | __shared__ float allsum[512]; 97 | const int Block=256; 98 | __shared__ float buf[Block*3]; 99 | for (int i=blockIdx.x;i>>(b,n,m,xyz1,xyz2,match,out); 138 | } 139 | __global__ void matchcostgrad(int b,int n,int m,const float * __restrict__ xyz1,const float * __restrict__ xyz2,const float * __restrict__ match,float * grad2){ 140 | __shared__ float sum_grad[256*3]; 141 | for (int i=blockIdx.x;i>>(b,n,m,xyz1,xyz2,match,grad2); 182 | } 183 | 184 | -------------------------------------------------------------------------------- /pointnet_plusplus_encoder.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on February 4, 2017 3 | 4 | @author: optas 5 | 6 | ''' 7 | 8 | import tensorflow as tf 9 | import numpy as np 10 | import warnings 11 | 12 | from tflearn.layers.core import fully_connected, dropout 13 | from tflearn.layers.conv import conv_1d, avg_pool_1d 14 | from tflearn.layers.normalization import batch_normalization 15 | from tflearn.layers.core import fully_connected, dropout 16 | 17 | 18 | import os 19 | import sys 20 | import collections 21 | 22 | BASE_DIR = os.path.dirname(__file__) 23 | sys.path.append(BASE_DIR) 24 | sys.path.append(BASE_DIR + "/pointnet_plusplus/utils") 25 | sys.path.append(BASE_DIR + "/pointnet_plusplus/tf_ops") 26 | sys.path.append(BASE_DIR + "/pointnet_plusplus/tf_ops/3d_interpolation") 27 | sys.path.append(BASE_DIR + "/pointnet_plusplus/tf_ops/grouping") 28 | sys.path.append(BASE_DIR + "/pointnet_plusplus/tf_ops/sampling") 29 | from pointnet_util import pointnet_sa_module, pointnet_fp_module 30 | 31 | 32 | def getEncoder_oneBranch_local(partPoints_input, dis2Joint, NumOfPts, is_training, reuse, scope_predix="part_1", verbose=True,bn_decay=None): 33 | 34 | scname = scope_predix+"_pointNetPP_encoder" 35 | with tf.variable_scope( scname ) as sc: 36 | if reuse: 37 | sc.reuse_variables() 38 | 39 | is_training = tf.constant(is_training, dtype=tf.bool) 40 | 41 | 42 | l0_xyz = partPoints_input 43 | l0_points = None 44 | 45 | 46 | print( "partPoints_input.shape = ", partPoints_input.shape ) 47 | if partPoints_input.shape[2] == 6: 48 | l0_xyz = partPoints_input[:,:, 0:3] 49 | l0_points = partPoints_input[:,:, 3:6] 50 | 51 | 52 | 53 | # assume self.shapeBatchSize==1 54 | inputDims = tf.reduce_max(l0_xyz , axis=[0, 1] ) - tf.reduce_min( l0_xyz , axis=[0, 1] ) 55 | print( "inputDims.shape = ",inputDims.shape ) 56 | does_part_exist = tf.dtypes.cast( tf.reduce_mean( tf.abs(inputDims) ) > 0.01, tf.float32 ) 57 | 58 | 59 | # Set Abstraction layers 60 | l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=256, radius=0.05, nsample=128, 61 | mlp=[32, 32, 64], mlp2=None, group_all=False, 62 | is_training=is_training, bn_decay=bn_decay, scope='layer1', bn=False) 63 | 64 | l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=128, radius=0.1, nsample=128, 65 | mlp=[64, 64, 128], mlp2=None, group_all=False, 66 | is_training=is_training, bn_decay=bn_decay, scope='layer2', bn=False) 67 | 68 | l4_xyz, l4_points, l4_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=None, radius=None, nsample=None, 69 | mlp=[128, 128, 128], mlp2=None, group_all=True, 70 | is_training=is_training, bn_decay=bn_decay, scope='layerxxx', bn=False) 71 | 72 | 73 | output_4 = tf.reshape(l4_points, [l0_xyz.shape[0], 128] ) 74 | 75 | 76 | print(('output_4.shape = %s', output_4.shape)) 77 | 78 | return output_4 * does_part_exist 79 | 80 | 81 | 82 | def getEncoder_oneBranch(partPoints_input, dis2Joint, Sigma, is_training, reuse, scope_predix="part_1", verbose=True,bn_decay=None): 83 | 84 | scname = scope_predix+"_pointNetPP_encoder" 85 | with tf.variable_scope( scname ) as sc: 86 | if reuse: 87 | sc.reuse_variables() 88 | 89 | is_training = tf.constant(is_training, dtype=tf.bool) 90 | 91 | 92 | l0_xyz = partPoints_input 93 | l0_points = None 94 | 95 | 96 | print( "partPoints_input.shape = ", partPoints_input.shape ) 97 | if partPoints_input.shape[2] == 6: 98 | l0_xyz = partPoints_input[:,:, 0:3] 99 | l0_points = partPoints_input[:,:, 3:6] 100 | 101 | 102 | # assume self.shapeBatchSize==1 103 | inputDims = tf.reduce_max(l0_xyz , axis=[0, 1] ) - tf.reduce_min( l0_xyz , axis=[0, 1] ) 104 | print( "inputDims.shape = ",inputDims.shape ) 105 | does_part_exist = tf.dtypes.cast( tf.reduce_mean( tf.abs(inputDims) ) > 0.01, tf.float32 ) 106 | 107 | 108 | # Set Abstraction layers 109 | l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=256, radius=0.1, nsample=128, 110 | mlp=[64, 64, 128], mlp2=None, group_all=False, 111 | is_training=is_training, bn_decay=bn_decay, scope='layer1', bn=False) 112 | 113 | l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=128, radius=0.2, nsample=128, 114 | mlp=[128, 128, 128], mlp2=None, group_all=False, 115 | is_training=is_training, bn_decay=bn_decay, scope='layer2', bn=False) 116 | 117 | l4_xyz, l4_points, l4_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=None, radius=None, nsample=None, 118 | mlp=[128, 128, 128], mlp2=None, group_all=True, 119 | is_training=is_training, bn_decay=bn_decay, scope='layerxxx', bn=False) 120 | 121 | 122 | output_4 = tf.reshape(l4_points, [l0_xyz.shape[0], 128] ) 123 | 124 | 125 | print(('output_4.shape = %s', output_4.shape)) 126 | 127 | return output_4 * does_part_exist 128 | 129 | 130 | 131 | def get_pointNet_code_of_singlePart(partPoints_input, dis2Joint, is_training, reuse, scope_predix="part_1", verbose=True, bn_decay=None): 132 | 133 | 134 | if len(partPoints_input.shape)==2: 135 | partPoints_input = tf.expand_dims(partPoints_input, 0) 136 | 137 | partPoints_input_local = partPoints_input[:, :512, :] 138 | 139 | latent_code_1 = getEncoder_oneBranch_local( partPoints_input_local , None, 512, is_training, reuse, scope_predix+"_B1", verbose, bn_decay) 140 | latent_code_2 = getEncoder_oneBranch( partPoints_input , None, 2048, is_training, reuse, scope_predix+"_B2", verbose, bn_decay) 141 | 142 | latent_code_12 = tf.concat([latent_code_1, latent_code_2], axis=1 ) 143 | 144 | return latent_code_12 145 | 146 | -------------------------------------------------------------------------------- /poisson-blending/blend/poisson_blend.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | from utils import * 4 | 5 | 6 | parser = argparse.ArgumentParser() 7 | parser.add_argument("idx", type=int) 8 | parser.add_argument("total", type=int) 9 | args = parser.parse_args() 10 | 11 | 12 | share_id = args.idx 13 | share_total = args.total 14 | 15 | jjj = 50 # the test-time optimization steps 16 | total_num = 1000 # total number of output shapes 17 | 18 | 19 | aligned_part_dir = "/local-scratch/results/chair/test_res_PWarp_overall_Epoch200_diffshapes_JS-128-120-0.002-0.0001" 20 | original_part_dir = "/local-scratch/shapenet_part_seg/chair/part_mesh0050" 21 | gen_joint_dir = aligned_part_dir 22 | 23 | 24 | part_name_list = ["12_back", "13_seat", "14_leg", "15_arm"] 25 | #part_names = ["1_handle", "2_body"] 26 | #part_names = ["1_body", "2_wing", "3_tail", "4_engine"] 27 | 28 | 29 | 30 | 31 | 32 | output_dir = "output_mesh" 33 | if not os.path.exists(output_dir): 34 | os.makedirs(output_dir) 35 | 36 | for kkk in range(share_id,total_num,share_total): 37 | try: 38 | print("--------------",kkk) 39 | src_txt_dir = aligned_part_dir+"/"+str(kkk)+"_"+str(jjj)+"/"+str(kkk)+".name.txt" 40 | if not os.path.exists(src_txt_dir): continue 41 | src_txt = open(src_txt_dir) 42 | src_part_names = [tmp.strip() for tmp in src_txt.readlines()] 43 | src_txt.close() 44 | 45 | ply_save_dir = output_dir+"/"+str(kkk)+"_"+str(jjj) 46 | if not os.path.exists(ply_save_dir): 47 | os.makedirs(ply_save_dir) 48 | 49 | #read joint 50 | joint_dir = gen_joint_dir+"/"+str(kkk)+".out."+str(jjj)+".ply" 51 | joint_v, joint_t = read_ply_triangle(joint_dir) #vertices and triangles of the joint mesh 52 | joint_p = compute_plane_for_each_triangle(joint_v, joint_t) #the plane parameters (abcd so that ax+by+cz+d=0) for each triangle 53 | joint_map_v2t = compute_mapping_vertex_to_triangles(joint_v, joint_t) #obtain a list storing: for a query vertex, which triangles are using it. 54 | joint_vn = compute_vertex_normal(joint_v, joint_t, joint_p, joint_map_v2t) #the vertex normals for joint vertices 55 | 56 | #gather edges 57 | all_v = [] #to store all vertices of the eroded parts 58 | all_t = [] #to store all triangles of the eroded parts 59 | all_loop_e = [] #to store vertices of the erosion boundaries of all parts 60 | all_loop_vn = [] #to store normals of the vertices of the erosion boundaries 61 | all_v_count = 0 62 | all_v_count_list = [all_v_count] 63 | for j in range(len(part_name_list)): 64 | edge_vertices_dir = aligned_part_dir+"/"+str(kkk)+"_"+str(jjj)+"/"+part_name_list[j]+".ply" 65 | edge_edges_dir = original_part_dir+"/"+src_part_names[j]+"/"+part_name_list[j]+"_edge.ply" 66 | if os.path.exists(edge_vertices_dir) and os.path.exists(edge_edges_dir): 67 | v,t = read_ply_triangle(edge_vertices_dir) 68 | _,e = read_ply_edge(edge_edges_dir) 69 | 70 | #important: edges need to form loops 71 | loop_e, v_use_flag = find_loops(v,e) 72 | loop_vn = compute_vertex_normal_for_masked_vertices(v, t, v_use_flag) 73 | print(len(loop_e)) 74 | #uncomment below to output discovered erosion boundaries (edges and loops) 75 | #####write_ply_edge(ply_save_dir+"/"+part_name_list[j]+".edge.ply",v,e) 76 | #####write_ply_edgeloop(ply_save_dir+"/"+part_name_list[j]+".loop.ply",loop_vn,loop_e) 77 | 78 | all_v.append(v) 79 | all_t.append(t) 80 | all_loop_vn.append(loop_vn) 81 | all_loop_e.append(loop_e) 82 | all_v_count += len(v) 83 | all_v_count_list.append(all_v_count) 84 | 85 | corresponding_loop_e = [] #store corresponding vertices on the joint mesh 86 | corresponding_vertices = [] #store corresponding vertices on the parts (actually, on the erosion boundaries) 87 | seam_t_all = [] #store triangles to fill the seams between the joint mesh and the parts 88 | for j in range(len(all_v)): 89 | loop_vn = all_loop_vn[j] 90 | loop_e = all_loop_e[j] 91 | all_v_count = all_v_count_list[j] 92 | all_v_count_last = all_v_count_list[-1] 93 | 94 | #find correspondence 95 | cle, cvv, seam_t = find_loop_correspondence_and_fill_seam(loop_vn,loop_e,joint_vn,joint_t,joint_map_v2t) 96 | #####write_ply_edgeloop(ply_save_dir+"/"+part_name_list[j]+".cloop.ply", joint_v, cle) 97 | corresponding_loop_e += cle 98 | corresponding_vertices += cvv 99 | 100 | #correct vertex indices in seam triangles 101 | for ii in range(len(seam_t)): 102 | for jj in range(len(seam_t[ii])): 103 | for kk in range(3): 104 | if seam_t[ii][jj][kk]<0: 105 | seam_t[ii][jj][kk] = all_v_count_last-seam_t[ii][jj][kk]-1 106 | else: 107 | seam_t[ii][jj][kk] = all_v_count+seam_t[ii][jj][kk] 108 | if seam_t[ii][jj][1] != seam_t[ii][jj][2]: 109 | seam_t_all.append(seam_t[ii][jj]) 110 | seam_t_all = np.array(seam_t_all,np.int32) 111 | 112 | 113 | #correct vertex indices in triangles 114 | for j in range(len(all_t)): 115 | all_t[j][:] = all_t[j][:] + all_v_count_list[j] 116 | 117 | 118 | #write combined (without joint) 119 | all_v2 = all_v 120 | all_t2 = all_t 121 | all_v2 = np.concatenate(all_v2,axis=0) 122 | all_t2 = np.concatenate(all_t2,axis=0) 123 | write_ply_triangle(ply_save_dir+"/combined_nojoint.ply", all_v2, all_t2) 124 | 125 | #write combined (with joint) 126 | all_v2 = all_v+[joint_v] 127 | all_t2 = all_t+[joint_t+all_v_count_list[-1]] 128 | all_v2 = np.concatenate(all_v2,axis=0) 129 | all_t2 = np.concatenate(all_t2,axis=0) 130 | write_ply_triangle(ply_save_dir+"/combined_beforeblend.ply", all_v2, all_t2) 131 | 132 | #filter_triangles 133 | joint_v, joint_t = filter_triangles(corresponding_loop_e, joint_v, joint_t, joint_map_v2t) 134 | if len(joint_t)==0: continue 135 | write_ply_triangle(ply_save_dir+"/joint.ply", joint_v, joint_t) 136 | 137 | 138 | #poisson blending version 1 139 | joint_v1 = np.copy(joint_v) 140 | poisson_blending(joint_v1, joint_t, corresponding_loop_e, corresponding_vertices, force_correspondence=True) 141 | 142 | #write combined 143 | all_v2 = all_v+[joint_v1] 144 | all_t2 = all_t+[joint_t+all_v_count_list[-1],seam_t_all] 145 | all_v2 = np.concatenate(all_v2,axis=0) 146 | all_t2 = np.concatenate(all_t2,axis=0) 147 | write_ply_triangle(ply_save_dir+"/combined_blended.ply", all_v2, all_t2) 148 | 149 | 150 | #poisson blending version 2 151 | joint_v2 = np.copy(joint_v) 152 | poisson_blending(joint_v2, joint_t, corresponding_loop_e, corresponding_vertices, force_correspondence=False) 153 | 154 | #write combined 155 | all_v2 = all_v+[joint_v2] 156 | all_t2 = all_t+[joint_t+all_v_count_list[-1],seam_t_all] 157 | all_v2 = np.concatenate(all_v2,axis=0) 158 | all_t2 = np.concatenate(all_t2,axis=0) 159 | write_ply_triangle(ply_save_dir+"/combined_blended_2.ply", all_v2, all_t2) 160 | 161 | except: 162 | print("ERROR!!!") 163 | -------------------------------------------------------------------------------- /poisson-blending/prepare/03797390_vox.txt: -------------------------------------------------------------------------------- 1 | 10c2b3eac377b9084b3c42e318f3affc 2 | 10f6e09036350e92b3f21f1137c3c347 3 | 128ecbc10df5b05d96eaf1340564a4de 4 | 1305b9266d38eb4d9f818dd0aa1a251 5 | 141f1db25095b16dcfb3760e4293e310 6 | 159e56c18906830278d8f8c02c47cde0 7 | 15bd6225c209a8e3654b0ce7754570c8 8 | 162201dfe14b73f0281365259d1cf342 9 | 17952a204c0a9f526c69dceb67157a66 10 | 187859d3c3a2fd23f54e1b6f41fdd78a 11 | 1a1c0a8d4bad82169f0594e65f756cf5 12 | 1a97f3c83016abca21d0de04f408950f 13 | 1ae1ba5dfb2a085247df6165146d5bbd 14 | 1bc5d303ff4d6e7e1113901b72a68e7c 15 | 1be6b2c84cdab826c043c2d07bb83fc8 16 | 1c9f9e25c654cbca3c71bf3f4dd78475 17 | 1dd8290a154f4b1534a8988fdcee4fde 18 | 1ea9ea99ac8ed233bf355ac8109b9988 19 | 1eaf8db2dd2b710c7d5b1b70ae595e60 20 | 1f035aa5fc6da0983ecac81e09b15ea9 21 | 2037531c43448c3016329cbc378d2a2 22 | 214dbcace712e49de195a69ef7c885a4 23 | 24651c3767aa5089e19f4cee87249aca 24 | 24b17537bce40695b3207096ecd79542 25 | 27119d9b2167080ec190cb14324769d 26 | 28f1e7bc572a633cb9946438ed40eeb9 27 | 2997f21fa426e18a6ab1a25d0e8f3590 28 | 2d10421716b16580e45ef4135c266a12 29 | 3093367916fb5216823323ed0e090a6f 30 | 3143a4accdc23349cac584186c95ce9b 31 | 32e197b8118b3ff6a4bd4f46ba404890 32 | 336122c3105440d193e42e2720468bf0 33 | 345d3e7252156db8d44ee24d6b5498e1 34 | 34869e23f9fdee027528ae0782b54aae 35 | 34ae0b61b0d8aaf2d7b20fded0142d7a 36 | 35ce7ede92198be2b759f7fb0032e59 37 | 37f56901a07da69dac6b8e58caf61f95 38 | 387b695db51190d3be276203d0b1a33f 39 | 39361b14ba19303ee42cfae782879837 40 | 3a7439cfaa9af51faf1af397e14a566d 41 | 3c0467f96e26b8c6a93445a1757adf6 42 | 3d1754b7cb46c0ce5c8081810641ef6 43 | 3d3e993f7baa4d7ef1ff24a8b1564a36 44 | 403fb4eb4fc6235adf0c7dbe7f8f4c8e 45 | 43e1cabc5dd2fa91fffc97a61124b1a9 46 | 43f94ba24d2f075c4d32a65fb7bf4ebc 47 | 46955fddcc83a50f79b586547e543694 48 | 46ed9dad0440c043d33646b0990bb4a 49 | 4815b8a6406494662a96924bce6ef687 50 | 48e260a614c0fd4434a8988fdcee4fde 51 | 4b7888feea81219ab5f4a9188bfa0ef6 52 | 4b8b10d03552e0891898dfa8eb8eefff 53 | 4d9764afa3fbeb1b6c69dceb67157a66 54 | 513c3410e8354e5211c7f3807925346a 55 | 52273f4b17505e898ef19a48ac4fcfdf 56 | 5310945bb21d74a41fabf3cbd0fc77bc 57 | 546648204a20b712dfb0e477a80dcc95 58 | 54f2d6a0b431839c99785666a0fe0255 59 | 5582a89be131867846ebf4f1147c3f0f 60 | 57f73714cbc425e44ae022a8f6e258a7 61 | 586e67c53f181dc22adf8abaa25e0215 62 | 599e604a8265cc0a98765d8aa3638e70 63 | 5b0c679eb8a2156c4314179664d18101 64 | 5c48d471200d2bf16e8a121e6886e18d 65 | 5c7c4cb503a757147dbda56eabff0c47 66 | 5d72df6bc7e93e6dd0cd466c08863ebd 67 | 5fe74baba21bba7ca4eec1b19b3a18f8 68 | 604fcae9d93201d9d7f470ee20dce9e0 69 | 61c10dccfa8e508e2d66cbf6a91063 70 | 62684ad0321b35189a3501eead248b52 71 | 633379db14d4d2b287dd60af81c93a3c 72 | 639a1f7d09d23ea37d70172a29ade99a 73 | 642eb7c42ebedabd223d193f5a188983 74 | 645b0e2ef3b95979204df312eabf367f 75 | 64a9d9f6774973ebc598d38a6a69ad2 76 | 6500ccc65e210b14d829190312080ea3 77 | 6661c0b9b9b8450c4ee002d643e7b29e 78 | 67b9abb424cf22a22d7082a28b056a5 79 | 6c04c2eac973936523c841f9d5051936 80 | 6c379385bf0a23ffdec712af445786fe 81 | 6c5ec193434326fd6fa82390eb12174f 82 | 6dd59cc1130a426571215a0b56898e5e 83 | 6faf1f04bde838e477f883dde7397db2 84 | 71995893d717598c9de7b195ccfa970 85 | 71ca4fc9c8c29fa8d5abaf84513415a2 86 | 7223820f07fd6b55e453535335057818 87 | 7374ea7fee07f94c86032c4825f3450 88 | 73b8b6456221f4ea20d3c05c08e26f 89 | 79e673336e836d1333becb3a9550cbb1 90 | 7a8ea24474846c5c2f23d8349a133d2b 91 | 7d282cc3cedd40c8b5c4f4801d3aada 92 | 7d6baadd51d0703455da767dfc5b748e 93 | 8012f52dd0a4d2f718a93a45bf780820 94 | 83827973c79ca7631c9ec1e03e401f54 95 | 83b41d719ea5af3f4dcd1df0d0a62a93 96 | 8570d9a8d24cb0acbebd3c0c0c70fb03 97 | 85a2511c375b5b32f72755048bac3f96 98 | 896f1d494bac0ebcdec712af445786fe 99 | 89bd0dff1b386ebed6b30d74fff98ffd 100 | 8b1dca1414ba88cb91986c63a4d7a99a 101 | 8b780e521c906eaf95a4f7ae0be930ac 102 | 8f6c86feaa74698d5c91ee20ade72edc 103 | 9196f53a0d4be2806ffeedd41ba624d6 104 | 91f90c3a50410c0dc27effd6fd6b7eb0 105 | 9278005254c8db7e95f577622f465c85 106 | 928a383f79698c3fb6d9bc28c8d8a2c4 107 | 92d6394732e6058d4bcbafcc905a9b98 108 | 9426e7aa67c83a4c3b51ab46b2f98f30 109 | 962883677a586bd84a60c1a189046dd1 110 | 9737c77d3263062b8ca7a0a01bcd55b6 111 | 9880097f723c98a9bd8c6965c4665b41 112 | 9961ccbafd59cb03fe36eb2ab5fa00e0 113 | 99eaa69cf6fe8811dec712af445786fe 114 | 9af98540f45411467246665d3d3724c 115 | 9d8c711750a73b06ad1d789f3b2120d0 116 | 9fc96d41ec7a66a6a159545213d74ea 117 | 9ff8400080c77feac2ad6fd1941624c3 118 | a0c78f254b037f88933dc172307a6bb9 119 | a1d293f5cc20d01ad7f470ee20dce9e0 120 | a3cd44bbd3ba5b019a4cbf5d3b79df06 121 | a637500654ca8d16c97cfc3e8a6b1d16 122 | a6d9f9ae39728831808951ff5fb582ac 123 | a8f7a0edd3edc3299e54b4084dc33544 124 | b46e89995f4f9cc5161e440f04bd2a2 125 | b4ae56d6638d5338de671f28c83d2dcb 126 | b6f30c63c946c286cf6897d8875cfd5e 127 | b7841572364fd9ce1249ffc39a0c3c0b 128 | b7e705de46ebdcc14af54ba5738cb1c5 129 | b811555ccf5ef6c4948fa2daa427fe1f 130 | b815d7e084a5a75b8d543d7713b96a41 131 | b88bcf33f25c6cb15b4f129f868dedb 132 | b98fa11a567f644344b25d683fe71de 133 | b9be7cfe653740eb7633a2dd89cec754 134 | bcb6be8f0ff4a51872e526c4f21dfca4 135 | bea77759a3e5f9037ae0031c221d81a4 136 | bed29baf625ce9145b68309557f3a78c 137 | c0c130c04edabc657c2b66248f91b3d8 138 | c2eacc521dd65bf7a1c742bb4ffef210 139 | c34718bd10e378186c6c61abcbd83e5a 140 | c51b79493419eccdc1584fff35347dc6 141 | c60f62684618cb52a4136492f17b9a59 142 | c6b24bf0a011b100d536be1f5e11c560 143 | c6bc2c9770a59b5ddd195661813efe58 144 | c7ddd93b15e30faae180a52fd2be32 145 | c7f8d39c406fee941050b055aafa6fb8 146 | c82b9f1b98f044fc15cf6e5ad80f2da 147 | ca198dc3f7dc0cacec6338171298c66b 148 | cc5b14ef71e87e9165ba97214ebde03 149 | cf777e14ca2c7a19b4aad3cc5ce7ee8 150 | d0a3fdd33c7e1eb040bc4e38b9ba163e 151 | d309d5f8038df4121198791a5b8655c 152 | d32cd77c6630b77de47c0353c18d58e 153 | d38295b8d83e8cdec712af445786fe 154 | d46b98f63a017578ea456f4bbbc96af9 155 | d7ba704184d424dfd56d9106430c3fe 156 | daee5cf285b8d210eeb8d422649e5f2b 157 | dcec634f18e12427c2c72e575af174cd 158 | df026976dc03197213ac44947b92716e 159 | dfa8a3a0c8a552b62bc8a44b22fcb3b9 160 | e16a895052da87277f58c33b328479f4 161 | e363fa24c824d20ca363b55cbd344baa 162 | e6dedae946ff5265a95fb60c110b25aa 163 | e71102b6da1d63f3a363b55cbd344baa 164 | e9499e4a9f632725d6e865157050a80e 165 | e94e46bc5833f2f5e57b873e4f3ef3a4 166 | e984fd7e97c2be347eaeab1f0c9120b7 167 | e9bd4ee553eb35c1d5ccc40b510e4bd 168 | ea127b5b9ba0696967699ff4ba91a25 169 | ea33ad442b032208d778b73d04298f62 170 | ea95f7b57ff1573b9469314c979caef4 171 | ec846432f3ebedf0a6f32a8797e3b9e9 172 | edaf960fb6afdadc4cebc4b5998de5d0 173 | eecb13f61a93b4048f58d8b19de93f99 174 | ef24c302911bcde6ea6ff2182dd34668 175 | f09e51579600cfbb88b651d2e4ea0846 176 | f1866a48c2fc17f85b2ecd212557fda0 177 | f1e439307b834015770a0ff1161fa15a 178 | f23a544c04e2f5ccb50d0c6a0c254040 179 | f42a9784d165ad2f5e723252788c3d6e 180 | f626192a5930d6c712f0124e8fa3930b 181 | f7d776fd68b126f23b67070c4a034f08 182 | f99e19b8c4a729353deb88581ea8417a 183 | fad118b32085f3f2c2c72e575af174cd 184 | ff1a44e1c1785d618bca309f2c51966a 185 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/sampling/tf_sampling_g.cu: -------------------------------------------------------------------------------- 1 | /* Furthest point sampling GPU implementation 2 | * Original author: Haoqiang Fan 3 | * Modified by Charles R. Qi 4 | * All Rights Reserved. 2017. 5 | */ 6 | 7 | __global__ void cumsumKernel(int b,int n,const float * __restrict__ inp,float * __restrict__ out){ 8 | const int BlockSize=2048; 9 | const int paddingLevel=5; 10 | __shared__ float buffer4[BlockSize*4]; 11 | __shared__ float buffer[BlockSize+(BlockSize>>paddingLevel)]; 12 | for (int i=blockIdx.x;i>2; 18 | for (int k=threadIdx.x*4;k>2)+(k>>(2+paddingLevel))]=v4; 33 | }else{ 34 | float v=0; 35 | for (int k2=k;k2>2)+(k>>(2+paddingLevel))]=v; 43 | } 44 | } 45 | int u=0; 46 | for (;(2<>(u+1));k+=blockDim.x){ 49 | int i1=(((k<<1)+2)<>paddingLevel; 52 | i2+=i2>>paddingLevel; 53 | buffer[i1]+=buffer[i2]; 54 | } 55 | } 56 | u--; 57 | for (;u>=0;u--){ 58 | __syncthreads(); 59 | for (int k=threadIdx.x;k>(u+1));k+=blockDim.x){ 60 | int i1=(((k<<1)+3)<>paddingLevel; 63 | i2+=i2>>paddingLevel; 64 | buffer[i1]+=buffer[i2]; 65 | } 66 | } 67 | __syncthreads(); 68 | for (int k=threadIdx.x*4;k>2)-1)+(((k>>2)-1)>>paddingLevel); 71 | buffer4[k]+=buffer[k2]; 72 | buffer4[k+1]+=buffer[k2]; 73 | buffer4[k+2]+=buffer[k2]; 74 | buffer4[k+3]+=buffer[k2]; 75 | } 76 | } 77 | __syncthreads(); 78 | for (int k=threadIdx.x;k>paddingLevel)]+runningsum2; 82 | float r2=runningsum+t; 83 | runningsum2=t-(r2-runningsum); 84 | runningsum=r2; 85 | __syncthreads(); 86 | } 87 | } 88 | } 89 | 90 | __global__ void binarysearchKernel(int b,int n,int m,const float * __restrict__ dataset,const float * __restrict__ query, int * __restrict__ result){ 91 | int base=1; 92 | while (base=1;k>>=1) 99 | if (r>=k && dataset[i*n+r-k]>=q) 100 | r-=k; 101 | result[i*m+j]=r; 102 | } 103 | } 104 | } 105 | __global__ void farthestpointsamplingKernel(int b,int n,int m,const float * __restrict__ dataset,float * __restrict__ temp,int * __restrict__ idxs){ 106 | if (m<=0) 107 | return; 108 | const int BlockSize=512; 109 | __shared__ float dists[BlockSize]; 110 | __shared__ int dists_i[BlockSize]; 111 | const int BufferSize=3072; 112 | __shared__ float buf[BufferSize*3]; 113 | for (int i=blockIdx.x;ibest){ 147 | best=d2; 148 | besti=k; 149 | } 150 | } 151 | dists[threadIdx.x]=best; 152 | dists_i[threadIdx.x]=besti; 153 | for (int u=0;(1<>(u+1))){ 156 | int i1=(threadIdx.x*2)<>>(b,n,inp,out); 196 | } 197 | //require b*n working space 198 | void probsampleLauncher(int b,int n,int m,const float * inp_p,const float * inp_r,float * temp,int * out){ 199 | cumsumKernel<<<32,512>>>(b,n,inp_p,temp); 200 | binarysearchKernel<<>>(b,n,m,temp,inp_r,out); 201 | } 202 | //require 32*n working space 203 | void farthestpointsamplingLauncher(int b,int n,int m,const float * inp,float * temp,int * out){ 204 | farthestpointsamplingKernel<<<32,512>>>(b,n,m,inp,temp,out); 205 | } 206 | void gatherpointLauncher(int b,int n,int m,const float * inp,const int * idx,float * out){ 207 | gatherpointKernel<<>>(b,n,m,inp,idx,out); 208 | } 209 | void scatteraddpointLauncher(int b,int n,int m,const float * out_g,const int * idx,float * inp_g){ 210 | scatteraddpointKernel<<>>(b,n,m,out_g,idx,inp_g); 211 | } 212 | 213 | -------------------------------------------------------------------------------- /latent_3d_points/structural_losses/approxmatch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | float randomf(){ 10 | return (rand()+0.5)/(RAND_MAX+1.0); 11 | } 12 | static double get_time(){ 13 | timespec tp; 14 | clock_gettime(CLOCK_MONOTONIC,&tp); 15 | return tp.tv_sec+tp.tv_nsec*1e-9; 16 | } 17 | void approxmatch_cpu(int b,int n,int m,float * xyz1,float * xyz2,float * match){ 18 | for (int i=0;i saturatedl(n,double(factorl)),saturatedr(m,double(factorr)); 22 | vector weight(n*m); 23 | for (int j=0;j=-2;j--){ 26 | //printf("i=%d j=%d\n",i,j); 27 | double level=-powf(4.0,j); 28 | if (j==-2) 29 | level=0; 30 | for (int k=0;k ss(m,1e-9); 42 | for (int k=0;k ss2(m,0); 59 | for (int k=0;k1){ 154 | printf("bad i=%d j=%d k=%d u=%f\n",i,j,k,u); 155 | } 156 | s+=u; 157 | } 158 | if (s<0.999 || s>1.001){ 159 | printf("bad i=%d j=%d s=%f\n",i,j,s); 160 | } 161 | } 162 | for (int j=0;j4.001){ 168 | printf("bad i=%d j=%d s=%f\n",i,j,s); 169 | } 170 | } 171 | }*/ 172 | /*for (int j=0;j1e-3) 222 | if (fabs(double(match[i*n*m+k*n+j]-match_cpu[i*n*m+j*m+k]))>1e-2){ 223 | printf("i %d j %d k %d m %f %f\n",i,j,k,match[i*n*m+k*n+j],match_cpu[i*n*m+j*m+k]); 224 | flag=false; 225 | break; 226 | } 227 | //emax=max(emax,fabs(double(match[i*n*m+k*n+j]-match_cpu[i*n*m+j*m+k]))); 228 | emax+=fabs(double(match[i*n*m+k*n+j]-match_cpu[i*n*m+j*m+k])); 229 | } 230 | } 231 | printf("emax_match=%f\n",emax/2/n/m); 232 | emax=0; 233 | for (int i=0;i<2;i++) 234 | emax+=fabs(double(cost[i]-cost_cpu[i])); 235 | printf("emax_cost=%f\n",emax/2); 236 | emax=0; 237 | for (int i=0;i<2*m*3;i++) 238 | emax+=fabs(double(grad[i]-grad_cpu[i])); 239 | //for (int i=0;i<3*m;i++){ 240 | //if (grad[i]!=0) 241 | //printf("i %d %f %f\n",i,grad[i],grad_cpu[i]); 242 | //} 243 | printf("emax_grad=%f\n",emax/(2*m*3)); 244 | 245 | cudaFree(xyz1_g); 246 | cudaFree(xyz2_g); 247 | cudaFree(match_g); 248 | cudaFree(cost_g); 249 | cudaFree(grad_g); 250 | 251 | return 0; 252 | } 253 | 254 | -------------------------------------------------------------------------------- /poisson-blending/prepare/get_part_mesh.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | import math 4 | import argparse 5 | from utils import * 6 | 7 | parser = argparse.ArgumentParser() 8 | parser.add_argument("idx", type=int) 9 | parser.add_argument("total", type=int) 10 | args = parser.parse_args() 11 | 12 | 13 | predefined_category = "chair" # "chair", "mug", "airplane" 14 | 15 | if predefined_category=="chair": 16 | in_obj_dir = "../reoriented-03797390-obj/" #the folder storing the meshes 17 | ref_txt_dir = "../03001627_vox.txt" #the list storing the names of the shapes 18 | ref_ply_dir = "../03001627_parts2048_ply_eroded0.05_withnormal/" #the folder storing the ground truth point cloud segmentations 19 | out_part_dir = "../part_mesh0050/" #the output folder 20 | 21 | #12 Chair 03001627 1 back 22 | #13 Chair 03001627 2 seat 23 | #14 Chair 03001627 3 leg 24 | #15 Chair 03001627 4 arm 25 | part_names = ["12_back", "13_seat", "14_leg", "15_arm"] 26 | part_list = [1,2,3,4] 27 | part_num = len(part_list) 28 | 29 | if predefined_category=="mug": 30 | in_obj_dir = "../reoriented-03797390-obj/" 31 | ref_txt_dir = "../03797390_vox.txt" 32 | ref_ply_dir = "../03797390_parts2048_ply_eroded0.05_withnormal/" 33 | out_part_dir = "../part_mesh0050/" 34 | 35 | #36 Mug 03797390 1 handle 36 | #37 Mug 03797390 2 body 37 | part_names = ["1_handle", "2_body"] 38 | part_list = [1,2] 39 | part_num = len(part_list) 40 | 41 | if predefined_category=="airplane": 42 | in_obj_dir = "../reoriented-02691156-obj/" 43 | ref_txt_dir = "../02691156_vox.txt" 44 | ref_ply_dir = "../02691156_parts2048_ply_eroded0.025_withnormal/" 45 | out_part_dir = "../part_mesh0025/" 46 | 47 | #0 Airplane 02691156 1 body 48 | #1 Airplane 02691156 2 wing 49 | #2 Airplane 02691156 3 tail 50 | #3 Airplane 02691156 4 engine 51 | part_names = ["1_body", "2_wing", "3_tail", "4_engine"] 52 | part_list = [1,2,3,4] 53 | part_num = len(part_list) 54 | 55 | 56 | #read the names of the shapes 57 | txt_list_ = open(ref_txt_dir) 58 | txt_list = txt_list_.readlines() 59 | txt_list_.close() 60 | txt_list = [name.strip() for name in txt_list] 61 | txt_list = sorted(txt_list) 62 | txt_list = txt_list[int(len(txt_list)*0.8):] #only testing shapes (20%) are processed 63 | 64 | 65 | 66 | idx = args.idx 67 | total = args.total 68 | 69 | for kkk in range(idx,len(txt_list),total): #this loop processes each shape individually 70 | print(kkk,txt_list[kkk]) 71 | 72 | obj_in_name = in_obj_dir+txt_list[kkk]+".reoriented.obj" 73 | ref_txt_name = ref_ply_dir+txt_list[kkk] 74 | vertices, triangles = load_obj(obj_in_name) 75 | part_points = read_ply_and_labels(ref_txt_name, part_list) 76 | 77 | 78 | vertices = list(vertices) 79 | triangles = triangles.tolist() 80 | label_vertices = np.full([len(vertices)],-1,np.int32) 81 | label_triangles_list = np.full([part_num,len(triangles)],-1,np.int32) 82 | 83 | #now we have: 84 | #vertices, triangles: the vertices and triangles of the mesh. 85 | #part_points: the points and labels of the ground truth point cloud segmentation of that shape. 86 | 87 | #this function below will use part_points to label vertices and triangles -> label_vertices and label_triangles_list. 88 | #each mesh vertex will receive one part label, by finding the nearest neighbor in part_points. 89 | #each mesh triangle may receive one or more part labels. 90 | #for each mesh triangle, we use its 3 vertex points and we also sample some points on the triangle. 91 | #then we use nearest-neighbor to label each point, and label the triangle according to the labels of those points. 92 | #therefore the triangle may belong to one or multiple parts, depending on the labels of those points. 93 | get_face_color_multiple(vertices, triangles, part_points, label_vertices, label_triangles_list) 94 | 95 | obj_dir = out_part_dir+txt_list[kkk] 96 | if not os.path.exists(obj_dir): 97 | os.makedirs(obj_dir) 98 | 99 | 100 | for i in range(part_num): #now segment each part from the mesh individually 101 | #obtain vertices and triangles containing the part (part #i) 102 | part_vertices_, part_triangles_ = collect_part_face(vertices, triangles, label_vertices, label_triangles_list[i], i) 103 | if len(part_triangles_)==0: continue 104 | 105 | part_vertices_ = list(part_vertices_) 106 | part_triangles_ = part_triangles_.tolist() 107 | #we initialize the labels below with "-1", meaning "unknown". 108 | #The labels will be filled gradually in the subdivision below, but some "-1" may remain for triangles that need to be subdivided. 109 | label_part_vertices = [-1]*len(part_vertices_) 110 | label_part_vertices_out = [-1]*len(part_vertices_) 111 | label_part_vertices_in = [-1]*len(part_vertices_) 112 | label_part_triangles = [-1]*len(part_triangles_) 113 | 114 | #the while loop below will subdivide the part mesh at most 5 times and stop when the number of triangles is 40000 or more. 115 | #note that only triangles close to the erosion boundary is subdivided. 116 | #The erosion radius is hard-coded in utils.py, explained below. You will need to change it if you prefer a different value. 117 | #erode_threshold: the erosion radius 118 | #erode_threshold_in: the radius used to determine which triangles to subdivide. it should be smaller than erode_threshold. 119 | #erode_threshold_out: the radius used to determine which triangles to subdivide. it should be larger than erode_threshold. 120 | #triangles that have vertices falling into [erode_threshold_in,erode_threshold_out) will be subdivided. 121 | itrc = 0 122 | while itrc<5 and len(part_triangles_)<40000: 123 | #fill in label_part_vertices, label_part_vertices_out, label_part_vertices_in, label_part_triangles 124 | get_face_color(part_vertices_, part_triangles_, part_points, label_part_vertices, label_part_vertices_out, label_part_vertices_in, label_part_triangles) 125 | print("part-"+part_names[i]) 126 | print("subdiv-"+str(itrc)) 127 | print("before:", len(part_vertices_), len(part_triangles_)) 128 | #subdivide the part mesh using midpoint. only triangles close to the erosion boundary is subdivided. 129 | adaptive_subdiv_according_to_color_mid(part_vertices_, part_triangles_, part_points, label_part_vertices, label_part_vertices_out, label_part_vertices_in, label_part_triangles) 130 | print("after:", len(part_vertices_), len(part_triangles_)) 131 | itrc += 1 132 | 133 | #fill in label_part_vertices and label_part_triangles before the final subdivision 134 | label_part_triangles = [-1]*len(part_triangles_) 135 | get_face_color_no_tolerance(part_vertices_, part_triangles_, part_points, label_part_vertices, label_part_triangles) 136 | 137 | print("subdiv-final") 138 | print("before:", len(part_vertices_), len(part_triangles_)) 139 | #final subdivision. instead of midpoint, we use the actual erosion boundary point to be more accurate 140 | adaptive_subdiv_according_to_color_boundary(part_vertices_, part_triangles_, part_points, label_part_vertices, label_part_triangles) 141 | print("after:", len(part_vertices_), len(part_triangles_)) 142 | 143 | #fill in label_part_vertices and label_part_triangles. this time, "-1" is not allowed. 144 | force_assign_face_color(part_vertices_, part_triangles_, part_points, label_part_vertices, label_part_triangles) 145 | 146 | #collect vertices, triangles, and erosion-boundary edges of the eroded part. useless vertices and triangles are removed. 147 | part_vertices, part_triangles, part_edges = collect_part_face_and_edge(part_vertices_, part_triangles_, label_part_vertices, label_part_triangles, i) 148 | if len(part_triangles)>0: 149 | part_dir = obj_dir+"/"+part_names[i]+".ply" 150 | write_ply_triangle(part_dir, part_vertices, part_triangles) 151 | part_edge_dir = obj_dir+"/"+part_names[i]+"_edge.ply" 152 | write_ply_edge(part_edge_dir, part_vertices, part_edges) 153 | 154 | #find loops 155 | #loop_e, _ = find_loops(part_vertices,part_edges) 156 | #part_loop_dir = obj_dir+"/"+part_names[i]+"_loop.ply" 157 | #write_ply_edgeloop(part_loop_dir,part_vertices,loop_e) 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /pointnet_plusplus/tf_ops/sampling/tf_sampling.cpp: -------------------------------------------------------------------------------- 1 | /* Furthest point sampling 2 | * Original author: Haoqiang Fan 3 | * Modified by Charles R. Qi 4 | * All Rights Reserved. 2017. 5 | */ 6 | #include "tensorflow/core/framework/op.h" 7 | #include "tensorflow/core/framework/op_kernel.h" 8 | #include "tensorflow/core/framework/shape_inference.h" 9 | #include "tensorflow/core/framework/common_shape_fns.h" 10 | #include 11 | 12 | using namespace tensorflow; 13 | 14 | REGISTER_OP("ProbSample") 15 | .Input("inp: float32") 16 | .Input("inpr: float32") 17 | .Output("out: int32") 18 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 19 | ::tensorflow::shape_inference::ShapeHandle dims1; // batch_size * ncategory 20 | c->WithRank(c->input(0), 2, &dims1); 21 | ::tensorflow::shape_inference::ShapeHandle dims2; // batch_size * npoints 22 | c->WithRank(c->input(1), 2, &dims2); 23 | // batch_size * npoints 24 | ::tensorflow::shape_inference::ShapeHandle output = c->MakeShape({c->Dim(dims2, 0), c->Dim(dims2, 1)}); 25 | c->set_output(0, output); 26 | return Status::OK(); 27 | }); 28 | REGISTER_OP("FarthestPointSample") 29 | .Attr("npoint: int") 30 | .Input("inp: float32") 31 | .Output("out: int32") 32 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 33 | ::tensorflow::shape_inference::ShapeHandle dims1; // batch_size * npoint * 3 34 | c->WithRank(c->input(0), 3, &dims1); 35 | int npoint; 36 | TF_RETURN_IF_ERROR(c->GetAttr("npoint", &npoint)); 37 | ::tensorflow::shape_inference::ShapeHandle output = c->MakeShape({c->Dim(dims1, 0), npoint}); 38 | c->set_output(0, output); 39 | return Status::OK(); 40 | }); 41 | REGISTER_OP("GatherPoint") 42 | .Input("inp: float32") 43 | .Input("idx: int32") 44 | .Output("out: float32") 45 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 46 | ::tensorflow::shape_inference::ShapeHandle dims1; // batch_size * ndataset * 3 47 | c->WithRank(c->input(0), 3, &dims1); 48 | ::tensorflow::shape_inference::ShapeHandle dims2; // batch_size * npoints 49 | c->WithRank(c->input(1), 2, &dims2); 50 | // batch_size * npoints * 3 51 | ::tensorflow::shape_inference::ShapeHandle output = c->MakeShape({c->Dim(dims1, 0), c->Dim(dims2, 1), c->Dim(dims1, 2)}); 52 | c->set_output(0, output); 53 | return Status::OK(); 54 | }); 55 | REGISTER_OP("GatherPointGrad") 56 | .Input("inp: float32") 57 | .Input("idx: int32") 58 | .Input("out_g: float32") 59 | .Output("inp_g: float32") 60 | .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 61 | c->set_output(0, c->input(0)); 62 | return Status::OK(); 63 | }); 64 | 65 | void probsampleLauncher(int b,int n,int m,const float * inp_p,const float * inp_r,float * temp,int * out); 66 | class ProbSampleGpuOp: public OpKernel{ 67 | public: 68 | explicit ProbSampleGpuOp(OpKernelConstruction* context):OpKernel(context){} 69 | void Compute(OpKernelContext * context)override{ 70 | const Tensor& inp_tensor=context->input(0); 71 | const Tensor& inpr_tensor=context->input(1); 72 | auto inp_flat=inp_tensor.flat(); 73 | auto inpr_flat=inpr_tensor.flat(); 74 | const float * inp=&(inp_flat(0)); 75 | const float * inpr=&(inpr_flat(0)); 76 | OP_REQUIRES(context,inp_tensor.dims()==2,errors::InvalidArgument("ProbSample expects (batch_size,num_choices) inp shape")); 77 | int b=inp_tensor.shape().dim_size(0); 78 | int n=inp_tensor.shape().dim_size(1); 79 | OP_REQUIRES(context,inpr_tensor.dims()==2 && inpr_tensor.shape().dim_size(0)==b,errors::InvalidArgument("ProbSample expects (batch_size,num_points) inpr shape")); 80 | int m=inpr_tensor.shape().dim_size(1); 81 | Tensor * out_tensor=NULL; 82 | OP_REQUIRES_OK(context,context->allocate_output(0,TensorShape{b,m},&out_tensor)); 83 | auto out_flat=out_tensor->flat(); 84 | int * out=&(out_flat(0)); 85 | Tensor temp_tensor; 86 | OP_REQUIRES_OK(context,context->allocate_temp(DataTypeToEnum::value,TensorShape{b,n},&temp_tensor)); 87 | auto temp_flat=temp_tensor.flat(); 88 | float * temp=&(temp_flat(0)); 89 | probsampleLauncher(b,n,m,inp,inpr,temp,out); 90 | } 91 | }; 92 | REGISTER_KERNEL_BUILDER(Name("ProbSample").Device(DEVICE_GPU), ProbSampleGpuOp); 93 | 94 | void farthestpointsamplingLauncher(int b,int n,int m,const float * inp,float * temp,int * out); 95 | class FarthestPointSampleGpuOp: public OpKernel{ 96 | public: 97 | explicit FarthestPointSampleGpuOp(OpKernelConstruction* context):OpKernel(context) { 98 | OP_REQUIRES_OK(context, context->GetAttr("npoint", &npoint_)); 99 | OP_REQUIRES(context, npoint_ > 0, errors::InvalidArgument("FarthestPointSample expects positive npoint")); 100 | } 101 | void Compute(OpKernelContext * context)override{ 102 | int m = npoint_; 103 | 104 | const Tensor& inp_tensor=context->input(0); 105 | OP_REQUIRES(context,inp_tensor.dims()==3 && inp_tensor.shape().dim_size(2)==3,errors::InvalidArgument("FarthestPointSample expects (batch_size,num_points,3) inp shape")); 106 | int b=inp_tensor.shape().dim_size(0); 107 | int n=inp_tensor.shape().dim_size(1); 108 | auto inp_flat=inp_tensor.flat(); 109 | const float * inp=&(inp_flat(0)); 110 | Tensor * out_tensor; 111 | OP_REQUIRES_OK(context,context->allocate_output(0,TensorShape{b,m},&out_tensor)); 112 | auto out_flat=out_tensor->flat(); 113 | int * out=&(out_flat(0)); 114 | Tensor temp_tensor; 115 | OP_REQUIRES_OK(context,context->allocate_temp(DataTypeToEnum::value,TensorShape{32,n},&temp_tensor)); 116 | auto temp_flat=temp_tensor.flat(); 117 | float * temp=&(temp_flat(0)); 118 | farthestpointsamplingLauncher(b,n,m,inp,temp,out); 119 | } 120 | private: 121 | int npoint_; 122 | }; 123 | REGISTER_KERNEL_BUILDER(Name("FarthestPointSample").Device(DEVICE_GPU),FarthestPointSampleGpuOp); 124 | 125 | void gatherpointLauncher(int b,int n,int m,const float * inp,const int * idx,float * out); 126 | class GatherPointGpuOp: public OpKernel{ 127 | public: 128 | explicit GatherPointGpuOp(OpKernelConstruction * context):OpKernel(context){} 129 | void Compute(OpKernelContext * context)override{ 130 | const Tensor& inp_tensor=context->input(0); 131 | OP_REQUIRES(context,inp_tensor.dims()==3 && inp_tensor.shape().dim_size(2)==3,errors::InvalidArgument("GatherPoint expects (batch_size,num_points,3) inp shape")); 132 | int b=inp_tensor.shape().dim_size(0); 133 | int n=inp_tensor.shape().dim_size(1); 134 | const Tensor& idx_tensor=context->input(1); 135 | OP_REQUIRES(context,idx_tensor.dims()==2 && idx_tensor.shape().dim_size(0)==b,errors::InvalidArgument("GatherPoint expects (batch_size,num_result) idx shape")); 136 | int m=idx_tensor.shape().dim_size(1); 137 | auto inp_flat=inp_tensor.flat(); 138 | const float * inp=&(inp_flat(0)); 139 | auto idx_flat=idx_tensor.flat(); 140 | const int * idx=&(idx_flat(0)); 141 | Tensor * out_tensor=NULL; 142 | OP_REQUIRES_OK(context,context->allocate_output(0,TensorShape{b,m,3},&out_tensor)); 143 | auto out_flat=out_tensor->flat(); 144 | float * out=&(out_flat(0)); 145 | gatherpointLauncher(b,n,m,inp,idx,out); 146 | } 147 | }; 148 | REGISTER_KERNEL_BUILDER(Name("GatherPoint").Device(DEVICE_GPU),GatherPointGpuOp); 149 | 150 | void scatteraddpointLauncher(int b,int n,int m,const float * out_g,const int * idx,float * inp_g); 151 | class GatherPointGradGpuOp: public OpKernel{ 152 | public: 153 | explicit GatherPointGradGpuOp(OpKernelConstruction * context):OpKernel(context){} 154 | void Compute(OpKernelContext * context)override{ 155 | const Tensor& inp_tensor=context->input(0); 156 | OP_REQUIRES(context,inp_tensor.dims()==3 && inp_tensor.shape().dim_size(2)==3,errors::InvalidArgument("GatherPointGradGpuOp expects (batch_size,num_points,3) inp")); 157 | int b=inp_tensor.shape().dim_size(0); 158 | int n=inp_tensor.shape().dim_size(1); 159 | const Tensor& idx_tensor=context->input(1); 160 | OP_REQUIRES(context,idx_tensor.dims()==2 && idx_tensor.shape().dim_size(0)==b,errors::InvalidArgument("GatherPointGradGpuOp expects (batch_size,num_result) idx shape")); 161 | int m=idx_tensor.shape().dim_size(1); 162 | auto inp_flat=inp_tensor.flat(); 163 | const float * inp=&(inp_flat(0)); 164 | auto idx_flat=idx_tensor.flat(); 165 | const int * idx=&(idx_flat(0)); 166 | const Tensor& out_g_tensor=context->input(2); 167 | OP_REQUIRES(context,out_g_tensor.dims()==3 && out_g_tensor.shape().dim_size(0)==b && out_g_tensor.shape().dim_size(1)==m && out_g_tensor.shape().dim_size(2)==3,errors::InvalidArgument("GatherPointGradGpuOp expects (batch_size,num_result,3) out_g shape")); 168 | auto out_g_flat=out_g_tensor.flat(); 169 | const float * out_g=&(out_g_flat(0)); 170 | Tensor * inp_g_tensor=NULL; 171 | OP_REQUIRES_OK(context,context->allocate_output(0,TensorShape{b,n,3},&inp_g_tensor)); 172 | auto inp_g_flat=inp_g_tensor->flat(); 173 | float * inp_g=&(inp_g_flat(0)); 174 | cudaMemset(inp_g,0,b*n*3*4); 175 | scatteraddpointLauncher(b,n,m,out_g,idx,inp_g); 176 | } 177 | }; 178 | REGISTER_KERNEL_BUILDER(Name("GatherPointGrad").Device(DEVICE_GPU),GatherPointGradGpuOp); 179 | 180 | -------------------------------------------------------------------------------- /latent_3d_points/structural_losses/tf_approxmatch_g.cu: -------------------------------------------------------------------------------- 1 | __global__ void approxmatch(int b,int n,int m,const float * __restrict__ xyz1,const float * __restrict__ xyz2,float * __restrict__ match,float * temp){ 2 | float * remainL=temp+blockIdx.x*(n+m)*2, * remainR=temp+blockIdx.x*(n+m)*2+n,*ratioL=temp+blockIdx.x*(n+m)*2+n+m,*ratioR=temp+blockIdx.x*(n+m)*2+n+m+n; 3 | float multiL,multiR; 4 | if (n>=m){ 5 | multiL=1; 6 | multiR=n/m; 7 | }else{ 8 | multiL=m/n; 9 | multiR=1; 10 | } 11 | const int Block=1024; 12 | __shared__ float buf[Block*4]; 13 | for (int i=blockIdx.x;i=-2;j--){ 22 | float level=-powf(4.0f,j); 23 | if (j==-2){ 24 | level=0; 25 | } 26 | for (int k0=0;k0>>(b,n,m,xyz1,xyz2,match,temp); 182 | } 183 | __global__ void matchcost(int b,int n,int m,const float * __restrict__ xyz1,const float * __restrict__ xyz2,const float * __restrict__ match,float * __restrict__ out){ 184 | __shared__ float allsum[512]; 185 | const int Block=1024; 186 | __shared__ float buf[Block*3]; 187 | for (int i=blockIdx.x;i>>(b,n,m,xyz1,xyz2,match,out); 228 | } 229 | __global__ void matchcostgrad2(int b,int n,int m,const float * __restrict__ xyz1,const float * __restrict__ xyz2,const float * __restrict__ match,float * __restrict__ grad2){ 230 | __shared__ float sum_grad[256*3]; 231 | for (int i=blockIdx.x;i>>(b,n,m,xyz1,xyz2,match,grad1); 294 | matchcostgrad2<<>>(b,n,m,xyz1,xyz2,match,grad2); 295 | } 296 | 297 | -------------------------------------------------------------------------------- /data-preprocess/1_extract_parts2048_ply_erodedX_withnormal.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import os 4 | import h5py 5 | from scipy.io import loadmat 6 | import random 7 | import json 8 | import io 9 | 10 | import argparse 11 | import datetime 12 | 13 | from plyfile import PlyData 14 | 15 | import random 16 | import scipy 17 | 18 | from utils import * 19 | 20 | 21 | parser = argparse.ArgumentParser() 22 | parser.add_argument('--pstart', type=int, default=0) 23 | parser.add_argument('--pend', type=int, default=10000) 24 | 25 | parser.add_argument('--class_ID', type=str, default='03001627') 26 | parser.add_argument('--num_of_parts', type=int, default=4) 27 | parser.add_argument('--erode_radius', type=float, default=0.05) 28 | 29 | 30 | FLAGS = parser.parse_args() 31 | 32 | 33 | ErodeRadius = FLAGS.erode_radius 34 | ErodeRadius_extend = ErodeRadius+0.025 35 | 36 | print( "ErodeRadius = ", ErodeRadius ) 37 | print( "ErodeRadius_extend = ", ErodeRadius_extend ) 38 | 39 | 40 | 41 | #class number 42 | class_ID = FLAGS.class_ID 43 | num_of_parts = FLAGS.num_of_parts 44 | 45 | print(class_ID) 46 | print(num_of_parts) 47 | 48 | 49 | yi2016_dir = "../yi2016/" +class_ID 50 | 51 | densePointCloud_dir = '../densePointCloud/' + class_ID 52 | # create output folder 53 | outPlyfolder = class_ID + '_parts2048_ply_eroded' + str(ErodeRadius) + '_withnormal' 54 | 55 | if not os.path.exists( outPlyfolder ): 56 | os.makedirs( outPlyfolder ) 57 | 58 | voxel_input_folder = "../modelBlockedVoxels256/"+class_ID+"/" 59 | 60 | 61 | print( "yi2016_dir = ", yi2016_dir ) 62 | print( "densePointCloud_dir = ", densePointCloud_dir ) 63 | print( "outPlyfolder = ", outPlyfolder ) 64 | print( "voxel_input_folder = ", voxel_input_folder ) 65 | 66 | 67 | 68 | 69 | 70 | # segment 71 | def getDenseSegLabels_eroded( densePoints, yi2016_pts, yi2016_labels, radius): 72 | 73 | 74 | yi2016_labels_eroded = np.copy( yi2016_labels ) 75 | 76 | for i in range( yi2016_pts.shape[0] ): 77 | px = yi2016_pts[i, 0] 78 | py = yi2016_pts[i, 1] 79 | pz = yi2016_pts[i, 2] 80 | if get_onJoint( yi2016_pts, yi2016_labels, px,py,pz, radius ): 81 | yi2016_labels_eroded[i] = 0 82 | 83 | tree = skKDtree(yi2016_pts, leaf_size=1 ) 84 | _, indices = tree.query( densePoints, k=1) 85 | 86 | denseSegLables = yi2016_labels_eroded[ indices[:, 0] ] 87 | 88 | 89 | return denseSegLables, yi2016_labels_eroded 90 | 91 | 92 | 93 | 94 | 95 | # make all parts 2048 96 | def makeEveryPart2048( densePoints, densePointsNormals, denseSegLables, num_of_parts ): 97 | 98 | 99 | jointPts = densePoints[denseSegLables==0, : ] 100 | 101 | partList = [] 102 | normalList = [] 103 | labelList = [] 104 | for lb in range(1, num_of_parts+1): 105 | 106 | 107 | partPts = densePoints[denseSegLables==lb, : ] 108 | partNormal = densePointsNormals[denseSegLables==lb, : ] 109 | 110 | if partPts.shape[0] == 0: 111 | partPts = np.zeros( (2048,3), np.float32 ) 112 | partNormal = np.ones( (2048,3), np.float32 ) 113 | 114 | while partPts.shape[0] < 2048: 115 | partPts = np.concatenate( (partPts, partPts), axis=0 ) 116 | partNormal = np.concatenate( (partNormal, partNormal), axis=0 ) 117 | 118 | idx = list( range( partPts.shape[0] ) ) 119 | random.shuffle(idx) 120 | 121 | partPts = partPts[idx] 122 | partNormal = partNormal[idx] 123 | 124 | partList.append( partPts[:2048,:] ) 125 | normalList.append( partNormal[:2048,:] ) 126 | labelList.append( np.ones(2048,dtype=int )*lb ) 127 | 128 | densePoints_2048 = np.concatenate( partList , axis=0 ) 129 | denseNormals_2048 = np.concatenate( normalList , axis=0 ) 130 | denseSegLables_2048 = np.concatenate( labelList , axis=0 ) 131 | 132 | 133 | # compute distance to joints 134 | 135 | if jointPts.shape[0] > 1: 136 | 137 | tree = skKDtree(jointPts, leaf_size=1 ) 138 | distanceToJoint_2048, indices = tree.query( densePoints_2048, k=1) 139 | distanceToJoint_2048 = distanceToJoint_2048[:,0] 140 | 141 | else: 142 | # Joints doesn't inclue points. COmpute distance to other parts 143 | Distance_list = [] 144 | for pid in range( num_of_parts ): 145 | thisPart = partList[ pid ] 146 | otherparts = np.vstack( partList[ :pid ] + partList[pid+1:] ) 147 | 148 | print( "thisPart.shape = ", thisPart.shape ) 149 | print( "otherparts.shape = ", otherparts.shape ) 150 | 151 | tree = skKDtree(otherparts, leaf_size=1 ) 152 | distances, _ = tree.query( thisPart, k=1) 153 | distances = distances[:,0] 154 | 155 | Distance_list.append( distances ) 156 | print( "distances.shape = ", distances.shape ) 157 | 158 | distanceToJoint_2048 = np.concatenate( Distance_list ) 159 | print( "distanceToJoint_2048.shape = ", distanceToJoint_2048.shape ) 160 | 161 | 162 | return densePoints_2048, denseNormals_2048, denseSegLables_2048, distanceToJoint_2048 163 | 164 | 165 | 166 | ############################ get name list ############################ 167 | 168 | name_list = [] 169 | image_list = list_image(voxel_input_folder, True, ['.mat']) 170 | for i in range(len(image_list)): 171 | imagine=image_list[i][0] 172 | name_list.append(imagine[0:-4]) 173 | name_list = sorted(name_list) 174 | print("len(name_list) = ", len(name_list) ) 175 | 176 | ######## only consider files that exist in Yi2016 177 | name_list_new = [] 178 | for objname in name_list: 179 | yi2016_gtLabel_path = yi2016_dir + '/expert_verified/points_label/' + objname + '.seg' 180 | if os.path.exists( yi2016_gtLabel_path ): 181 | name_list_new.append( objname ) 182 | 183 | name_list = name_list_new 184 | print("len(name_list) = ", len(name_list) ) 185 | 186 | 187 | for ii in range( len( name_list ) ): 188 | 189 | if ii < FLAGS.pstart or ii >= FLAGS.pend: 190 | continue 191 | 192 | print(ii) 193 | 194 | objname = name_list[ii] 195 | yi2016_gtLabel_path = yi2016_dir + '/expert_verified/points_label/' + objname + '.seg' 196 | yi2016_pts_path = yi2016_dir + '/points/' + objname + '.pts' 197 | densePointCloud_ply_path = densePointCloud_dir + '/'+ objname + '.reoriented.16384.ply' 198 | 199 | if not os.path.exists( yi2016_gtLabel_path ): 200 | print( yi2016_gtLabel_path, " does not exist!" ) 201 | exit(0) 202 | 203 | if not os.path.exists( yi2016_pts_path ): 204 | print( yi2016_pts_path, " does not exist!" ) 205 | exit(0) 206 | 207 | if not os.path.exists( densePointCloud_ply_path ): 208 | print( densePointCloud_ply_path, " does not exist!" ) 209 | exit(0) 210 | 211 | 212 | print( "objname = ", objname ) 213 | 214 | 215 | # load yi2016 pts and seg 216 | 217 | yi2016_pts = None 218 | yi2016_labels = None 219 | 220 | if os.path.exists( yi2016_gtLabel_path ): 221 | pts_ori = np.loadtxt( yi2016_pts_path ) 222 | yi2016_pts = np.concatenate( (pts_ori[:,2:3], pts_ori[:,1:2], -pts_ori[:,0:1] ), axis=1 ) ### swaped x and z, then flipped z 223 | yi2016_labels = np.loadtxt(yi2016_gtLabel_path, dtype=np.dtype(int)) 224 | else: 225 | print("error: cannot load "+ yi2016_gtLabel_path) 226 | exit() 227 | 228 | #################### outlier filtering ######################### 229 | yi2016_pts_beforeFilter = np.copy( yi2016_pts ) 230 | yi2016_labels_beforeFilter = np.copy( yi2016_labels ) 231 | 232 | write_colored_ply( outPlyfolder + '/' + objname + '_yi2016-beforeFilter.ply', yi2016_pts, None, yi2016_labels ) 233 | with open( outPlyfolder + '/' + objname + '_yi2016-beforeFilter.labels', "w") as f: 234 | for id in range( yi2016_labels.shape[0] ): 235 | f.write( str( yi2016_labels[id] ) + '\n') 236 | 237 | 238 | yi2016_pts, yi2016_labels = filter_yi2016_segLabels(yi2016_pts, yi2016_labels, num_of_parts ) 239 | 240 | write_colored_ply( outPlyfolder + '/' + objname + '_yi2016-afterFilter.ply', yi2016_pts, None, yi2016_labels ) 241 | with open( outPlyfolder + '/' + objname + '_yi2016-afterFilter.labels', "w") as f: 242 | for id in range( yi2016_labels.shape[0] ): 243 | f.write( str( yi2016_labels[id] ) + '\n') 244 | 245 | 246 | 247 | ################################################################################ 248 | 249 | 250 | # load dense points ply and normalize 251 | densePoints, densePointsNormals = load_ply_withNormals( densePointCloud_ply_path ) 252 | 253 | bbox_min = np.min( densePoints, axis=0 ) 254 | bbox_max = np.max( densePoints, axis=0 ) 255 | 256 | densePoints = densePoints - ( bbox_max+bbox_min)/2 257 | densePoints = densePoints / np.linalg.norm( bbox_max - bbox_min ) 258 | 259 | 260 | # segment 261 | if ErodeRadius > 0.001: 262 | denseSegLables, yi2016_labels_eroded = getDenseSegLabels_eroded( densePoints, yi2016_pts, yi2016_labels, ErodeRadius) 263 | 264 | ################## if yi2016_labels_eroded doesn't contain joint points, then recover the data to beforefilter 265 | if np.sum( yi2016_labels_eroded==0 ) == 0: 266 | yi2016_pts = yi2016_pts_beforeFilter 267 | yi2016_labels = yi2016_labels_beforeFilter 268 | denseSegLables, yi2016_labels_eroded = getDenseSegLabels_eroded( densePoints, yi2016_pts, yi2016_labels, ErodeRadius) 269 | else: 270 | denseSegLables = getDenseSegLabels( densePoints, yi2016_pts, yi2016_labels ) 271 | yi2016_labels_eroded = yi2016_labels 272 | 273 | 274 | write_colored_ply( outPlyfolder + '/' + objname + '_yi2016-afterFilter-eroded.ply', yi2016_pts, None, yi2016_labels_eroded ) 275 | with open( outPlyfolder + '/' + objname + '_yi2016-afterFilter-eroded.labels', "w") as f: 276 | for id in range( yi2016_labels_eroded.shape[0] ): 277 | f.write( str( yi2016_labels_eroded[id] ) + '\n') 278 | 279 | 280 | write_colored_ply( outPlyfolder + '/' + objname + '_densePoint.ply', densePoints, None, denseSegLables ) 281 | with open( outPlyfolder + '/' + objname + '_densePoint.labels', "w") as f: 282 | for id in range( denseSegLables.shape[0] ): 283 | f.write( str( denseSegLables[id] ) + '\n') 284 | 285 | ################## 286 | 287 | 288 | # make all parts 2048 289 | densePoints_2048, denseNormals_2048, densePartLabels_2048, distanceToJoint_2048 = makeEveryPart2048( densePoints, densePointsNormals, denseSegLables, num_of_parts ) 290 | 291 | write_colored_ply( outPlyfolder + '/' + objname + '_ori.ply', densePoints_2048, denseNormals_2048, densePartLabels_2048 ) 292 | 293 | with open( outPlyfolder + '/' + objname + '_ori.labels', "w") as f: 294 | for id in range( densePartLabels_2048.shape[0] ): 295 | f.write( str( densePartLabels_2048[id] ) + '\n') 296 | 297 | with open( outPlyfolder + '/' + objname + '_ori.dis2joint', "w") as f: 298 | for id in range( distanceToJoint_2048.shape[0] ): 299 | f.write( str( distanceToJoint_2048[id] ) + '\n') 300 | 301 | --------------------------------------------------------------------------------