├── 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 |
--------------------------------------------------------------------------------