├── README.md
├── models
├── __init__.py
├── deformnet.py
├── losses.py
├── meshnet.py
├── pointnet
│ ├── __init__.py
│ ├── model.py
│ ├── model_cpu.py
│ ├── model_emd.py
│ ├── model_fc_upconv.py
│ ├── model_hierachy.py
│ ├── model_pointnet2.py
│ ├── model_seg.py
│ ├── model_upconv.py
│ ├── model_vae.py
│ ├── model_withtransform.py
│ ├── pointnet2_cls_msg.py
│ ├── pointnet2_part_seg.py
│ └── transform_nets.py
├── pointnet_util.py
├── tf_ops
│ ├── 3d_interpolation
│ │ ├── interpolate.cpp
│ │ ├── tf_interpolate.cpp
│ │ ├── tf_interpolate.py
│ │ ├── tf_interpolate_compile.sh
│ │ ├── tf_interpolate_op_test.py
│ │ └── visu_interpolation.py
│ ├── __init__.py
│ ├── approxmatch
│ │ ├── __init__.py
│ │ ├── tf_approxmatch.cpp
│ │ ├── tf_approxmatch.py
│ │ ├── tf_approxmatch_compile.sh
│ │ └── tf_approxmatch_g.cu
│ ├── compile.sh
│ ├── grouping
│ │ ├── test
│ │ │ ├── compile.sh
│ │ │ ├── query_ball_point.cpp
│ │ │ ├── query_ball_point.cu
│ │ │ ├── query_ball_point_block.cu
│ │ │ ├── query_ball_point_grid.cu
│ │ │ ├── selection_sort.cpp
│ │ │ ├── selection_sort.cu
│ │ │ └── selection_sort_const.cu
│ │ ├── tf_grouping.cpp
│ │ ├── tf_grouping.py
│ │ ├── tf_grouping_compile.sh
│ │ ├── tf_grouping_g.cu
│ │ └── tf_grouping_op_test.py
│ ├── mesh_laplacian
│ │ ├── __init__.py
│ │ ├── tf_meshlaplacian.cpp
│ │ ├── tf_meshlaplacian.py
│ │ ├── tf_meshlaplacian_compile.sh
│ │ └── tf_meshlaplacian_g.cu
│ ├── mesh_sampling
│ │ ├── __init__.py
│ │ ├── tf_meshsampling.cpp
│ │ ├── tf_meshsampling.h
│ │ ├── tf_meshsampling.py
│ │ ├── tf_meshsampling_compile.sh
│ │ └── tf_meshsampling_g.cu
│ ├── nn_distance
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── tf_nndistance.cpp
│ │ ├── tf_nndistance.py
│ │ ├── tf_nndistance_compile.sh
│ │ ├── tf_nndistance_cpu.py
│ │ └── tf_nndistance_g.cu
│ ├── sampling
│ │ ├── tf_sampling.cpp
│ │ ├── tf_sampling.py
│ │ ├── tf_sampling_compile.sh
│ │ └── tf_sampling_g.cu
│ └── test.py
└── tf_util.py
├── shapenet
├── 2D
│ ├── demo_2D.py
│ ├── model_vgg.py
│ ├── test.py
│ └── train_vgg.py
├── 3D
│ ├── demo.py
│ ├── model.py
│ ├── test.py
│ └── train.py
└── data
│ ├── data_h5.py
│ ├── data_h5_mp.py
│ ├── data_h5_template.py
│ ├── data_img.py
│ ├── data_obj.py
│ ├── data_off.py
│ ├── data_pc.py
│ ├── data_rendered_img.py
│ ├── data_rendered_img_template.py
│ └── obj.py
└── utils
├── __init__.py
├── output_utils.py
├── part_color_mapping.json
├── test_utils.py
└── tf_util.py
/README.md:
--------------------------------------------------------------------------------
1 | ### 3DN: 3D Deformation Network [Arxiv]
2 |
3 | ### Installation
4 | Install Tensorflow (1.10.0), PyMesh.
5 |
6 | The mesh sampling and mesh laplacian operations are under folder `models/tf_ops`. To build them, simply use `cd models/tf_ops` and `sh compile.sh` to compile. You may need to set CUDA path in each subfolder.
7 |
8 | ### Training
9 |
10 | ```bash
11 | cd shapenet/3D
12 | python train.py
13 | ```
14 | ```bash
15 | cd shapenet/2D
16 | python train_vgg.py
17 | ```
18 | Pretrained Model can be found here.
19 | ### Testing
20 |
21 | ```bash
22 | cd shapenet/3D
23 | python test.py
24 | ```
25 | ```bash
26 | cd shapenet/2D
27 | python test.py
28 | ```
29 |
30 | ### Citation
31 | If you find this work useful, please consider citing:
32 |
33 | @inproceedings{wang20193dn,
34 | title={3DN: 3D Deformation Network},
35 | author={Wang, Weiyue and Ceylan, Duygu and Mech, Radomir and Neumann, Ulrich},
36 | booktitle={CVPR},
37 | year={2019}
38 | }
39 |
40 |
41 | ### Acknowledgemets
42 | - PointNet
43 | - PointNet AutoEncoder
44 | - Point Set Generation
45 |
46 |
47 |
--------------------------------------------------------------------------------
/models/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/laughtervv/3DN/81e3651d780478139c3b8dee5e737ce565813900/models/__init__.py
--------------------------------------------------------------------------------
/models/deformnet.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import tf_util
3 | from pointnet_util import pointnet_sa_module, pointnet_fp_module
4 |
5 | def displacement_decoder(net, batch_size, is_training, bn=True, bn_decay=None, scope = '', outputdim=3):
6 |
7 | net2 = tf_util.conv2d(net, 512, [1,1], padding='VALID', stride=[1,1], bn_decay=bn_decay, bn=bn, is_training=is_training, scope=scope+'decoder/conv1')
8 | net2 = tf_util.conv2d(net2, 256, [1,1], padding='VALID', stride=[1,1], bn_decay=bn_decay, bn=bn, is_training=is_training, scope=scope+'decoder/conv2')
9 | net2 = tf_util.conv2d(net2, outputdim, [1,1], padding='VALID', stride=[1,1], activation_fn=None, bn=False, scope=scope+'decoder/conv5')
10 |
11 | net2 = tf.reshape(net2, [batch_size, -1, outputdim])
12 | return net2
13 |
14 | def get_pred_foldenet_basic(src_pc, src_feats, ref_feats, is_training, batch_size, num_point, bn, bn_decay):
15 | ##TODO: Symmetry
16 |
17 | globalfeats = tf.concat([src_feats, ref_feats], axis=1)
18 |
19 | globalfeats = tf.reshape(globalfeats, [batch_size, 1, 1, -1])
20 | globalfeats_expand = tf.tile(globalfeats, [1, src_pc.get_shape()[1], 1, 1])
21 |
22 | concat = tf.concat(axis=3, values=[tf.expand_dims(src_pc,2), globalfeats_expand])
23 | displacement = displacement_decoder(concat, batch_size, is_training, bn=bn, bn_decay=bn_decay)
24 |
25 | concat = tf.concat(axis=3, values=[tf.expand_dims(displacement,2), globalfeats_expand])
26 | displacement = displacement_decoder(concat, batch_size, is_training, bn=bn, bn_decay=bn_decay, scope='fold2/')
27 |
28 | concat2 = tf.concat(axis=3, values=[tf.expand_dims(displacement,2), concat])
29 | displacement = displacement_decoder(concat2, batch_size, is_training, bn=bn, bn_decay=bn_decay, scope='fold3/')
30 |
31 | pred = src_pc + displacement
32 |
33 | return pred, displacement
34 |
35 |
--------------------------------------------------------------------------------
/models/meshnet.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import numpy as np
3 | import math
4 | import os
5 | import sys
6 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
7 | sys.path.append(os.path.join(BASE_DIR))
8 | ROOT_DIR = os.path.dirname(BASE_DIR)
9 | sys.path.append(os.path.join(ROOT_DIR))
10 | try:
11 | import models.tf_ops.mesh_sampling.tf_meshsampling as tf_meshsampling
12 | except:
13 | import models.tf_ops_server.mesh_sampling.tf_meshsampling as tf_meshsampling
14 |
15 |
16 | def mesh_sample(src_verts, src_nverts, src_tris, src_ntris, batch_size, num_point, feats=None, scope='', random=None):
17 |
18 | with tf.variable_scope(scope) as sc:
19 | if random is not None:
20 | r1, r2, r = random
21 | # r1 = r1.initialized_value()
22 | # r2 = r2.initialized_value()
23 | # r = r.initialized_value()
24 | else:
25 | r1 = tf.random_uniform([batch_size, num_point], dtype=tf.float32)
26 | r2 = tf.random_uniform([batch_size, num_point], dtype=tf.float32)
27 | r = tf.random_uniform([batch_size, num_point], dtype=tf.float32)
28 | # print (scope,'r', r.get_shape())
29 | # print (scope,'feats', feats.get_shape())
30 |
31 | if feats == None:
32 | src_pc, src_pc_feats_from_verts, correspondingface = tf_meshsampling.mesh_sampling(src_verts, src_nverts, src_tris, src_ntris, src_verts, r, r1, r2)
33 | else:
34 | src_pc, src_pc_feats_from_verts, correspondingface = tf_meshsampling.mesh_sampling(src_verts, src_nverts, src_tris, src_ntris, feats, r, r1, r2)
35 |
36 | src_pc_feats_from_verts = tf.expand_dims(src_pc_feats_from_verts, 2)
37 | correspondingface = tf.expand_dims(correspondingface, 2)
38 | # print (scope,'src_pc_feats_from_verts', src_pc_feats_from_verts.get_shape())
39 |
40 | return src_pc, src_pc_feats_from_verts, correspondingface, r1, r2, r
--------------------------------------------------------------------------------
/models/pointnet/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/laughtervv/3DN/81e3651d780478139c3b8dee5e737ce565813900/models/pointnet/__init__.py
--------------------------------------------------------------------------------
/models/pointnet/model.py:
--------------------------------------------------------------------------------
1 | """ TF model for point cloud autoencoder. PointNet encoder, FC decoder.import tensorflow as tf
2 | import numpy as np
3 | import math
4 | import os
5 | import sys
6 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
7 | ROOT_DIR = os.path.dirname(BASE_DIR)
8 | sys.path.append(os.path.join(ROOT_DIR))
9 | import models.pointnet.model as pointnet
10 | from models.ffd import *
11 | try:
12 | import models.tf_ops.approxmatch.tf_approxmatch as tf_approxmatch
13 | import models.tf_ops.nn_distance.tf_nndistance as tf_nndistance
14 | except:
15 | import models.tf_ops_server.approxmatch.tf_approxmatch as tf_approxmatch
16 | import models.tf_ops_server.nn_distance.tf_nndistance as tf_nndistance
17 | Using GPU Chamfer's distance loss.
18 |
19 | Author: Charles R. Qi
20 | Date: May 2018
21 | """
22 | import tensorflow as tf
23 | import numpy as np
24 | import math
25 | import sys
26 | import os
27 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
28 | ROOT_DIR = os.path.dirname(BASE_DIR)
29 | sys.path.append(os.path.join(ROOT_DIR))
30 | import tf_util
31 | # sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/nn_distance'))
32 | # import tf_nndistance
33 |
34 | def placeholder_inputs(batch_size, num_point):
35 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
36 | labels_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
37 | return pointclouds_pl, labels_pl
38 |
39 |
40 | def get_model(point_cloud, is_training, scope='', num_point=None, bn_decay=None, ifglobal=False, bn=True):
41 | """ Autoencoder for point clouds.
42 | Input:
43 | point_cloud: TF tensor BxNx3
44 | is_training: boolean
45 | bn_decay: float between 0 and 1
46 | Output:
47 | net: TF tensor BxNx3, reconstructed point clouds
48 | end_points: dict
49 | """
50 | batch_size = point_cloud.get_shape()[0].value
51 | if num_point is None:
52 | num_point = point_cloud.get_shape()[1].value
53 | point_dim = point_cloud.get_shape()[2].value
54 | end_points = {}
55 |
56 | with tf.variable_scope(scope) as sc:
57 |
58 | input_image = tf.expand_dims(point_cloud, -1)
59 |
60 | # Encoder
61 | net = tf_util.conv2d(input_image, 64, [1,point_dim],
62 | padding='VALID', stride=[1,1],
63 | bn=bn, is_training=is_training,
64 | scope='conv1', bn_decay=bn_decay)
65 | print('pointnet shape', net.get_shape())
66 | net = tf_util.conv2d(net, 64, [1,1],
67 | padding='VALID', stride=[1,1],
68 | bn=bn, is_training=is_training,
69 | scope='conv2', bn_decay=bn_decay)
70 | point_feat = tf_util.conv2d(net, 64, [1,1],
71 | padding='VALID', stride=[1,1],
72 | bn=bn, is_training=is_training,
73 | scope='conv3', bn_decay=bn_decay)
74 | net = tf_util.conv2d(point_feat, 128, [1,1],
75 | padding='VALID', stride=[1,1],
76 | bn=bn, is_training=is_training,
77 | scope='conv4', bn_decay=bn_decay)
78 | pointwise = tf_util.conv2d(net, 1024, [1,1],
79 | padding='VALID', stride=[1,1],
80 | bn=bn, is_training=is_training,
81 | scope='conv5', bn_decay=bn_decay)
82 | # global_feat = tf_util.max_pool2d(pointwise, [num_point,1],
83 | # padding='VALID', scope='maxpool')
84 |
85 | global_feat = tf.reduce_max(pointwise, axis = 1, keep_dims=True)
86 |
87 | print('maxpoolglobal_feat', global_feat.get_shape())
88 |
89 | feat0 = tf.reshape(global_feat, [batch_size, 1024])
90 |
91 | # FC Decoder
92 | net = None
93 | # if ifglobal:
94 | feat = tf_util.fully_connected(feat0, 1024, bn=bn, is_training=is_training, scope='fc1', bn_decay=bn_decay)
95 | feat = tf_util.fully_connected(feat, 1024, bn=bn, is_training=is_training, scope='fc2', bn_decay=bn_decay)
96 | # if num_point is not None:
97 | # net = tf_util.fully_connected(feat, num_point * 3, activation_fn=None, scope='fc3')
98 | # net = tf.reshape(net, (batch_size, num_point, 3))
99 | # end_points['pc'] = net
100 | end_points['embedding'] = feat
101 | end_points['pointwise'] = pointwise
102 |
103 | return net, end_points
104 |
105 | # def get_loss(pred, label, end_points):
106 | # """ pred: BxNx3,
107 | # label: BxNx3, """
108 | # dists_forward,_,dists_backward,_ = tf_nndistance.nn_distance(pred, label)
109 | # loss = tf.reduce_mean(dists_forward+dists_backward)
110 | # end_points['pcloss'] = loss
111 | # return loss*100, end_points
112 |
113 | def get_decoder(embedding, is_training, scope='', bn_decay=None, bn=True):
114 |
115 | batch_size = embedding.get_shape()[0].value
116 | print(embedding.shape)
117 | net = tf_util.fully_connected(embedding, 512, bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
118 | net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training, scope='fc2', bn_decay=bn_decay)
119 | net = tf_util.fully_connected(net, 1024*3, activation_fn=None, scope='fc3')
120 | pc_fc = tf.reshape(net, (batch_size, -1, 3))
121 |
122 | # UPCONV Decoder
123 | net = tf.reshape(embedding, [batch_size, 1, 1, -1])
124 | net = tf_util.conv2d_transpose(net, 512, kernel_size=[2,2], stride=[1,1], padding='VALID', scope='upconv1', bn=True, bn_decay=bn_decay, is_training=is_training)
125 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[3,3], stride=[1,1], padding='VALID', scope='upconv2', bn=True, bn_decay=bn_decay, is_training=is_training)
126 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[4,4], stride=[2,2], padding='VALID', scope='upconv3', bn=True, bn_decay=bn_decay, is_training=is_training)
127 | net = tf_util.conv2d_transpose(net, 128, kernel_size=[5,5], stride=[3,3], padding='VALID', scope='upconv4', bn=True, bn_decay=bn_decay, is_training=is_training)
128 | net = tf_util.conv2d_transpose(net, 3, kernel_size=[1,1], stride=[1,1], padding='VALID', scope='upconv5', activation_fn=None)
129 |
130 | pc_upconv = tf.reshape(net, [batch_size, -1, 3])
131 |
132 | # Set union
133 | reconst_pc = tf.concat(values=[pc_fc,pc_upconv], axis=1)
134 |
135 | return reconst_pc
136 |
137 | if __name__=='__main__':
138 | with tf.Graph().as_default():
139 | inputs = tf.zeros((32,1024,3))
140 | outputs = get_model(inputs, tf.constant(True))
141 | print(outputs)
142 | loss = get_loss(outputs[0], tf.zeros((32,1024,3)), outputs[1])
143 |
--------------------------------------------------------------------------------
/models/pointnet/model_cpu.py:
--------------------------------------------------------------------------------
1 | """ TF model for point cloud autoencoder. PointNet encoder, FC decoder.
2 | Using CPU Chamfer's distance loss.
3 |
4 | Author: Charles R. Qi
5 | Date: May 2018
6 | """
7 | import tensorflow as tf
8 | import numpy as np
9 | import math
10 | import sys
11 | import os
12 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
13 | ROOT_DIR = os.path.dirname(BASE_DIR)
14 | sys.path.append(os.path.join(ROOT_DIR, 'utils'))
15 | import tf_util
16 | sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/nn_distance'))
17 | import tf_nndistance_cpu
18 |
19 | def placeholder_inputs(batch_size, num_point):
20 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
21 | labels_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
22 | return pointclouds_pl, labels_pl
23 |
24 |
25 | def get_model(point_cloud, is_training, bn_decay=None):
26 | """ Autoencoder for point clouds.
27 | Input:
28 | point_cloud: TF tensor BxNx3
29 | is_training: boolean
30 | bn_decay: float between 0 and 1
31 | Output:
32 | net: TF tensor BxNx3, reconstructed point clouds
33 | end_points: dict
34 | """
35 |
36 | batch_size = point_cloud.get_shape()[0].value
37 | num_point = point_cloud.get_shape()[1].value
38 | point_dim = point_cloud.get_shape()[2].value
39 | end_points = {}
40 |
41 | input_image = tf.expand_dims(point_cloud, -1)
42 |
43 | # Encoder
44 | net = tf_util.conv2d(input_image, 64, [1,point_dim],
45 | padding='VALID', stride=[1,1],
46 | bn=True, is_training=is_training,
47 | scope='conv1', bn_decay=bn_decay)
48 | net = tf_util.conv2d(net, 64, [1,1],
49 | padding='VALID', stride=[1,1],
50 | bn=True, is_training=is_training,
51 | scope='conv2', bn_decay=bn_decay)
52 | point_feat = tf_util.conv2d(net, 64, [1,1],
53 | padding='VALID', stride=[1,1],
54 | bn=True, is_training=is_training,
55 | scope='conv3', bn_decay=bn_decay)
56 | net = tf_util.conv2d(point_feat, 128, [1,1],
57 | padding='VALID', stride=[1,1],
58 | bn=True, is_training=is_training,
59 | scope='conv4', bn_decay=bn_decay)
60 | net = tf_util.conv2d(net, 1024, [1,1],
61 | padding='VALID', stride=[1,1],
62 | bn=True, is_training=is_training,
63 | scope='conv5', bn_decay=bn_decay)
64 | global_feat = tf_util.max_pool2d(net, [num_point,1],
65 | padding='VALID', scope='maxpool')
66 |
67 | net = tf.reshape(global_feat, [batch_size, -1])
68 | end_points['embedding'] = net
69 |
70 | # FC Decoder
71 | net = tf_util.fully_connected(net, 1024, bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
72 | net = tf_util.fully_connected(net, 1024, bn=True, is_training=is_training, scope='fc2', bn_decay=bn_decay)
73 | net = tf_util.fully_connected(net, num_point*3, activation_fn=None, scope='fc3')
74 | net = tf.reshape(net, (batch_size, num_point, 3))
75 |
76 | return net, end_points
77 |
78 | def get_loss(pred, label, end_points):
79 | """ pred: BxNx3,
80 | label: BxNx3, """
81 | dists_forward,_,dists_backward,_ = tf_nndistance_cpu.nn_distance_cpu(pred, label)
82 | loss = tf.reduce_mean(dists_forward+dists_backward)
83 | end_points['pcloss'] = loss
84 | return loss*100, end_points
85 |
86 |
87 | if __name__=='__main__':
88 | with tf.Graph().as_default():
89 | inputs = tf.zeros((32,1024,3))
90 | outputs = get_model(inputs, tf.constant(True))
91 | print(outputs)
92 | loss = get_loss(outputs[0], tf.zeros((32,1024,3)), outputs[1])
93 |
--------------------------------------------------------------------------------
/models/pointnet/model_emd.py:
--------------------------------------------------------------------------------
1 | """ TF model for point cloud autoencoder. PointNet encoder, FC decoder.
2 | Using GPU Earth Mover's distance loss.
3 |
4 | Author: Charles R. Qi
5 | Date: May 2018
6 | """
7 | import tensorflow as tf
8 | import numpy as np
9 | import math
10 | import sys
11 | import os
12 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
13 | ROOT_DIR = os.path.dirname(BASE_DIR)
14 | sys.path.append(os.path.join(ROOT_DIR, 'utils'))
15 | import tf_util
16 | sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/nn_distance'))
17 | import tf_nndistance
18 | sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/approxmatch'))
19 | import tf_approxmatch
20 |
21 | def placeholder_inputs(batch_size, num_point):
22 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
23 | labels_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
24 | return pointclouds_pl, labels_pl
25 |
26 |
27 | def get_model(point_cloud, is_training, bn_decay=None):
28 | """ Autoencoder for point clouds.
29 | Input:
30 | point_cloud: TF tensor BxNxC
31 | is_training: boolean
32 | bn_decay: float between 0 and 1
33 | Output:
34 | net: TF tensor BxNxC, reconstructed point clouds
35 | end_points: dict
36 | """
37 | batch_size = point_cloud.get_shape()[0].value
38 | num_point = point_cloud.get_shape()[1].value
39 | point_dim = point_cloud.get_shape()[2].value
40 | end_points = {}
41 |
42 | input_image = tf.expand_dims(point_cloud, -1)
43 |
44 | # Encoder
45 | net = tf_util.conv2d(input_image, 64, [1,point_dim],
46 | padding='VALID', stride=[1,1],
47 | bn=True, is_training=is_training,
48 | scope='conv1', bn_decay=bn_decay)
49 | net = tf_util.conv2d(net, 64, [1,1],
50 | padding='VALID', stride=[1,1],
51 | bn=True, is_training=is_training,
52 | scope='conv2', bn_decay=bn_decay)
53 | point_feat = tf_util.conv2d(net, 64, [1,1],
54 | padding='VALID', stride=[1,1],
55 | bn=True, is_training=is_training,
56 | scope='conv3', bn_decay=bn_decay)
57 | net = tf_util.conv2d(point_feat, 128, [1,1],
58 | padding='VALID', stride=[1,1],
59 | bn=True, is_training=is_training,
60 | scope='conv4', bn_decay=bn_decay)
61 | net = tf_util.conv2d(net, 1024, [1,1],
62 | padding='VALID', stride=[1,1],
63 | bn=True, is_training=is_training,
64 | scope='conv5', bn_decay=bn_decay)
65 | global_feat = tf_util.max_pool2d(net, [num_point,1],
66 | padding='VALID', scope='maxpool')
67 |
68 | net = tf.reshape(global_feat, [batch_size, -1])
69 | end_points['embedding'] = net
70 |
71 | # FC Decoder
72 | net = tf_util.fully_connected(net, 1024, bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
73 | net = tf_util.fully_connected(net, 1024, bn=True, is_training=is_training, scope='fc2', bn_decay=bn_decay)
74 | net = tf_util.fully_connected(net, num_point*3, activation_fn=None, scope='fc3')
75 | net = tf.reshape(net, (batch_size, num_point, 3))
76 |
77 | return net, end_points
78 |
79 | def get_loss(pred, label, end_points):
80 | """ pred: BxNx3,
81 | label: BxNx3, """
82 | dists_forward,_,dists_backward,_ = tf_nndistance.nn_distance(pred, label)
83 | pc_loss = tf.reduce_mean(dists_forward+dists_backward)
84 | end_points['pcloss'] = pc_loss
85 |
86 | match = tf_approxmatch.approx_match(label, pred)
87 | loss = tf.reduce_mean(tf_approxmatch.match_cost(label, pred, match))
88 | tf.summary.scalar('loss', loss)
89 | return loss, end_points
90 |
91 |
92 | if __name__=='__main__':
93 | with tf.Graph().as_default():
94 | inputs = tf.zeros((32,1024,3))
95 | outputs = get_model(inputs, tf.constant(True))
96 | print outputs
97 | loss = get_loss(outputs[0], tf.zeros((32,1024,3)), outputs[1])
98 |
--------------------------------------------------------------------------------
/models/pointnet/model_fc_upconv.py:
--------------------------------------------------------------------------------
1 | """ TF model for point cloud autoencoder. PointNet encoder, FC and UPCONV decoder.
2 | Using GPU Chamfer's distance loss. Required to have 2048 points.
3 |
4 | Author: Charles R. Qi
5 | Date: May 2018
6 | """
7 | import tensorflow as tf
8 | import numpy as np
9 | import math
10 | import sys
11 | import os
12 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
13 | ROOT_DIR = os.path.dirname(BASE_DIR)
14 | sys.path.append(os.path.join(ROOT_DIR))
15 | import tf_util
16 | # sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/nn_distance'))
17 | # import tf_nndistance
18 |
19 | def placeholder_inputs(batch_size, num_point):
20 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
21 | labels_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
22 | return pointclouds_pl, labels_pl
23 |
24 |
25 | def get_model(point_cloud, is_training, bn_decay=None):
26 | """ Autoencoder for point clouds.
27 | Input:
28 | point_cloud: TF tensor BxNx3
29 | is_training: boolean
30 | bn_decay: float between 0 and 1
31 | Output:
32 | net: TF tensor BxNx3, reconstructed point clouds
33 | end_points: dict
34 | """
35 | batch_size = point_cloud.get_shape()[0].value
36 | num_point = point_cloud.get_shape()[1].value
37 | # assert(num_point==2048)
38 | point_dim = point_cloud.get_shape()[2].value
39 | end_points = {}
40 |
41 | input_image = tf.expand_dims(point_cloud, -1)
42 |
43 | # Encoder
44 | net = tf_util.conv2d(input_image, 64, [1, point_dim],
45 | padding='VALID', stride=[1,1],
46 | bn=True, is_training=is_training,
47 | scope='conv1', bn_decay=bn_decay)
48 | net = tf_util.conv2d(net, 64, [1,1],
49 | padding='VALID', stride=[1,1],
50 | bn=True, is_training=is_training,
51 | scope='conv2', bn_decay=bn_decay)
52 | point_feat = tf_util.conv2d(net, 64, [1,1],
53 | padding='VALID', stride=[1,1],
54 | bn=True, is_training=is_training,
55 | scope='conv3', bn_decay=bn_decay)
56 | net = tf_util.conv2d(point_feat, 128, [1,1],
57 | padding='VALID', stride=[1,1],
58 | bn=True, is_training=is_training,
59 | scope='conv4', bn_decay=bn_decay)
60 | net = tf_util.conv2d(net, 1024, [1,1],
61 | padding='VALID', stride=[1,1],
62 | bn=True, is_training=is_training,
63 | scope='conv5', bn_decay=bn_decay)
64 | end_points['pointwise'] = net
65 | # global_feat = tf_util.max_pool2d(net, [num_point,1],
66 | # padding='VALID', scope='maxpool')
67 | global_feat = tf.reduce_max(net, axis = 1, keep_dims=True)
68 |
69 | net = tf.reshape(global_feat, [batch_size, -1])
70 | net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training, scope='fc00', bn_decay=bn_decay)
71 | embedding = tf.reshape(net, [batch_size, -1])
72 | end_points['embedding'] = embedding
73 |
74 | # FC Decoder
75 | net = tf_util.fully_connected(embedding, 512, bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
76 | net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training, scope='fc2', bn_decay=bn_decay)
77 | net = tf_util.fully_connected(net, 1024*3, activation_fn=None, scope='fc3')
78 | pc_fc = tf.reshape(net, (batch_size, -1, 3))
79 |
80 | # UPCONV Decoder
81 | net = tf.reshape(embedding, [batch_size, 1, 1, -1])
82 | print net.shape
83 | net = tf_util.conv2d_transpose(net, 512, kernel_size=[2,2], stride=[1,1], padding='VALID', scope='upconv1', bn=True, bn_decay=bn_decay, is_training=is_training)
84 | print net.shape
85 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[3,3], stride=[1,1], padding='VALID', scope='upconv2', bn=True, bn_decay=bn_decay, is_training=is_training)
86 | print net.shape
87 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[4,4], stride=[2,2], padding='VALID', scope='upconv3', bn=True, bn_decay=bn_decay, is_training=is_training)
88 | print net.shape
89 | net = tf_util.conv2d_transpose(net, 128, kernel_size=[5,5], stride=[3,3], padding='VALID', scope='upconv4', bn=True, bn_decay=bn_decay, is_training=is_training)
90 | print net.shape
91 | net = tf_util.conv2d_transpose(net, 3, kernel_size=[1,1], stride=[1,1], padding='VALID', scope='upconv5', activation_fn=None)
92 | end_points['xyzmap'] = net
93 | pc_upconv = tf.reshape(net, [batch_size, -1, 3])
94 |
95 |
96 | # Set union
97 | net = tf.concat(values=[pc_fc,pc_upconv], axis=1)
98 |
99 | return net, end_points
100 |
101 | # def get_loss(pred, label, end_points):
102 | # """ pred: BxNx3,
103 | # label: BxNx3, """
104 | # dists_forward,_,dists_backward,_ = tf_nndistance.nn_distance(pred, label)
105 | # loss = tf.reduce_mean(dists_forward+dists_backward)
106 | # end_points['pcloss'] = loss
107 | # return loss*100, end_points
108 |
109 |
110 | if __name__=='__main__':
111 | with tf.Graph().as_default():
112 | inputs = tf.zeros((32,2048,3))
113 | outputs = get_model(inputs, tf.constant(True))
114 | print(outputs)
115 | # loss = get_loss(outputs[0], tf.zeros((32,2048,3)), outputs[1])
116 |
--------------------------------------------------------------------------------
/models/pointnet/model_hierachy.py:
--------------------------------------------------------------------------------
1 | """ TF model for point cloud autoencoder. PointNet encoder, *hierachical* FC decoder.
2 | Using GPU Chamfer's distance loss.
3 |
4 | Author: Charles R. Qi
5 | Date: May 2018
6 | """
7 | import tensorflow as tf
8 | import numpy as np
9 | import math
10 | import sys
11 | import os
12 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
13 | ROOT_DIR = os.path.dirname(BASE_DIR)
14 | sys.path.append(os.path.join(ROOT_DIR, 'utils'))
15 | import tf_util
16 | sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/nn_distance'))
17 | import tf_nndistance
18 |
19 | def placeholder_inputs(batch_size, num_point):
20 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
21 | labels_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
22 | return pointclouds_pl, labels_pl
23 |
24 |
25 | def get_model(point_cloud, is_training, bn_decay=None):
26 | """ Autoencoder for point clouds.
27 | Input:
28 | point_cloud: TF tensor BxNxC
29 | is_training: boolean
30 | bn_decay: float between 0 and 1
31 | Output:
32 | pc_xyz: TF tensor BxNxC, reconstructed point clouds
33 | end_points: dict
34 | """
35 | batch_size = point_cloud.get_shape()[0].value
36 | num_point = point_cloud.get_shape()[1].value
37 | point_dim = point_cloud.get_shape()[2].value
38 | end_points = {}
39 |
40 | input_image = tf.expand_dims(point_cloud, -1)
41 |
42 | # Encoder
43 | net = tf_util.conv2d(input_image, 64, [1,point_dim],
44 | padding='VALID', stride=[1,1],
45 | bn=True, is_training=is_training,
46 | scope='conv1', bn_decay=bn_decay)
47 | net = tf_util.conv2d(net, 64, [1,1],
48 | padding='VALID', stride=[1,1],
49 | bn=True, is_training=is_training,
50 | scope='conv2', bn_decay=bn_decay)
51 | point_feat = tf_util.conv2d(net, 64, [1,1],
52 | padding='VALID', stride=[1,1],
53 | bn=True, is_training=is_training,
54 | scope='conv3', bn_decay=bn_decay)
55 | net = tf_util.conv2d(point_feat, 128, [1,1],
56 | padding='VALID', stride=[1,1],
57 | bn=True, is_training=is_training,
58 | scope='conv4', bn_decay=bn_decay)
59 | net = tf_util.conv2d(net, 1024, [1,1],
60 | padding='VALID', stride=[1,1],
61 | bn=True, is_training=is_training,
62 | scope='conv5', bn_decay=bn_decay)
63 | global_feat = tf_util.max_pool2d(net, [num_point,1],
64 | padding='VALID', scope='maxpool')
65 |
66 | net = tf.reshape(global_feat, [batch_size, -1])
67 | net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training, scope='fc00', bn_decay=bn_decay)
68 | net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training, scope='fc01', bn_decay=bn_decay)
69 | end_points['embedding'] = net
70 |
71 | # Hierarchical FC decoder
72 | # Firstly predict 64 points with their XYZs and features
73 | # Then from feature of each of the 64 points, predict XYZs for NUM_POINT/64 subpoints with their *local* XYZs
74 | # At last, local XYZs are translated to their global XYZs
75 | pc1_feat = tf_util.fully_connected(net, 64*256, bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
76 | pc1_xyz = tf_util.fully_connected(net, 64*3, activation_fn=None, scope='fc1_xyz')
77 | pc1_feat = tf.reshape(pc1_feat, [batch_size, 64, 256])
78 | pc1_xyz = tf.reshape(pc1_xyz, [batch_size, 64, 3])
79 | end_points['pc1_xyz'] = pc1_xyz
80 |
81 | pc2 = tf_util.conv1d(pc1_feat, 256, 1, padding='VALID', stride=1, bn=True, is_training=is_training, scope='fc_conv1', bn_decay=bn_decay)
82 | pc2_xyz = tf_util.conv1d(pc2, (num_point/64)*3, 1, padding='VALID', stride=1, activation_fn=None, scope='fc_conv3') # B,64,32*3
83 | pc2_xyz = tf.reshape(pc2_xyz, [batch_size, 64, num_point/64, 3])
84 | pc1_xyz_expand = tf.expand_dims(pc1_xyz, 2) # B,64,1,3
85 | # Translate local XYZs to global XYZs
86 | pc2_xyz = pc2_xyz + pc1_xyz_expand
87 | pc_xyz = tf.reshape(pc2_xyz, [batch_size, num_point, 3])
88 |
89 | return pc_xyz, end_points
90 |
91 | def get_loss(pred, label, end_points):
92 | """ pred: BxNx3,
93 | label: BxNx3, """
94 | dists_forward,_,dists_backward,_ = tf_nndistance.nn_distance(pred, label)
95 | pc_loss = tf.reduce_mean(dists_forward+dists_backward)
96 | end_points['pcloss'] = pc_loss
97 | tf.summary.scalar('pcloss', pc_loss)
98 |
99 | d1,_,d2,_ = tf_nndistance.nn_distance(end_points['pc1_xyz'], label)
100 | pc1_loss = tf.reduce_mean(d1) + tf.reduce_mean(d2)
101 | tf.summary.scalar('pc1loss', pc1_loss)
102 | loss = pc_loss + 0.1*pc1_loss
103 |
104 | return loss*100, end_points
105 |
106 |
107 | if __name__=='__main__':
108 | with tf.Graph().as_default():
109 | inputs = tf.zeros((32,1024,3))
110 | outputs = get_model(inputs, tf.constant(True))
111 | print(outputs)
112 | loss = get_loss(outputs[0], tf.zeros((32,1024,3)), outputs[1])
113 |
--------------------------------------------------------------------------------
/models/pointnet/model_pointnet2.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | BASE_DIR = os.path.dirname(__file__)
4 | sys.path.append(BASE_DIR)
5 | sys.path.append(os.path.join(BASE_DIR, '..'))
6 | import tensorflow as tf
7 | import numpy as np
8 | import tf_util
9 | from pointnet_util import pointnet_sa_module, pointnet_fp_module
10 |
11 | def placeholder_inputs(batch_size, num_point):
12 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
13 | labels_pl = tf.placeholder(tf.int32, shape=(batch_size, num_point))
14 | smpws_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point))
15 | return pointclouds_pl, labels_pl, smpws_pl
16 |
17 |
18 | def get_model(point_cloud, is_training, scope='', num_point=None, bn_decay=None, ifglobal=False, bn=True, end_points={}):
19 | """ Semantic segmentation PointNet, input is BxNx3, output Bxnum_class """
20 | batch_size = point_cloud.get_shape()[0].value
21 | num_point = point_cloud.get_shape()[1].value
22 | end_points = {}
23 | l0_xyz = point_cloud
24 | l0_points = None
25 | end_points['l0_xyz'] = l0_xyz
26 |
27 | # Layer 1
28 | l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=1024, radius=0.1, nsample=32, mlp=[32,32,64], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer1')
29 | l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=256, radius=0.2, nsample=32, mlp=[64,64,128], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer2')
30 | l3_xyz, l3_points, l3_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=64, radius=0.4, nsample=32, mlp=[128,128,256], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer3')
31 | l4_xyz, l4_points, l4_indices = pointnet_sa_module(l3_xyz, l3_points, npoint=16, radius=0.8, nsample=32, mlp=[256,256,512], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer4')
32 |
33 | # Feature Propagation layers
34 | l3_points = pointnet_fp_module(l3_xyz, l4_xyz, l3_points, l4_points, [256,256], is_training, bn_decay, scope='fa_layer1')
35 | l2_points = pointnet_fp_module(l2_xyz, l3_xyz, l2_points, l3_points, [256,256], is_training, bn_decay, scope='fa_layer2')
36 | l1_points = pointnet_fp_module(l1_xyz, l2_xyz, l1_points, l2_points, [256,128], is_training, bn_decay, scope='fa_layer3')
37 | l0_points = pointnet_fp_module(l0_xyz, l1_xyz, l0_points, l1_points, [128,128,128], is_training, bn_decay, scope='fa_layer4')
38 |
39 | # FC layers
40 | net = tf_util.conv1d(l0_points, 256, 1, padding='VALID', bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
41 | end_points['embedding'] = net
42 | # net = tf_util.dropout(net, keep_prob=0.5, is_training=is_training, scope='dp1')
43 | # net = tf_util.conv1d(net, num_class, 1, padding='VALID', activation_fn=None, scope='fc2')
44 |
45 | return net, end_points
46 |
47 |
48 | def get_loss(pred, label, smpw):
49 | """ pred: BxNxC,
50 | label: BxN,
51 | smpw: BxN """
52 | classify_loss = tf.losses.sparse_softmax_cross_entropy(labels=label, logits=pred, weights=smpw)
53 | tf.summary.scalar('classify loss', classify_loss)
54 | tf.add_to_collection('losses', classify_loss)
55 | return classify_loss
56 |
57 | if __name__=='__main__':
58 | with tf.Graph().as_default():
59 | inputs = tf.zeros((32,2048,3))
60 | net, _ = get_model(inputs, tf.constant(True), 10)
61 | print(net)
62 |
--------------------------------------------------------------------------------
/models/pointnet/model_seg.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import numpy as np
3 | import math
4 | import sys
5 | import os
6 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
7 | sys.path.append(BASE_DIR)
8 | sys.path.append(os.path.join(BASE_DIR, '../utils'))
9 | import tf_util
10 | from transform_nets import input_transform_net, feature_transform_net
11 |
12 | def placeholder_inputs(batch_size, num_point):
13 | pointclouds_pl = tf.placeholder(tf.float32,
14 | shape=(batch_size, num_point, 3))
15 | labels_pl = tf.placeholder(tf.int32,
16 | shape=(batch_size, num_point))
17 | return pointclouds_pl, labels_pl
18 |
19 |
20 | def get_model(point_cloud, is_training, bn_decay=None):
21 | """ Classification PointNet, input is BxNx3, output BxNx50 """
22 | batch_size = point_cloud.get_shape()[0].value
23 | num_point = point_cloud.get_shape()[1].value
24 | end_points = {}
25 |
26 | with tf.variable_scope('transform_net1') as sc:
27 | transform = input_transform_net(point_cloud, is_training, bn_decay, K=3)
28 | point_cloud_transformed = tf.matmul(point_cloud, transform)
29 | input_image = tf.expand_dims(point_cloud_transformed, -1)
30 |
31 | net = tf_util.conv2d(input_image, 64, [1,3],
32 | padding='VALID', stride=[1,1],
33 | bn=True, is_training=is_training,
34 | scope='conv1', bn_decay=bn_decay)
35 | net = tf_util.conv2d(net, 64, [1,1],
36 | padding='VALID', stride=[1,1],
37 | bn=True, is_training=is_training,
38 | scope='conv2', bn_decay=bn_decay)
39 |
40 | with tf.variable_scope('transform_net2') as sc:
41 | transform = feature_transform_net(net, is_training, bn_decay, K=64)
42 | end_points['transform'] = transform
43 | net_transformed = tf.matmul(tf.squeeze(net, axis=[2]), transform)
44 | point_feat = tf.expand_dims(net_transformed, [2])
45 | print(point_feat)
46 |
47 | net = tf_util.conv2d(point_feat, 64, [1,1],
48 | padding='VALID', stride=[1,1],
49 | bn=True, is_training=is_training,
50 | scope='conv3', bn_decay=bn_decay)
51 | net = tf_util.conv2d(net, 128, [1,1],
52 | padding='VALID', stride=[1,1],
53 | bn=True, is_training=is_training,
54 | scope='conv4', bn_decay=bn_decay)
55 | net = tf_util.conv2d(net, 1024, [1,1],
56 | padding='VALID', stride=[1,1],
57 | bn=True, is_training=is_training,
58 | scope='conv5', bn_decay=bn_decay)
59 | global_feat = tf_util.max_pool2d(net, [num_point,1],
60 | padding='VALID', scope='maxpool')
61 | end_points['embedding'] = global_feat
62 | print(global_feat)
63 |
64 | global_feat_expand = tf.tile(global_feat, [1, num_point, 1, 1])
65 | print('global_feat_expand', global_feat_expand)
66 | print('point_feat', point_feat)
67 | concat_feat = tf.concat([point_feat, global_feat_expand], axis=3)
68 | print(concat_feat)
69 |
70 | net = tf_util.conv2d(concat_feat, 512, [1,1],
71 | padding='VALID', stride=[1,1],
72 | bn=True, is_training=is_training,
73 | scope='conv6', bn_decay=bn_decay)
74 | net = tf_util.conv2d(net, 256, [1,1],
75 | padding='VALID', stride=[1,1],
76 | bn=True, is_training=is_training,
77 | scope='conv7', bn_decay=bn_decay)
78 | net = tf_util.conv2d(net, 128, [1,1],
79 | padding='VALID', stride=[1,1],
80 | bn=True, is_training=is_training,
81 | scope='conv8', bn_decay=bn_decay)
82 | net = tf_util.conv2d(net, 128, [1,1],
83 | padding='VALID', stride=[1,1],
84 | bn=True, is_training=is_training,
85 | scope='conv9', bn_decay=bn_decay)
86 |
87 | net = tf_util.conv2d(net, 50, [1,1],
88 | padding='VALID', stride=[1,1], activation_fn=None,
89 | scope='conv10')
90 | net = tf.squeeze(net, [2]) # BxNxC
91 |
92 | return net, end_points
93 |
94 |
95 | def get_loss(pred, label, end_points, reg_weight=0.001):
96 | """ pred: BxNxC,
97 | label: BxN, """
98 | loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=pred, labels=label)
99 | classify_loss = tf.reduce_mean(loss)
100 | tf.summary.scalar('classify loss', classify_loss)
101 |
102 | # Enforce the transformation as orthogonal matrix
103 | transform = end_points['transform'] # BxKxK
104 | K = transform.get_shape()[1].value
105 | mat_diff = tf.matmul(transform, tf.transpose(transform, perm=[0,2,1]))
106 | mat_diff -= tf.constant(np.eye(K), dtype=tf.float32)
107 | mat_diff_loss = tf.nn.l2_loss(mat_diff)
108 | tf.summary.scalar('mat_loss', mat_diff_loss)
109 |
110 | return classify_loss + mat_diff_loss * reg_weight
111 |
112 |
113 | if __name__=='__main__':
114 | with tf.Graph().as_default():
115 | inputs = tf.zeros((32,1024,3))
116 | outputs = get_model(inputs, tf.constant(True))
117 | print(outputs)
118 |
--------------------------------------------------------------------------------
/models/pointnet/model_upconv.py:
--------------------------------------------------------------------------------
1 | """ TF model for point cloud autoencoder. PointNet encoder, UPCONV decoder.
2 | Using GPU Chamfer's distance loss. Required to have 2048 points.
3 |
4 | Author: Charles R. Qi
5 | Date: May 2018
6 | """
7 | import tensorflow as tf
8 | import numpy as np
9 | import math
10 | import sys
11 | import os
12 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
13 | ROOT_DIR = os.path.dirname(BASE_DIR)
14 | sys.path.append(ROOT_DIR)
15 | sys.path.append(os.path.join(ROOT_DIR, 'utils'))
16 | import tf_util
17 | # sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/nn_distance'))
18 | # import tf_nndistance
19 |
20 | def placeholder_inputs(batch_size, num_point):
21 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
22 | labels_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
23 | return pointclouds_pl, labels_pl
24 |
25 |
26 | def get_model(point_cloud, is_training, bn_decay=None):
27 | """ Autoencoder for point clouds.
28 | Input:
29 | point_cloud: TF tensor BxNx3
30 | is_training: boolean
31 | bn_decay: float between 0 and 1
32 | Output:
33 | net: TF tensor BxNx3, reconstructed point clouds
34 | end_points: dict
35 | """
36 | batch_size = point_cloud.get_shape()[0].value
37 | num_point = point_cloud.get_shape()[1].value
38 | assert(num_point==2048)
39 | point_dim = point_cloud.get_shape()[2].value
40 | end_points = {}
41 |
42 | input_image = tf.expand_dims(point_cloud, -1)
43 |
44 | # Encoder
45 | net = tf_util.conv2d(input_image, 64, [1,point_dim],
46 | padding='VALID', stride=[1,1],
47 | bn=True, is_training=is_training,
48 | scope='conv1', bn_decay=bn_decay)
49 | net = tf_util.conv2d(net, 64, [1,1],
50 | padding='VALID', stride=[1,1],
51 | bn=True, is_training=is_training,
52 | scope='conv2', bn_decay=bn_decay)
53 | point_feat = tf_util.conv2d(net, 64, [1,1],
54 | padding='VALID', stride=[1,1],
55 | bn=True, is_training=is_training,
56 | scope='conv3', bn_decay=bn_decay)
57 | net = tf_util.conv2d(point_feat, 128, [1,1],
58 | padding='VALID', stride=[1,1],
59 | bn=True, is_training=is_training,
60 | scope='conv4', bn_decay=bn_decay)
61 | net = tf_util.conv2d(net, 1024, [1,1],
62 | padding='VALID', stride=[1,1],
63 | bn=True, is_training=is_training,
64 | scope='conv5', bn_decay=bn_decay)
65 | global_feat = tf_util.max_pool2d(net, [num_point,1],
66 | padding='VALID', scope='maxpool')
67 |
68 | net = tf.reshape(global_feat, [batch_size, -1])
69 | # net = tf_util.fully_connected(net, 1024, bn=True, is_training=is_training, scope='fc00', bn_decay=bn_decay)
70 | #
71 | net = tf.reshape(net, [batch_size, -1])
72 | end_points['embedding'] = net
73 | # z_log_sigma_sq = tf_util.fully_connected(z_mu, 1024, scope='enc_fc4_sigma', activation_fn=None)
74 | # eps = tf.random_normal(shape=tf.shape(z_log_sigma_sq),
75 | # mean=0, stddev=1, dtype=tf.float32)
76 | # net = net + tf.sqrt(tf.exp(z_log_sigma_sq)) * eps
77 |
78 |
79 | # latent_loss = -0.5 * tf.reduce_sum(1 + z_log_sigma_sq - tf.square(z_mu) - tf.exp(z_log_sigma_sq), axis=1)
80 | # end_points['latent_loss'] = tf.reduce_mean(latent_loss)
81 |
82 | # UPCONV Decoder
83 | net = tf.reshape(net, [batch_size, 1, 2, -1])
84 | net = tf_util.conv2d_transpose(net, 512, kernel_size=[2,2], stride=[2,2], padding='VALID', scope='upconv1', bn=True, bn_decay=bn_decay, is_training=is_training)
85 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[3,3], stride=[1,1], padding='VALID', scope='upconv2', bn=True, bn_decay=bn_decay, is_training=is_training)
86 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[4,5], stride=[2,3], padding='VALID', scope='upconv3', bn=True, bn_decay=bn_decay, is_training=is_training)
87 | net = tf_util.conv2d_transpose(net, 128, kernel_size=[5,7], stride=[3,3], padding='VALID', scope='upconv4', bn=True, bn_decay=bn_decay, is_training=is_training)
88 | net = tf_util.conv2d_transpose(net, 3, kernel_size=[1,1], stride=[1,1], padding='VALID', scope='upconv5', activation_fn=None)
89 | end_points['xyzmap'] = net
90 | net = tf.reshape(net, [batch_size, -1, 3])
91 |
92 | return net, end_points
93 |
94 | def get_loss(pred, label, end_points):
95 | """ pred: BxNx3,
96 | label: BxNx3, """
97 | dists_forward,_,dists_backward,_ = tf_nndistance.nn_distance(pred, label)
98 | loss = tf.reduce_mean(dists_forward+dists_backward)
99 | end_points['pcloss'] = loss
100 | return loss*100, end_points
101 |
102 |
103 | if __name__=='__main__':
104 | with tf.Graph().as_default():
105 | inputs = tf.zeros((32,2048,3))
106 | outputs = get_model(inputs, tf.constant(True))
107 | print(outputs)
108 | loss = get_loss(outputs[0], tf.zeros((32,2048,3)), outputs[1])
109 |
--------------------------------------------------------------------------------
/models/pointnet/model_vae.py:
--------------------------------------------------------------------------------
1 | """ TF model for point cloud autoencoder. PointNet encoder, UPCONV decoder.
2 | Using GPU Chamfer's distance loss. Required to have 2048 points.
3 |
4 | Author: Charles R. Qi
5 | Date: May 2018
6 | """
7 | import tensorflow as tf
8 | import numpy as np
9 | import math
10 | import sys
11 | import os
12 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
13 | ROOT_DIR = os.path.dirname(BASE_DIR)
14 | sys.path.append(ROOT_DIR)
15 | sys.path.append(os.path.join(ROOT_DIR, 'utils'))
16 | import tf_util
17 | # sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/nn_distance'))
18 | # import tf_nndistance
19 |
20 | def placeholder_inputs(batch_size, num_point):
21 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
22 | labels_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
23 | return pointclouds_pl, labels_pl
24 |
25 |
26 | def get_model(point_cloud, is_training, bn_decay=None):
27 | """ Autoencoder for point clouds.
28 | Input:
29 | point_cloud: TF tensor BxNx3
30 | is_training: boolean
31 | bn_decay: float between 0 and 1
32 | Output:
33 | net: TF tensor BxNx3, reconstructed point clouds
34 | end_points: dict
35 | """
36 | batch_size = point_cloud.get_shape()[0].value
37 | num_point = point_cloud.get_shape()[1].value
38 | assert(num_point==2048)
39 | point_dim = point_cloud.get_shape()[2].value
40 | end_points = {}
41 |
42 | input_image = tf.expand_dims(point_cloud, -1)
43 |
44 | # Encoder
45 | net = tf_util.conv2d(input_image, 64, [1,point_dim],
46 | padding='VALID', stride=[1,1],
47 | bn=True, is_training=is_training,
48 | scope='conv1', bn_decay=bn_decay)
49 | net = tf_util.conv2d(net, 64, [1,1],
50 | padding='VALID', stride=[1,1],
51 | bn=True, is_training=is_training,
52 | scope='conv2', bn_decay=bn_decay)
53 | point_feat = tf_util.conv2d(net, 64, [1,1],
54 | padding='VALID', stride=[1,1],
55 | bn=True, is_training=is_training,
56 | scope='conv3', bn_decay=bn_decay)
57 | net = tf_util.conv2d(point_feat, 128, [1,1],
58 | padding='VALID', stride=[1,1],
59 | bn=True, is_training=is_training,
60 | scope='conv4', bn_decay=bn_decay)
61 | net = tf_util.conv2d(net, 1024, [1,1],
62 | padding='VALID', stride=[1,1],
63 | bn=True, is_training=is_training,
64 | scope='conv5', bn_decay=bn_decay)
65 | global_feat = tf_util.max_pool2d(net, [num_point,1],
66 | padding='VALID', scope='maxpool')
67 |
68 | net = tf.reshape(global_feat, [batch_size, -1])
69 | net = tf_util.fully_connected(net, 1024, bn=True, is_training=is_training, scope='fc00', bn_decay=bn_decay)
70 | #
71 | z_mu = tf.reshape(net, [batch_size, -1])
72 | end_points['embedding'] = z_mu
73 | z_log_sigma_sq = tf_util.fully_connected(z_mu, 1024, scope='enc_fc4_sigma', activation_fn=None)
74 | eps = tf.random_normal(shape=tf.shape(z_log_sigma_sq),
75 | mean=0, stddev=1, dtype=tf.float32)
76 | net = net + tf.sqrt(tf.exp(z_log_sigma_sq)) * eps
77 |
78 |
79 | # latent_loss = -0.5 * tf.reduce_sum(1 + z_log_sigma_sq - tf.square(z_mu) - tf.exp(z_log_sigma_sq), axis=1)
80 | # end_points['latent_loss'] = tf.reduce_mean(latent_loss)
81 |
82 | # UPCONV Decoder
83 | net = tf.reshape(net, [batch_size, 1, 2, -1])
84 | net = tf_util.conv2d_transpose(net, 512, kernel_size=[2,2], stride=[2,2], padding='VALID', scope='upconv1', bn=True, bn_decay=bn_decay, is_training=is_training)
85 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[3,3], stride=[1,1], padding='VALID', scope='upconv2', bn=True, bn_decay=bn_decay, is_training=is_training)
86 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[4,5], stride=[2,3], padding='VALID', scope='upconv3', bn=True, bn_decay=bn_decay, is_training=is_training)
87 | net = tf_util.conv2d_transpose(net, 128, kernel_size=[5,7], stride=[3,3], padding='VALID', scope='upconv4', bn=True, bn_decay=bn_decay, is_training=is_training)
88 | net = tf_util.conv2d_transpose(net, 3, kernel_size=[1,1], stride=[1,1], padding='VALID', scope='upconv5', activation_fn=None)
89 | end_points['xyzmap'] = net
90 | net = tf.reshape(net, [batch_size, -1, 3])
91 |
92 | return net, end_points
93 |
94 | def get_loss(pred, label, end_points):
95 | """ pred: BxNx3,
96 | label: BxNx3, """
97 | dists_forward,_,dists_backward,_ = tf_nndistance.nn_distance(pred, label)
98 | loss = tf.reduce_mean(dists_forward+dists_backward)
99 | end_points['pcloss'] = loss
100 | return loss*100, end_points
101 |
102 |
103 | if __name__=='__main__':
104 | with tf.Graph().as_default():
105 | inputs = tf.zeros((32,2048,3))
106 | outputs = get_model(inputs, tf.constant(True))
107 | print(outputs)
108 | loss = get_loss(outputs[0], tf.zeros((32,2048,3)), outputs[1])
109 |
--------------------------------------------------------------------------------
/models/pointnet/model_withtransform.py:
--------------------------------------------------------------------------------
1 | """ TF model for point cloud autoencoder. PointNet encoder, FC decoder.import tensorflow as tf
2 | import numpy as np
3 | import math
4 | import os
5 | import sys
6 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
7 | ROOT_DIR = os.path.dirname(BASE_DIR)
8 | sys.path.append(os.path.join(ROOT_DIR))
9 | import models.pointnet.model as pointnet
10 | from models.ffd import *
11 | try:
12 | import models.tf_ops.approxmatch.tf_approxmatch as tf_approxmatch
13 | import models.tf_ops.nn_distance.tf_nndistance as tf_nndistance
14 | except:
15 | import models.tf_ops_server.approxmatch.tf_approxmatch as tf_approxmatch
16 | import models.tf_ops_server.nn_distance.tf_nndistance as tf_nndistance
17 | Using GPU Chamfer's distance loss.
18 |
19 | Author: Charles R. Qi
20 | Date: May 2018
21 | """
22 | import tensorflow as tf
23 | import numpy as np
24 | import math
25 | import sys
26 | import os
27 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
28 | ROOT_DIR = os.path.dirname(BASE_DIR)
29 | sys.path.append(os.path.join(ROOT_DIR))
30 | import tf_util
31 | from transform_nets import input_transform_net, feature_transform_net
32 | # sys.path.append(os.path.join(ROOT_DIR, 'tf_ops/nn_distance'))
33 | # import tf_nndistance
34 |
35 | def placeholder_inputs(batch_size, num_point):
36 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
37 | labels_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
38 | return pointclouds_pl, labels_pl
39 |
40 |
41 | def get_model(point_cloud, is_training, scope='', num_point=None, bn_decay=None, ifglobal=False, bn=True, end_points={}):
42 | """ Autoencoder for point clouds.
43 | Input:
44 | point_cloud: TF tensor BxNx3
45 | is_training: boolean
46 | bn_decay: float between 0 and 1
47 | Output:
48 | net: TF tensor BxNx3, reconstructed point clouds
49 | end_points: dict
50 | """
51 | """ Classification PointNet, input is BxNx3, output BxNx50 """
52 | batch_size = point_cloud.get_shape()[0].value
53 | num_point = point_cloud.get_shape()[1].value
54 | end_points = {}
55 |
56 | with tf.variable_scope('transform_net1') as sc:
57 | transform = input_transform_net(point_cloud, is_training, bn_decay, K=3)
58 | point_cloud_transformed = tf.matmul(point_cloud, transform)
59 | input_image = tf.expand_dims(point_cloud_transformed, -1)
60 |
61 | net = tf_util.conv2d(input_image, 64, [1,3],
62 | padding='VALID', stride=[1,1],
63 | bn=True, is_training=is_training,
64 | scope='conv1', bn_decay=bn_decay)
65 | net = tf_util.conv2d(net, 64, [1,1],
66 | padding='VALID', stride=[1,1],
67 | bn=True, is_training=is_training,
68 | scope='conv2', bn_decay=bn_decay)
69 |
70 | with tf.variable_scope('transform_net2') as sc:
71 | transform = feature_transform_net(net, is_training, bn_decay, K=64)
72 | end_points['transform'] = transform
73 | net_transformed = tf.matmul(tf.squeeze(net, axis=[2]), transform)
74 | point_feat = tf.expand_dims(net_transformed, [2])
75 | print(point_feat)
76 |
77 | net = tf_util.conv2d(point_feat, 64, [1,1],
78 | padding='VALID', stride=[1,1],
79 | bn=True, is_training=is_training,
80 | scope='conv3', bn_decay=bn_decay)
81 | net = tf_util.conv2d(net, 128, [1,1],
82 | padding='VALID', stride=[1,1],
83 | bn=True, is_training=is_training,
84 | scope='conv4', bn_decay=bn_decay)
85 | pointwise = tf_util.conv2d(net, 1024, [1,1],
86 | padding='VALID', stride=[1,1],
87 | bn=True, is_training=is_training,
88 | scope='conv5', bn_decay=bn_decay)
89 |
90 |
91 | global_feat = tf.reduce_max(pointwise, axis = 1, keep_dims=True)
92 |
93 | print('maxpoolglobal_feat', global_feat.get_shape())
94 |
95 | feat0 = tf.reshape(global_feat, [batch_size, 1024])
96 |
97 | # FC Decoder
98 | net = None
99 | # if ifglobal:
100 | feat = tf_util.fully_connected(feat0, 1024, bn=bn, is_training=is_training, scope='fc1', bn_decay=bn_decay)
101 | feat = tf_util.fully_connected(feat, 1024, bn=bn, is_training=is_training, scope='fc2', bn_decay=bn_decay)
102 | # if num_point is not None:
103 | # net = tf_util.fully_connected(feat, num_point * 3, activation_fn=None, scope='fc3')
104 | # net = tf.reshape(net, (batch_size, num_point, 3))
105 | # end_points['pc'] = net
106 | end_points['embedding'] = feat
107 | end_points['pointwise'] = pointwise
108 |
109 | return net, end_points
110 |
111 | # def get_loss(pred, label, end_points):
112 | # """ pred: BxNx3,
113 | # label: BxNx3, """
114 | # dists_forward,_,dists_backward,_ = tf_nndistance.nn_distance(pred, label)
115 | # loss = tf.reduce_mean(dists_forward+dists_backward)
116 | # end_points['pcloss'] = loss
117 | # return loss*100, end_points
118 |
119 | def get_decoder(embedding, is_training, scope='', bn_decay=None, bn=True):
120 |
121 | batch_size = embedding.get_shape()[0].value
122 | net = tf_util.fully_connected(embedding, 512, bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
123 | net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training, scope='fc2', bn_decay=bn_decay)
124 | net = tf_util.fully_connected(net, 1024*3, activation_fn=None, scope='fc3')
125 | pc_fc = tf.reshape(net, (batch_size, -1, 3))
126 |
127 | # UPCONV Decoder
128 | net = tf.reshape(embedding, [batch_size, 1, 1, -1])
129 | net = tf_util.conv2d_transpose(net, 512, kernel_size=[2,2], stride=[1,1], padding='VALID', scope='upconv1', bn=True, bn_decay=bn_decay, is_training=is_training)
130 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[3,3], stride=[1,1], padding='VALID', scope='upconv2', bn=True, bn_decay=bn_decay, is_training=is_training)
131 | net = tf_util.conv2d_transpose(net, 256, kernel_size=[4,4], stride=[2,2], padding='VALID', scope='upconv3', bn=True, bn_decay=bn_decay, is_training=is_training)
132 | net = tf_util.conv2d_transpose(net, 128, kernel_size=[5,5], stride=[3,3], padding='VALID', scope='upconv4', bn=True, bn_decay=bn_decay, is_training=is_training)
133 | net = tf_util.conv2d_transpose(net, 3, kernel_size=[1,1], stride=[1,1], padding='VALID', scope='upconv5', activation_fn=None)
134 |
135 | pc_upconv = tf.reshape(net, [batch_size, -1, 3])
136 |
137 | # Set union
138 | reconst_pc = tf.concat(values=[pc_fc,pc_upconv], axis=1)
139 |
140 | return reconst_pc
141 |
142 | if __name__=='__main__':
143 | with tf.Graph().as_default():
144 | inputs = tf.zeros((32,1024,3))
145 | outputs = get_model(inputs, tf.constant(True))
146 | print(outputs)
147 | loss = get_loss(outputs[0], tf.zeros((32,1024,3)), outputs[1])
148 |
--------------------------------------------------------------------------------
/models/pointnet/pointnet2_cls_msg.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | BASE_DIR = os.path.dirname(__file__)
4 | sys.path.append(BASE_DIR)
5 | sys.path.append(os.path.join(BASE_DIR, '../utils'))
6 | import tensorflow as tf
7 | import numpy as np
8 | import tf_util
9 | from pointnet_util import pointnet_sa_module, pointnet_sa_module_msg
10 | from pointnet_util import pointnet_sa_module, pointnet_fp_module
11 |
12 |
13 | def placeholder_inputs(batch_size, num_point):
14 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
15 | labels_pl = tf.placeholder(tf.int32, shape=(batch_size))
16 | return pointclouds_pl, labels_pl
17 |
18 |
19 | def get_model(point_cloud, is_training, scope='', num_point=None, bn_decay=None, ifglobal=False, bn=True, end_points={}):
20 | """ Classification PointNet, input is BxNx3, output Bx40 """
21 | batch_size = point_cloud.get_shape()[0].value
22 | num_point = point_cloud.get_shape()[1].value
23 | end_points = {}
24 |
25 | l0_xyz = point_cloud
26 | l0_points = None
27 |
28 | # Set abstraction layers
29 | l1_xyz, l1_points = pointnet_sa_module_msg(l0_xyz, l0_points, 512, [0.1,0.2,0.4], [16,32,128], [[32,32,64], [64,64,128], [64,96,128]], is_training, bn_decay, scope='layer1', use_nchw=True, bn = bn)
30 | l2_xyz, l2_points = pointnet_sa_module_msg(l1_xyz, l1_points, 128, [0.2,0.4,0.8], [32,64,128], [[64,64,128], [128,128,256], [128,128,256]], is_training, bn_decay, scope='layer2', bn = bn)
31 | l3_xyz, l3_points, _ = pointnet_sa_module(l2_xyz, l2_points, npoint=None, radius=None, nsample=None, mlp=[256,512,1024], mlp2=None, group_all=True, is_training=is_training, bn_decay=bn_decay, scope='layer3', bn = bn)
32 |
33 | # Fully connected layers
34 | net = tf.reshape(l3_points, [batch_size, -1])
35 | net = tf_util.fully_connected(net, 512, bn=bn, is_training=is_training, scope='fc1', bn_decay=bn_decay)
36 | end_points['embedding'] = net
37 | # net = tf_util.dropout(net, keep_prob=0.4, is_training=is_training, scope='dp1')
38 | # net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training, scope='fc2', bn_decay=bn_decay)
39 | # net = tf_util.dropout(net, keep_prob=0.4, is_training=is_training, scope='dp2')
40 | # net = tf_util.fully_connected(net, 40, activation_fn=None, scope='fc3')
41 | end_points['l2_xyz'] = l2_xyz
42 | end_points['l3_xyz'] = l3_xyz
43 | end_points['l1_xyz'] = l1_xyz
44 | end_points['l0_xyz'] = l0_xyz
45 | end_points['l2_points'] = l2_points
46 | end_points['l3_points'] = l3_points
47 | end_points['l1_points'] = l1_points
48 | end_points['l0_points'] = l0_points
49 |
50 | return net, end_points
51 |
52 | def get_decoder(embedding, is_training, scope='pointnet2_decoder', bn_decay=None, bn=True, end_points = {}):
53 | with tf.name_scope(scope) as sc:
54 | l2_xyz = end_points['l2_xyz']
55 | l3_xyz = end_points['l3_xyz']
56 | l1_xyz = end_points['l1_xyz']
57 | l0_xyz = end_points['l0_xyz']
58 | l2_points = end_points['l2_points']
59 | l3_points = end_points['l3_points']
60 | l1_points = end_points['l1_points']
61 | l0_points = end_points['l0_points']
62 |
63 | batch_size = embedding.get_shape()[0].value
64 | # net = tf_util.fully_connected(embedding, 512, bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
65 | # net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training, scope='fc2', bn_decay=bn_decay)
66 | # net = tf_util.fully_connected(net, 1024*3, activation_fn=None, scope='fc3')
67 | # pc_fc = tf.reshape(net, (batch_size, -1, 3))
68 |
69 | embedding = tf.expand_dims(embedding, axis=1)
70 | l3_points = tf.concat([embedding, l3_points], axis = -1)
71 |
72 | # Feature Propagation layers
73 | l2_points = pointnet_fp_module(l2_xyz, l3_xyz, l2_points, l3_points, [256,256], is_training, bn_decay, scope='fa_layer1')
74 | l1_points = pointnet_fp_module(l1_xyz, l2_xyz, l1_points, l2_points, [256,128], is_training, bn_decay, scope='fa_layer2')
75 | l0_points = pointnet_fp_module(l0_xyz, l1_xyz, l0_points, l1_points, [128,128,128], is_training, bn_decay, scope='fa_layer3')
76 |
77 | # FC layers
78 | net = tf_util.conv1d(l0_points, 128, 1, padding='VALID', bn=True, is_training=is_training, scope='decoder_fc1', bn_decay=bn_decay)
79 | net = tf_util.conv1d(l0_points, 3, 1, padding='VALID', bn=False, is_training=is_training, scope='decoder_fc2', bn_decay=None, activation_fn=None)
80 | # net = tf_util.conv2d_transpose(net, 3, kernel_size=[1,1], stride=[1,1], padding='VALID', scope='fc2', activation_fn=None)
81 |
82 | reconst_pc = tf.reshape(net, [batch_size, -1, 3])
83 |
84 |
85 | return reconst_pc
86 |
87 | def get_loss(pred, label, end_points):
88 | """ pred: B*NUM_CLASSES,
89 | label: B, """
90 | loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=pred, labels=label)
91 | classify_loss = tf.reduce_mean(loss)
92 | tf.summary.scalar('classify loss', classify_loss)
93 | tf.add_to_collection('losses', classify_loss)
94 | return classify_loss
95 |
96 |
97 | if __name__=='__main__':
98 | with tf.Graph().as_default():
99 | inputs = tf.zeros((32,1024,3))
100 | net, _ = get_model(inputs, tf.constant(True))
101 | print(net)
102 |
--------------------------------------------------------------------------------
/models/pointnet/pointnet2_part_seg.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | BASE_DIR = os.path.dirname(__file__)
4 | sys.path.append(BASE_DIR)
5 | sys.path.append(os.path.join(BASE_DIR, '..'))
6 | import tensorflow as tf
7 | import numpy as np
8 | import tf_util
9 | from pointnet_util import pointnet_sa_module, pointnet_fp_module
10 |
11 | def placeholder_inputs(batch_size, num_point):
12 | pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 6))
13 | labels_pl = tf.placeholder(tf.int32, shape=(batch_size, num_point))
14 | return pointclouds_pl, labels_pl
15 |
16 |
17 | def get_model(point_cloud, is_training, scope='', num_point=None, bn_decay=None, ifglobal=False, bn=True, end_points={}):
18 | """ Part segmentation PointNet, input is BxNx6 (XYZ NormalX NormalY NormalZ), output Bx50 """
19 | batch_size = point_cloud.get_shape()[0].value
20 | num_point = point_cloud.get_shape()[1].value
21 | end_points = {}
22 | l0_xyz = tf.slice(point_cloud, [0,0,0], [-1,-1,3])
23 | l0_points = None#tf.slice(point_cloud, [0,0,3], [-1,-1,3])
24 |
25 | # Set Abstraction layers
26 | l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=512, radius=0.2, nsample=64, mlp=[64,64,128], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer1')
27 | l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=128, radius=0.4, nsample=64, mlp=[128,128,256], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer2')
28 | l3_xyz, l3_points, l3_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=None, radius=None, nsample=None, mlp=[256,512,1024], mlp2=None, group_all=True, is_training=is_training, bn_decay=bn_decay, scope='layer3')
29 |
30 | # Feature Propagation layers
31 | l2_points = pointnet_fp_module(l2_xyz, l3_xyz, l2_points, l3_points, [256,256], is_training, bn_decay, scope='fa_layer1')
32 | l1_points = pointnet_fp_module(l1_xyz, l2_xyz, l1_points, l2_points, [256,128], is_training, bn_decay, scope='fa_layer2')
33 | l0_points = pointnet_fp_module(l0_xyz, l1_xyz, tf.concat([l0_xyz,l0_points],axis=-1), l1_points, [128,128,128], is_training, bn_decay, scope='fa_layer3')
34 |
35 | # FC layers
36 | net = tf_util.conv1d(l0_points, 128, 1, padding='VALID', bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
37 | end_points['embedding'] = net
38 | net = tf_util.dropout(net, keep_prob=0.5, is_training=is_training, scope='dp1')
39 | net = tf_util.conv1d(net, 50, 1, padding='VALID', activation_fn=None, scope='fc2')
40 |
41 | return net, end_points
42 |
43 |
44 | def get_loss(pred, label):
45 | """ pred: BxNxC,
46 | label: BxN, """
47 | loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=pred, labels=label)
48 | classify_loss = tf.reduce_mean(loss)
49 | tf.summary.scalar('classify loss', classify_loss)
50 | tf.add_to_collection('losses', classify_loss)
51 | return classify_loss
52 |
53 | if __name__=='__main__':
54 | with tf.Graph().as_default():
55 | inputs = tf.zeros((32,2048,6))
56 | net, _ = get_model(inputs, tf.constant(True))
57 | print(net)
58 |
--------------------------------------------------------------------------------
/models/pointnet/transform_nets.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import numpy as np
3 | import sys
4 | import os
5 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
6 | sys.path.append(BASE_DIR)
7 | sys.path.append(os.path.join(BASE_DIR, '../utils'))
8 | import tf_util
9 |
10 | def input_transform_net(point_cloud, is_training, bn_decay=None, K=3):
11 | """ Input (XYZ) Transform Net, input is BxNx3 gray image
12 | Return:
13 | Transformation matrix of size 3xK """
14 | batch_size = point_cloud.get_shape()[0].value
15 | num_point = point_cloud.get_shape()[1].value
16 |
17 | input_image = tf.expand_dims(point_cloud, -1)
18 | net = tf_util.conv2d(input_image, 64, [1,3],
19 | padding='VALID', stride=[1,1],
20 | bn=True, is_training=is_training,
21 | scope='tconv1', bn_decay=bn_decay)
22 | net = tf_util.conv2d(net, 128, [1,1],
23 | padding='VALID', stride=[1,1],
24 | bn=True, is_training=is_training,
25 | scope='tconv2', bn_decay=bn_decay)
26 | net = tf_util.conv2d(net, 1024, [1,1],
27 | padding='VALID', stride=[1,1],
28 | bn=True, is_training=is_training,
29 | scope='tconv3', bn_decay=bn_decay)
30 | net = tf_util.max_pool2d(net, [num_point,1],
31 | padding='VALID', scope='tmaxpool')
32 |
33 | net = tf.reshape(net, [batch_size, -1])
34 | net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,
35 | scope='tfc1', bn_decay=bn_decay)
36 | net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,
37 | scope='tfc2', bn_decay=bn_decay)
38 |
39 | with tf.variable_scope('transform_XYZ') as sc:
40 | assert(K==3)
41 | weights = tf.get_variable('weights', [256, 3*K],
42 | initializer=tf.constant_initializer(0.0),
43 | dtype=tf.float32)
44 | biases = tf.get_variable('biases', [3*K],
45 | initializer=tf.constant_initializer(0.0),
46 | dtype=tf.float32)
47 | biases += tf.constant([1,0,0,0,1,0,0,0,1], dtype=tf.float32)
48 | transform = tf.matmul(net, weights)
49 | transform = tf.nn.bias_add(transform, biases)
50 |
51 | transform = tf.reshape(transform, [batch_size, 3, K])
52 | return transform
53 |
54 |
55 | def feature_transform_net(inputs, is_training, bn_decay=None, K=64):
56 | """ Feature Transform Net, input is BxNx1xK
57 | Return:
58 | Transformation matrix of size KxK """
59 | batch_size = inputs.get_shape()[0].value
60 | num_point = inputs.get_shape()[1].value
61 |
62 | net = tf_util.conv2d(inputs, 64, [1,1],
63 | padding='VALID', stride=[1,1],
64 | bn=True, is_training=is_training,
65 | scope='tconv1', bn_decay=bn_decay)
66 | net = tf_util.conv2d(net, 128, [1,1],
67 | padding='VALID', stride=[1,1],
68 | bn=True, is_training=is_training,
69 | scope='tconv2', bn_decay=bn_decay)
70 | net = tf_util.conv2d(net, 1024, [1,1],
71 | padding='VALID', stride=[1,1],
72 | bn=True, is_training=is_training,
73 | scope='tconv3', bn_decay=bn_decay)
74 | net = tf_util.max_pool2d(net, [num_point,1],
75 | padding='VALID', scope='tmaxpool')
76 |
77 | net = tf.reshape(net, [batch_size, -1])
78 | net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,
79 | scope='tfc1', bn_decay=bn_decay)
80 | net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,
81 | scope='tfc2', bn_decay=bn_decay)
82 |
83 | with tf.variable_scope('transform_feat') as sc:
84 | weights = tf.get_variable('weights', [256, K*K],
85 | initializer=tf.constant_initializer(0.0),
86 | dtype=tf.float32)
87 | biases = tf.get_variable('biases', [K*K],
88 | initializer=tf.constant_initializer(0.0),
89 | dtype=tf.float32)
90 | biases += tf.constant(np.eye(K).flatten(), dtype=tf.float32)
91 | transform = tf.matmul(net, weights)
92 | transform = tf.nn.bias_add(transform, biases)
93 |
94 | transform = tf.reshape(transform, [batch_size, K, K])
95 | return transform
96 |
--------------------------------------------------------------------------------
/models/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
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 | 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 |
--------------------------------------------------------------------------------
/models/tf_ops/grouping/test/query_ball_point_block.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 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 |
--------------------------------------------------------------------------------
/models/tf_ops/grouping/test/query_ball_point_grid.cu:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include // memset
4 | #include // rand, RAND_MAX
5 | #include // sqrtf
6 | #include
7 | #include
8 | using namespace std;
9 | float randomf(){
10 | return (rand()+0.5)/(RAND_MAX+1.0);
11 | }
12 | static double get_time(){
13 | timespec tp;
14 | clock_gettime(CLOCK_MONOTONIC,&tp);
15 | return tp.tv_sec+tp.tv_nsec*1e-9;
16 | }
17 | // input: radius (1), nsample (1), xyz1 (b,n,3), xyz2 (b,m,3)
18 | // output: idx (b,m,nsample)
19 | __global__ void query_ball_point_gpu(int b, int n, int m, float radius, int nsample, const float *xyz1, const float *xyz2, int *idx) {
20 | int batch_index = blockIdx.x;
21 | xyz1 += n*3*batch_index;
22 | xyz2 += m*3*batch_index;
23 | idx += m*nsample*batch_index;
24 |
25 | int index = threadIdx.x;
26 | int stride = blockDim.x;
27 |
28 | for (int j=index;j>>(b,n,m,radius,nsample,xyz1,xyz2,idx);
123 | cudaDeviceSynchronize();
124 | printf("query_ball_point gpu time %f\n",get_time()-t0);
125 |
126 | t0=get_time();
127 | group_point_gpu<<>>(b,n,c,m,nsample,points,idx,out);
128 | cudaDeviceSynchronize();
129 | printf("grou_point gpu time %f\n",get_time()-t0);
130 |
131 | t0=get_time();
132 | group_point_grad_gpu<<>>(b,n,c,m,nsample,grad_out,idx,grad_points);
133 | cudaDeviceSynchronize();
134 | printf("grou_point_grad gpu time %f\n",get_time()-t0);
135 |
136 | cudaFree(xyz1);
137 | cudaFree(xyz2);
138 | cudaFree(points);
139 | cudaFree(idx);
140 | cudaFree(out);
141 | cudaFree(grad_out);
142 | cudaFree(grad_points);
143 | return 0;
144 | }
145 |
--------------------------------------------------------------------------------
/models/tf_ops/grouping/test/selection_sort.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 | // input: k (1), distance matrix dist (b,m,n)
19 | // output: idx (b,m,n), val (b,m,n)
20 | void selection_sort_cpu(int b, int n, int m, int k, const float *dist, int *idx, float *val) {
21 | float *p_dist;
22 | float tmp;
23 | int tmpi;
24 | for (int i=0;i
2 | #include
3 | #include // memset
4 | #include // rand, RAND_MAX
5 | #include // sqrtf
6 | #include
7 | #include
8 | using namespace std;
9 | float randomf(){
10 | return (rand()+0.5)/(RAND_MAX+1.0);
11 | }
12 | static double get_time(){
13 | timespec tp;
14 | clock_gettime(CLOCK_MONOTONIC,&tp);
15 | return tp.tv_sec+tp.tv_nsec*1e-9;
16 | }
17 |
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 |
--------------------------------------------------------------------------------
/models/tf_ops/grouping/test/selection_sort_const.cu:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include // memset
4 | #include // rand, RAND_MAX
5 | #include // sqrtf
6 | #include
7 | #include
8 | using namespace std;
9 | float randomf(){
10 | return (rand()+0.5)/(RAND_MAX+1.0);
11 | }
12 | static double get_time(){
13 | timespec tp;
14 | clock_gettime(CLOCK_MONOTONIC,&tp);
15 | return tp.tv_sec+tp.tv_nsec*1e-9;
16 | }
17 |
18 | // input: k (1), distance matrix dist (b,m,n)
19 | // output: idx (b,m,n), dist_out (b,m,n)
20 | __global__ void selection_sort_gpu(int b, int n, int m, int k, const float *dist, int *outi, float *out) {
21 | int batch_index = blockIdx.x;
22 | dist+=m*n*batch_index;
23 | outi+=m*n*batch_index;
24 | out+=m*n*batch_index;
25 |
26 | int index = threadIdx.x;
27 | int stride = blockDim.x;
28 |
29 | // copy from dist to dist_out
30 | for (int j=index;j>>(b,n,m,k,dist,idx,dist_out);
84 | cudaDeviceSynchronize();
85 | printf("selection sort cpu time %f\n",get_time()-t0);
86 |
87 | //for (int i=0;i>>(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 |
--------------------------------------------------------------------------------
/models/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 |
--------------------------------------------------------------------------------
/models/tf_ops/mesh_laplacian/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/laughtervv/3DN/81e3651d780478139c3b8dee5e737ce565813900/models/tf_ops/mesh_laplacian/__init__.py
--------------------------------------------------------------------------------
/models/tf_ops/mesh_laplacian/tf_meshlaplacian.py:
--------------------------------------------------------------------------------
1 | """
2 | Mesh laplacian Operator
3 | Weiyue Wang
4 | """
5 |
6 | import tensorflow as tf
7 | from tensorflow.python.framework import ops
8 | import sys
9 | import os
10 | import time
11 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
12 | mesh_laplacian_module=tf.load_op_library(os.path.join(BASE_DIR, 'tf_meshlaplacian_so.so'))
13 |
14 | def mesh_laplacian(verts,nverts,tris,ntris):
15 | '''
16 | .Input("verts: float32")
17 | .Input("nverts: int32")
18 | .Input("tris: int32")
19 | .Input("ntris: int32")
20 | .Output("laplacian: float32")
21 | .Output("count: int32")
22 | .Output("nb: int32");
23 | '''
24 | return mesh_laplacian_module.mesh_laplacian(verts,nverts,tris,ntris)
25 |
26 | @ops.RegisterGradient('MeshLaplacian')
27 | def _mesh_laplacian_grad(op, grad_laplacian, grad_count, grad_nb):
28 | '''
29 | .Input("nverts: int32")
30 | .Input("count: int32")
31 | .Input("nb: int32")
32 | .Input("grad_laplacian: float32")
33 | .Output("grad_verts: float32");
34 | '''
35 |
36 | nverts = op.inputs[1]
37 | # global count
38 | count = op.outputs[1]
39 | # global nb
40 | nb = op.outputs[2]
41 | # global aaa
42 | # aaa = grad_laplacian
43 | grad_verts = mesh_laplacian_module.mesh_laplacian_grad(nverts,count,nb,grad_laplacian)
44 |
45 | return [grad_verts,None,None,None]
46 |
47 |
48 | if __name__=='__main__':
49 | import numpy as np
50 | import random
51 | import time
52 | from tensorflow.python.ops.gradient_checker import compute_gradient
53 | random.seed(100)
54 | np.random.seed(100)
55 |
56 |
57 | def write_off(fn, verts, faces):
58 | file = open(fn, 'w')
59 | file.write('OFF\n')
60 | file.write('%d %d %d\n' % (len(verts), len(faces), 0))
61 | for vert in verts:
62 | file.write('%f %f %f\n' % (vert[0], vert[1], vert[2]))
63 | # verts.append([float(s) for s in readline().strip().split(' ')])
64 | for face in faces:
65 | file.write('3 %f %f %f\n' % (face[0], face[1], face[2]))
66 | # faces.append([int(s) for s in readline().strip().split(' ')][1:])
67 | file.close()
68 | return
69 |
70 | def read_off(fn):
71 | file = open(fn, 'r')
72 | if 'OFF' != file.readline().strip():
73 | print ('Not a valid OFF header')
74 | return
75 | n_verts, n_faces, n_dontknow = tuple([int(s) for s in file.readline().strip().split(' ')])
76 | verts = []
77 | for i_vert in range(n_verts):
78 | verts.append([float(s) for s in file.readline().strip().split(' ')])
79 | faces = []
80 | for i_face in range(n_faces):
81 | faces.append([int(s) for s in file.readline().strip().split(' ')][1:])
82 | file.close()
83 | return np.asarray(verts,dtype=np.float32), np.asarray(faces, dtype=np.int32)
84 |
85 |
86 | test1 = True
87 | test2 = False
88 | test1 = False
89 | test2 = True
90 |
91 | with tf.Session('') as sess:
92 |
93 | vertices, faces = read_off('bunny.off')
94 |
95 | if test1:
96 | verts=tf.expand_dims(tf.constant(vertices),0)
97 | tris=tf.expand_dims(tf.constant(faces),0)
98 | nverts = tf.constant([[len(vertices)]],dtype=tf.int32)
99 | ntris = tf.constant([[len(faces)]],dtype=tf.int32)
100 |
101 | laplacian,_,_ = mesh_laplacian(verts, nverts, tris, ntris)
102 | loss = tf.nn.l2_loss(laplacian - 0)
103 | verts1_grad = tf.gradients(loss, [verts])[0]
104 | laplacian_val, old_count_val, old_nb_val = sess.run([laplacian, count, nb])
105 | for i in range(10):
106 | laplacian_val, count_val, nb_val, verts_val = sess.run([laplacian, count, nb, verts])
107 |
108 | verts_val += 0.3* laplacian_val
109 | verts=tf.constant(verts_val)
110 | laplacian,_,_ = mesh_laplacian(verts, nverts, tris, ntris)
111 |
112 | color = np.squeeze(laplacian_val)
113 | color = 255*(color - np.min(color))/(np.max(color)-np.min(color))
114 | color[:,0]=0
115 | np.savetxt('verts_val.xyz', np.concatenate((vertices, color.astype(np.int8)), axis=1))
116 |
117 | write_off('out.off', np.squeeze(verts_val), faces)
118 | if test2:
119 |
120 | verts1=tf.expand_dims(tf.constant(vertices),0)
121 | tris1=tf.expand_dims(tf.constant(faces),0)
122 | nverts1 = tf.constant([[len(vertices)]],dtype=tf.int32)
123 | ntris1 = tf.constant([[len(faces)]],dtype=tf.int32)
124 |
125 | laplacian1,_,_ = mesh_laplacian(verts1, nverts1, tris1, ntris1)
126 |
127 | vertices[:,1] *= 2
128 | old_verts2 = tf.expand_dims(tf.constant(vertices),0)
129 | verts2=tf.Variable(old_verts2)
130 | tris2=tf.expand_dims(tf.constant(faces),0)
131 | nverts2 = tf.constant([[len(vertices)]],dtype=tf.int32)
132 | ntris2 = tf.constant([[len(faces)]],dtype=tf.int32)
133 |
134 | laplacian2,_,_ = mesh_laplacian(verts2, nverts2, tris2, ntris2)
135 |
136 | #
137 | loss = 10*tf.nn.l2_loss(laplacian2 - laplacian1)
138 | verts2_grad = tf.gradients(loss, [verts2])[0]
139 | #
140 | train=tf.train.GradientDescentOptimizer(learning_rate=0.05).minimize(loss)
141 |
142 | sess.run(tf.initialize_all_variables())
143 | #
144 | old_lossval = 10000
145 | for i in range(500):
146 | _, loss_val, verts2_val, verts1_val, verts2_grad_val,count_val,grad_laplasian_val,old_verts2_val =sess.run([train, loss, verts2, verts1, verts2_grad, count, aaa,old_verts2])#, feed_dict=feed_dict)
147 |
148 | np.savetxt('verts2.xyz', np.squeeze(verts2_val))
149 | np.savetxt('verts1.xyz', np.squeeze(verts1_val))
150 |
151 | write_off('out2.off', np.squeeze(verts2_val), faces)
152 | write_off('old_out2.off', np.squeeze(old_verts2_val), faces)
153 |
154 | write_off('out1.off', np.squeeze(verts1_val), faces)
--------------------------------------------------------------------------------
/models/tf_ops/mesh_laplacian/tf_meshlaplacian_compile.sh:
--------------------------------------------------------------------------------
1 | /usr/local/cuda/bin/nvcc tf_meshlaplacian_g.cu -o tf_meshlaplacian_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC
2 | g++ -std=c++11 tf_meshlaplacian.cpp tf_meshlaplacian_g.cu.o -o tf_meshlaplacian_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0
3 |
4 |
--------------------------------------------------------------------------------
/models/tf_ops/mesh_laplacian/tf_meshlaplacian_g.cu:
--------------------------------------------------------------------------------
1 | //Mesh Laplacian
2 | //Author: Weiyue Wang
3 | //Reference: https://github.com/charlesq34/pointnet-autoencoder/blob/master/tf_ops/nn_distance/tf_nndistance_g.cu
4 | // https://github.com/PointCloudLibrary/pcl/blob/master/tools/mesh_sampling.cpp
5 |
6 | #if GOOGLE_CUDA
7 | #define EIGEN_USE_GPU
8 | #include
9 | #include
10 |
11 |
12 | __device__ void getPoint(const float *vertices, int v_id, float *p){
13 | p[0] = vertices[3* v_id];
14 | p[1] = vertices[3* v_id+1];
15 | p[2] = vertices[3* v_id+2];
16 | }
17 |
18 | __device__ void getTriangle(const int *triangles, int t_id, int &v1, int &v2, int &v3){
19 | v1 = triangles[3 * t_id];
20 | v2 = triangles[3 * t_id + 1];
21 | v3 = triangles[3 * t_id + 2];
22 | }
23 |
24 | __host__ void getTriangle_cpu(const int *triangles, int t_id, int &v1, int &v2, int &v3){
25 | v1 = triangles[3 * t_id];
26 | v2 = triangles[3 * t_id + 1];
27 | v3 = triangles[3 * t_id + 2];
28 | }
29 |
30 | __host__ bool findnb_cpu(const int *nb, int v_id){
31 | bool flag = false;
32 | for (int i=0; i<20; i++)
33 | if (nb[i] == v_id){
34 | flag = true;
35 | break;
36 | }
37 | return flag;
38 | }
39 | __device__ bool findnb(const int *nb, int v_id){
40 | bool flag = false;
41 | for (int i=0; i<20; i++)
42 | if (nb[i] == v_id){
43 | flag = true;
44 | break;
45 | }
46 | return flag;
47 | }
48 |
49 | __device__ void setLaplacian(float *laplacian, int *count, int v_id1, int v_id2, float * p1, float * p2){
50 |
51 | atomicAdd(&laplacian[3 * v_id1], p2[0] - p1[0]);
52 | atomicAdd(&laplacian[3 * v_id1+1], p2[1] - p1[1]);
53 | atomicAdd(&laplacian[3 * v_id1+2], p2[2] - p1[2]);
54 |
55 | atomicAdd(&count[v_id1], 1);
56 |
57 |
58 | atomicAdd(&laplacian[3 * v_id2], p1[0] - p2[0]);
59 | atomicAdd(&laplacian[3 * v_id2+1], p1[1] - p2[1]);
60 | atomicAdd(&laplacian[3 * v_id2+2], p1[2] - p2[2]);
61 |
62 | atomicAdd(&count[v_id2], 1);
63 | }
64 |
65 |
66 | __global__ void InitMeshLaplacianKernel(const int b, const int maxnverts, float* laplacian, int* count){
67 | for (int i=blockIdx.x;i>>(b, maxn_verts, laplacian, count);
128 | cudaMemset(nb, -1, b*maxn_verts*20*sizeof(int));
129 | MeshLaplacianKernel<<<64,512>>>(b, n_verts, maxn_verts, vertices, n_triangles, maxn_triangles, triangles, laplacian, nb, count);
130 | AvgMeshLaplacianKernel<<>>(b, maxn_verts, laplacian, count);
131 |
132 |
133 | }
134 |
135 | /****************** Gradient ******************/
136 | __device__ void setLaplaciangrad (const float * grad_laplacian, float *grad_verts, int v_id1, int v_id2){
137 |
138 | atomicAdd(&grad_verts[3 * v_id1], - 1 * grad_laplacian[3 * v_id1]);
139 | atomicAdd(&grad_verts[3 * v_id1+1], - 1 * grad_laplacian[3 * v_id1+1]);
140 | atomicAdd(&grad_verts[3 * v_id1+2], - 1 * grad_laplacian[3 * v_id1+2]);
141 |
142 | atomicAdd(&grad_verts[3 * v_id2], grad_laplacian[3 * v_id1]);
143 | atomicAdd(&grad_verts[3 * v_id2+1], grad_laplacian[3 * v_id1+1]);
144 | atomicAdd(&grad_verts[3 * v_id2+2], grad_laplacian[3 * v_id1+2]);
145 | }
146 |
147 |
148 | __global__ void MeshLaplacianGradKernel(const int b, const int maxnverts, const int *nverts, const int * nb, const float * grad_laplacian, float* grad_verts){
149 | for (int i=blockIdx.x;i>>(b, maxnverts, nverts, nb, grad_laplacian, grad_verts);
179 | AvgGradKernel<<>>(b, maxnverts, grad_verts, count);
180 | }
181 |
182 | #endif
183 |
184 |
--------------------------------------------------------------------------------
/models/tf_ops/mesh_sampling/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/laughtervv/3DN/81e3651d780478139c3b8dee5e737ce565813900/models/tf_ops/mesh_sampling/__init__.py
--------------------------------------------------------------------------------
/models/tf_ops/mesh_sampling/tf_meshsampling.h:
--------------------------------------------------------------------------------
1 | #ifndef TF_MESHSAMPLING_H_
2 | #define TF_MESHSAMPLING_H_
3 |
4 |
5 | void randomPointTriangle (float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3,
6 | float r1, float r2, float p[3])
7 | {
8 | float r1sqr = std::sqrt (r1);
9 | float OneMinR1Sqr = (1 - r1sqr);
10 | float OneMinR2 = (1 - r2);
11 | a1 *= OneMinR1Sqr;
12 | a2 *= OneMinR1Sqr;
13 | a3 *= OneMinR1Sqr;
14 | b1 *= OneMinR2;
15 | b2 *= OneMinR2;
16 | b3 *= OneMinR2;
17 | c1 = r1sqr * (r2 * c1 + b1) + a1;
18 | c2 = r1sqr * (r2 * c2 + b2) + a2;
19 | c3 = r1sqr * (r2 * c3 + b3) + a3;
20 | p[0] = c1;
21 | p[1] = c2;
22 | p[2] = c3;
23 | }
24 |
25 | #endif// TF_MESHSAMPLING_H_
--------------------------------------------------------------------------------
/models/tf_ops/mesh_sampling/tf_meshsampling_compile.sh:
--------------------------------------------------------------------------------
1 | /usr/local/cuda/bin/nvcc tf_meshsampling_g.cu -o tf_meshsampling_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC
2 | g++ -std=c++11 tf_meshsampling.cpp tf_meshsampling_g.cu.o -o tf_meshsampling_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0
3 |
4 |
--------------------------------------------------------------------------------
/models/tf_ops/nn_distance/README.md:
--------------------------------------------------------------------------------
1 | From https://github.com/fanhqme/PointSetGeneration/tree/master/depthestimate
2 |
--------------------------------------------------------------------------------
/models/tf_ops/nn_distance/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/laughtervv/3DN/81e3651d780478139c3b8dee5e737ce565813900/models/tf_ops/nn_distance/__init__.py
--------------------------------------------------------------------------------
/models/tf_ops/nn_distance/tf_nndistance.py:
--------------------------------------------------------------------------------
1 | """ Compute Chamfer's Distance.
2 |
3 | Original author: Haoqiang Fan.
4 | Modified by Charles R. Qi
5 | """
6 |
7 | import tensorflow as tf
8 | from tensorflow.python.framework import ops
9 | import sys
10 | import os
11 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
12 | nn_distance_module=tf.load_op_library(os.path.join(BASE_DIR, 'tf_nndistance_so.so'))
13 |
14 | def nn_distance(xyz1,xyz2):
15 | '''
16 | Computes the distance of nearest neighbors for a pair of point clouds
17 | input: xyz1: (batch_size,#points_1,3) the first point cloud
18 | input: xyz2: (batch_size,#points_2,3) the second point cloud
19 | output: dist1: (batch_size,#point_1) distance from first to second
20 | output: idx1: (batch_size,#point_1) nearest neighbor from first to second
21 | output: dist2: (batch_size,#point_2) distance from second to first
22 | output: idx2: (batch_size,#point_2) nearest neighbor from second to first
23 | '''
24 | return nn_distance_module.nn_distance(xyz1,xyz2)
25 | #@tf.RegisterShape('NnDistance')
26 | #def _nn_distance_shape(op):
27 | #shape1=op.inputs[0].get_shape().with_rank(3)
28 | #shape2=op.inputs[1].get_shape().with_rank(3)
29 | #return [tf.TensorShape([shape1.dims[0],shape1.dims[1]]),tf.TensorShape([shape1.dims[0],shape1.dims[1]]),
30 | #tf.TensorShape([shape2.dims[0],shape2.dims[1]]),tf.TensorShape([shape2.dims[0],shape2.dims[1]])]
31 | @ops.RegisterGradient('NnDistance')
32 | def _nn_distance_grad(op,grad_dist1,grad_idx1,grad_dist2,grad_idx2):
33 | xyz1=op.inputs[0]
34 | xyz2=op.inputs[1]
35 | idx1=op.outputs[1]
36 | idx2=op.outputs[3]
37 | return nn_distance_module.nn_distance_grad(xyz1,xyz2,grad_dist1,idx1,grad_dist2,idx2)
38 |
39 |
40 | if __name__=='__main__':
41 | import numpy as np
42 | import random
43 | import time
44 | from tensorflow.python.ops.gradient_checker import compute_gradient
45 | random.seed(100)
46 | np.random.seed(100)
47 | with tf.Session('') as sess:
48 | xyz1=np.random.randn(32,16384,3).astype('float32')
49 | xyz2=np.random.randn(32,1024,3).astype('float32')
50 | #with tf.device('/gpu:0'):
51 | if True:
52 | inp1=tf.Variable(xyz1)
53 | inp2=tf.constant(xyz2)
54 | reta,retb,retc,retd=nn_distance(inp1,inp2)
55 | loss=tf.reduce_sum(reta)+tf.reduce_sum(retc)
56 | train=tf.train.GradientDescentOptimizer(learning_rate=0.05).minimize(loss)
57 | sess.run(tf.initialize_all_variables())
58 | t0=time.time()
59 | t1=t0
60 | best=1e100
61 | for i in xrange(100):
62 | trainloss,_=sess.run([loss,train])
63 | newt=time.time()
64 | best=min(best,newt-t1)
65 | print (i,trainloss,(newt-t0)/(i+1),best)
66 | t1=newt
67 | #print sess.run([inp1,retb,inp2,retd])
68 | #grads=compute_gradient([inp1,inp2],[(16,32,3),(16,32,3)],loss,(1,),[xyz1,xyz2])
69 | #for i,j in grads:
70 | #print i.shape,j.shape,np.mean(np.abs(i-j)),np.mean(np.abs(i)),np.mean(np.abs(j))
71 | #for i in xrange(10):
72 | #t0=time.time()
73 | #a,b,c,d=sess.run([reta,retb,retc,retd],feed_dict={inp1:xyz1,inp2:xyz2})
74 | #print 'time',time.time()-t0
75 | #print a.shape,b.shape,c.shape,d.shape
76 | #print a.dtype,b.dtype,c.dtype,d.dtype
77 | #samples=np.array(random.sample(range(xyz2.shape[1]),100),dtype='int32')
78 | #dist1=((xyz1[:,samples,None,:]-xyz2[:,None,:,:])**2).sum(axis=-1).min(axis=-1)
79 | #idx1=((xyz1[:,samples,None,:]-xyz2[:,None,:,:])**2).sum(axis=-1).argmin(axis=-1)
80 | #print np.abs(dist1-a[:,samples]).max()
81 | #print np.abs(idx1-b[:,samples]).max()
82 | #dist2=((xyz2[:,samples,None,:]-xyz1[:,None,:,:])**2).sum(axis=-1).min(axis=-1)
83 | #idx2=((xyz2[:,samples,None,:]-xyz1[:,None,:,:])**2).sum(axis=-1).argmin(axis=-1)
84 | #print np.abs(dist2-c[:,samples]).max()
85 | #print np.abs(idx2-d[:,samples]).max()
86 |
87 |
88 |
--------------------------------------------------------------------------------
/models/tf_ops/nn_distance/tf_nndistance_compile.sh:
--------------------------------------------------------------------------------
1 | /usr/local/cuda/bin/nvcc tf_nndistance_g.cu -o tf_nndistance_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC
2 | g++ -std=c++11 tf_nndistance.cpp tf_nndistance_g.cu.o -o tf_nndistance_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0
3 |
4 |
--------------------------------------------------------------------------------
/models/tf_ops/nn_distance/tf_nndistance_cpu.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import numpy as np
3 |
4 | def nn_distance_cpu(pc1, pc2):
5 | '''
6 | Input:
7 | pc1: float TF tensor in shape (B,N,C) the first point cloud
8 | pc2: float TF tensor in shape (B,M,C) the second point cloud
9 | Output:
10 | dist1: float TF tensor in shape (B,N) distance from first to second
11 | idx1: int32 TF tensor in shape (B,N) nearest neighbor from first to second
12 | dist2: float TF tensor in shape (B,M) distance from second to first
13 | idx2: int32 TF tensor in shape (B,M) nearest neighbor from second to first
14 | '''
15 | N = pc1.get_shape()[1].value
16 | M = pc2.get_shape()[1].value
17 | pc1_expand_tile = tf.tile(tf.expand_dims(pc1,2), [1,1,M,1])
18 | pc2_expand_tile = tf.tile(tf.expand_dims(pc2,1), [1,N,1,1])
19 | pc_diff = pc1_expand_tile - pc2_expand_tile # B,N,M,C
20 | pc_dist = tf.reduce_sum(pc_diff ** 2, axis=-1) # B,N,M
21 | dist1 = tf.reduce_min(pc_dist, axis=2) # B,N
22 | idx1 = tf.argmin(pc_dist, axis=2) # B,N
23 | dist2 = tf.reduce_min(pc_dist, axis=1) # B,M
24 | idx2 = tf.argmin(pc_dist, axis=1) # B,M
25 | return dist1, idx1, dist2, idx2
26 |
27 |
28 | def verify_nn_distance_cup():
29 | np.random.seed(0)
30 | sess = tf.Session()
31 | pc1arr = np.random.random((1,5,3))
32 | pc2arr = np.random.random((1,6,3))
33 | pc1 = tf.constant(pc1arr)
34 | pc2 = tf.constant(pc2arr)
35 | dist1, idx1, dist2, idx2 = nn_distance_cpu(pc1, pc2)
36 | print(sess.run(dist1))
37 | print(sess.run(idx1))
38 | print(sess.run(dist2))
39 | print(sess.run(idx2))
40 |
41 | dist = np.zeros((5,6))
42 | for i in range(5):
43 | for j in range(6):
44 | dist[i,j] = np.sum((pc1arr[0,i,:] - pc2arr[0,j,:]) ** 2)
45 | print(dist)
46 |
47 | if __name__ == '__main__':
48 | verify_nn_distance_cup()
49 |
--------------------------------------------------------------------------------
/models/tf_ops/nn_distance/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 |
161 |
--------------------------------------------------------------------------------
/models/tf_ops/sampling/tf_sampling.py:
--------------------------------------------------------------------------------
1 | ''' Furthest point sampling
2 | Original author: Haoqiang Fan
3 | Modified by Charles R. Qi
4 | All Rights Reserved. 2017.
5 | '''
6 | import tensorflow as tf
7 | from tensorflow.python.framework import ops
8 | import sys
9 | import os
10 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
11 | sys.path.append(BASE_DIR)
12 | sampling_module=tf.load_op_library(os.path.join(BASE_DIR, 'tf_sampling_so.so'))
13 | def prob_sample(inp,inpr):
14 | '''
15 | input:
16 | batch_size * ncategory float32
17 | batch_size * npoints float32
18 | returns:
19 | batch_size * npoints int32
20 | '''
21 | return sampling_module.prob_sample(inp,inpr)
22 | ops.NoGradient('ProbSample')
23 | # TF1.0 API requires set shape in C++
24 | #@tf.RegisterShape('ProbSample')
25 | #def _prob_sample_shape(op):
26 | # shape1=op.inputs[0].get_shape().with_rank(2)
27 | # shape2=op.inputs[1].get_shape().with_rank(2)
28 | # return [tf.TensorShape([shape2.dims[0],shape2.dims[1]])]
29 | def gather_point(inp,idx):
30 | '''
31 | input:
32 | batch_size * ndataset * 3 float32
33 | batch_size * npoints int32
34 | returns:
35 | batch_size * npoints * 3 float32
36 | '''
37 | return sampling_module.gather_point(inp,idx)
38 | #@tf.RegisterShape('GatherPoint')
39 | #def _gather_point_shape(op):
40 | # shape1=op.inputs[0].get_shape().with_rank(3)
41 | # shape2=op.inputs[1].get_shape().with_rank(2)
42 | # return [tf.TensorShape([shape1.dims[0],shape2.dims[1],shape1.dims[2]])]
43 | @tf.RegisterGradient('GatherPoint')
44 | def _gather_point_grad(op,out_g):
45 | inp=op.inputs[0]
46 | idx=op.inputs[1]
47 | return [sampling_module.gather_point_grad(inp,idx,out_g),None]
48 | def farthest_point_sample(npoint,inp):
49 | '''
50 | input:
51 | int32
52 | batch_size * ndataset * 3 float32
53 | returns:
54 | batch_size * npoint int32
55 | '''
56 | return sampling_module.farthest_point_sample(inp, npoint)
57 | ops.NoGradient('FarthestPointSample')
58 |
59 |
60 | if __name__=='__main__':
61 | import numpy as np
62 | np.random.seed(100)
63 | triangles=np.random.rand(1,5,3,3).astype('float32')
64 | with tf.device('/gpu:1'):
65 | inp=tf.constant(triangles)
66 | tria=inp[:,:,0,:]
67 | trib=inp[:,:,1,:]
68 | tric=inp[:,:,2,:]
69 | areas=tf.sqrt(tf.reduce_sum(tf.cross(trib-tria,tric-tria)**2,2)+1e-9)
70 | randomnumbers=tf.random_uniform((1,8192))
71 | triids=prob_sample(areas,randomnumbers)
72 | tria_sample=gather_point(tria,triids)
73 | trib_sample=gather_point(trib,triids)
74 | tric_sample=gather_point(tric,triids)
75 | us=tf.random_uniform((1,8192))
76 | vs=tf.random_uniform((1,8192))
77 | uplusv=1-tf.abs(us+vs-1)
78 | uminusv=us-vs
79 | us=(uplusv+uminusv)*0.5
80 | vs=(uplusv-uminusv)*0.5
81 | pt_sample=tria_sample+(trib_sample-tria_sample)*tf.expand_dims(us,-1)+(tric_sample-tria_sample)*tf.expand_dims(vs,-1)
82 | print 'pt_sample: ', pt_sample
83 | reduced_sample=gather_point(pt_sample,farthest_point_sample(1024,pt_sample))
84 | print reduced_sample
85 | with tf.Session('') as sess:
86 | ret=sess.run(reduced_sample)
87 | print ret.shape,ret.dtype
88 | import cPickle as pickle
89 | pickle.dump(ret,open('1.pkl','wb'),-1)
90 |
--------------------------------------------------------------------------------
/models/tf_ops/sampling/tf_sampling_compile.sh:
--------------------------------------------------------------------------------
1 | #/bin/bash
2 | /usr/local/cuda/bin/nvcc tf_sampling_g.cu -o tf_sampling_g.cu.o -c -O2 -DGOOGLE_CUDA=1 -x cu -Xcompiler -fPIC
3 |
4 | # TF1.2
5 | #g++ -std=c++11 tf_sampling.cpp tf_sampling_g.cu.o -o tf_sampling_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda-8.0/include -lcudart -L /usr/local/cuda-8.0/lib64/ -O2 -D_GLIBCXX_USE_CXX11_ABI=0
6 |
7 | # TF1.4
8 | g++ -std=c++11 tf_sampling.cpp tf_sampling_g.cu.o -o tf_sampling_so.so -shared -fPIC -I /usr/local/lib/python2.7/dist-packages/tensorflow/include -I /usr/local/cuda/include -I /usr/local/lib/python2.7/dist-packages/tensorflow/include/external/nsync/public -lcudart -L /usr/local/cuda/lib64/ -L/usr/local/lib/python2.7/dist-packages/tensorflow -ltensorflow_framework -O2 -D_GLIBCXX_USE_CXX11_ABI=0
9 |
--------------------------------------------------------------------------------
/models/tf_ops/sampling/tf_sampling_g.cu:
--------------------------------------------------------------------------------
1 | /* Furthest point sampling GPU implementation
2 | * Original author: Haoqiang Fan
3 | * Modified by Charles R. Qi
4 | * All Rights Reserved. 2017.
5 | */
6 |
7 | __global__ void cumsumKernel(int b,int n,const float * __restrict__ inp,float * __restrict__ out){
8 | const int BlockSize=2048;
9 | const int paddingLevel=5;
10 | __shared__ float buffer4[BlockSize*4];
11 | __shared__ float buffer[BlockSize+(BlockSize>>paddingLevel)];
12 | for (int i=blockIdx.x;i>2;
18 | for (int k=threadIdx.x*4;k>2)+(k>>(2+paddingLevel))]=v4;
33 | }else{
34 | float v=0;
35 | for (int k2=k;k2>2)+(k>>(2+paddingLevel))]=v;
43 | }
44 | }
45 | int u=0;
46 | for (;(2<>(u+1));k+=blockDim.x){
49 | int i1=(((k<<1)+2)<>paddingLevel;
52 | i2+=i2>>paddingLevel;
53 | buffer[i1]+=buffer[i2];
54 | }
55 | }
56 | u--;
57 | for (;u>=0;u--){
58 | __syncthreads();
59 | for (int k=threadIdx.x;k>(u+1));k+=blockDim.x){
60 | int i1=(((k<<1)+3)<>paddingLevel;
63 | i2+=i2>>paddingLevel;
64 | buffer[i1]+=buffer[i2];
65 | }
66 | }
67 | __syncthreads();
68 | for (int k=threadIdx.x*4;k>2)-1)+(((k>>2)-1)>>paddingLevel);
71 | buffer4[k]+=buffer[k2];
72 | buffer4[k+1]+=buffer[k2];
73 | buffer4[k+2]+=buffer[k2];
74 | buffer4[k+3]+=buffer[k2];
75 | }
76 | }
77 | __syncthreads();
78 | for (int k=threadIdx.x;k>paddingLevel)]+runningsum2;
82 | float r2=runningsum+t;
83 | runningsum2=t-(r2-runningsum);
84 | runningsum=r2;
85 | __syncthreads();
86 | }
87 | }
88 | }
89 |
90 | __global__ void binarysearchKernel(int b,int n,int m,const float * __restrict__ dataset,const float * __restrict__ query, int * __restrict__ result){
91 | int base=1;
92 | while (base=1;k>>=1)
99 | if (r>=k && dataset[i*n+r-k]>=q)
100 | r-=k;
101 | result[i*m+j]=r;
102 | }
103 | }
104 | }
105 | __global__ void farthestpointsamplingKernel(int b,int n,int m,const float * __restrict__ dataset,float * __restrict__ temp,int * __restrict__ idxs){
106 | if (m<=0)
107 | return;
108 | const int BlockSize=512;
109 | __shared__ float dists[BlockSize];
110 | __shared__ int dists_i[BlockSize];
111 | const int BufferSize=3072;
112 | __shared__ float buf[BufferSize*3];
113 | for (int i=blockIdx.x;ibest){
147 | best=d2;
148 | besti=k;
149 | }
150 | }
151 | dists[threadIdx.x]=best;
152 | dists_i[threadIdx.x]=besti;
153 | for (int u=0;(1<>(u+1))){
156 | int i1=(threadIdx.x*2)<>>(b,n,inp,out);
196 | }
197 | //require b*n working space
198 | void probsampleLauncher(int b,int n,int m,const float * inp_p,const float * inp_r,float * temp,int * out){
199 | cumsumKernel<<<32,512>>>(b,n,inp_p,temp);
200 | binarysearchKernel<<>>(b,n,m,temp,inp_r,out);
201 | }
202 | //require 32*n working space
203 | void farthestpointsamplingLauncher(int b,int n,int m,const float * inp,float * temp,int * out){
204 | farthestpointsamplingKernel<<<32,512>>>(b,n,m,inp,temp,out);
205 | }
206 | void gatherpointLauncher(int b,int n,int m,const float * inp,const int * idx,float * out){
207 | gatherpointKernel<<>>(b,n,m,inp,idx,out);
208 | }
209 | void scatteraddpointLauncher(int b,int n,int m,const float * out_g,const int * idx,float * inp_g){
210 | scatteraddpointKernel<<>>(b,n,m,out_g,idx,inp_g);
211 | }
212 |
213 |
--------------------------------------------------------------------------------
/models/tf_ops/test.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import tensorflow as tf
3 | import approxmatch.tf_approxmatch as tf_approxmatch
4 | import nn_distance.tf_nndistance as tf_nndistance
5 | import mesh_sampling.tf_meshsampling as tf_meshsampling
6 | import mesh_laplacian.tf_meshlaplacian as tf_meshlaplacian
7 | import os
8 | import sys
9 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
10 | ROOT_DIR = os.path.dirname(BASE_DIR)
11 | sys.path.append(os.path.join(ROOT_DIR))
12 | import tf_util
13 |
14 | if __name__=='__main__':
15 | import numpy as np
16 | import random
17 | import time
18 | from tensorflow.python.ops.gradient_checker import compute_gradient
19 | random.seed(100)
20 | np.random.seed(100)
21 |
22 |
23 | def write_off(fn, verts, faces):
24 | file = open(fn, 'w')
25 | file.write('OFF\n')
26 | file.write('%d %d %d\n' % (len(verts), len(faces), 0))
27 | for vert in verts:
28 | file.write('%f %f %f\n' % (vert[0], vert[1], vert[2]))
29 | # verts.append([float(s) for s in readline().strip().split(' ')])
30 | for face in faces:
31 | file.write('3 %f %f %f\n' % (face[0], face[1], face[2]))
32 | # faces.append([int(s) for s in readline().strip().split(' ')][1:])
33 | file.close()
34 | return
35 |
36 | def read_off(fn):
37 | file = open(fn, 'r')
38 | if 'OFF' != file.readline().strip():
39 | print ('Not a valid OFF header')
40 | return
41 | n_verts, n_faces, n_dontknow = tuple([int(s) for s in file.readline().strip().split(' ')])
42 | verts = []
43 | for i_vert in range(n_verts):
44 | verts.append([float(s) for s in file.readline().strip().split(' ')])
45 | faces = []
46 | for i_face in range(n_faces):
47 | faces.append([int(s) for s in file.readline().strip().split(' ')][1:])
48 | file.close()
49 | return np.asarray(verts,dtype=np.float32), np.asarray(faces, dtype=np.int32)
50 |
51 |
52 | test1 = False
53 | test2 = True
54 |
55 | with tf.Session('') as sess:
56 | # xyz1=np.random.randn(32,16384,3).astype('float32')
57 | # xyz2=np.random.randn(32,1024,3).astype('float32')
58 | src_vertices, src_faces = read_off('1bf710535121b17cf453cc5da9731a22.off')
59 | dst_vertices, dst_faces = read_off('/mnt/ilcompf8d0/user/weiyuewa/dataset/shapenet/part_mesh/Models/Chair/1bcec47c5dc259ea95ca4adb70946a21.off')
60 |
61 |
62 | np.random.seed(int(time.time()))
63 | # r1 = tf.constant(np.random.random_sample((1, 40000)),dtype=tf.float32)
64 | # r2 = tf.constant(np.random.random_sample((1, 40000)),dtype=tf.float32)
65 | # r = tf.constant(np.random.random_sample((1, 40000)),dtype=tf.float32)
66 | r1 = tf.random_uniform([1, 40000],dtype=tf.float32)
67 | r2 = tf.random_uniform([1, 40000],dtype=tf.float32)
68 | r = tf.random_uniform([1, 40000],dtype=tf.float32)
69 |
70 |
71 | ##target
72 | dst_verts=tf.expand_dims(tf.constant(dst_vertices),0)
73 | dst_tris=tf.expand_dims(tf.constant(dst_faces),0)
74 | dst_feats=tf.expand_dims(tf.constant(dst_vertices),0)
75 | dst_nverts = tf.constant([[len(dst_vertices)]],dtype=tf.int32)
76 | dst_ntris = tf.constant([[len(dst_faces)]],dtype=tf.int32)
77 | dst_points, outfeats, correspondingfaces = tf_meshsampling.mesh_sampling(dst_verts, dst_nverts, dst_tris, dst_ntris, dst_feats, r, r1, r2)
78 | dst_points_val, dst_verts_val = sess.run([dst_points, dst_verts])
79 | np.savetxt('dst_points.xyz', np.squeeze(dst_points_val))
80 |
81 | # dst_points_val = np.concatenate((dst_points_val, dst_verts_val), axis =1)
82 | targetpoints = tf.constant(dst_points_val)
83 |
84 | ##source
85 | src_verts=tf.expand_dims(tf.constant(src_vertices),0)
86 | src_tris=tf.expand_dims(tf.constant(src_faces),0)
87 | src_feats=tf.expand_dims(tf.constant(src_vertices),0)
88 | src_nverts = tf.constant([[len(src_vertices)]],dtype=tf.int32)
89 | src_ntris = tf.constant([[len(src_faces)]],dtype=tf.int32)
90 | src_points, outfeats, correspondingfaces = tf_meshsampling.mesh_sampling(src_verts, src_nverts, src_tris, src_ntris, src_feats, r, r1, r2)
91 | src_points_val, src_verts_val = sess.run([src_points, src_verts])
92 | np.savetxt('src_points.xyz', np.squeeze(src_points_val))
93 |
94 | # src_feats = tf.concat([src_feats]*100, axis=2)
95 | feats = tf.Variable(src_feats)
96 | print src_feats.get_shape()
97 | points, outfeats, correspondingfaces = tf_meshsampling.mesh_sampling(src_verts, src_nverts, src_tris, src_ntris, feats, r, r1, r2)
98 | laplacian1, _, _ = tf_meshlaplacian.mesh_laplacian(src_verts, src_nverts, src_tris, src_ntris)
99 | # feats1 = tf.slice(feats, [0, 0, 0], [1, -1, 3])
100 | laplacian2, _, _ = tf_meshlaplacian.mesh_laplacian(feats, src_nverts, src_tris, src_ntris)
101 | laplacian_loss = 10*tf.nn.l2_loss(laplacian1 - laplacian2)
102 | # outfeats = tf.concat([outfeats, feats], axis=1)
103 |
104 | #loss
105 |
106 | # outfeats = tf.expand_dims(outfeats, 2)
107 |
108 | # Encoder
109 | # net = tf_util.conv2d(outfeats, 3, [1,6],
110 | # padding='VALID', stride=[1,1],
111 | # bn=False,
112 | # scope='conv1')
113 | # net = tf.squeeze(outfeats, 2)
114 | # print net.get_shape()
115 | outfeats = tf.slice(outfeats, [0, 0, 0], [1, -1, 3])
116 | dists_forward, _, dists_backward, _ = tf_nndistance.nn_distance(outfeats, targetpoints)
117 | loss = 10000*tf.reduce_mean(dists_forward) + 10000*tf.reduce_mean(dists_backward)+laplacian_loss
118 |
119 | feats_grad = tf.gradients(loss, [feats])[0]
120 | #
121 | train=tf.train.GradientDescentOptimizer(learning_rate=0.05).minimize(loss)
122 |
123 | sess.run(tf.initialize_all_variables())
124 | #
125 | old_lossval = 10000
126 | for i in range(100):
127 | # feed_dict = {feats_ph: feats_val}
128 | _, loss_val, feats_val, points_val, dst_points_val, outfeats_val, feats_grad_val,correspondingfaces_val2,r_val =sess.run([train, loss, feats, points, targetpoints, outfeats, feats_grad, correspondingfaces,r])#, feed_dict=feed_dict)
129 | # print feats_val
130 | # feats_val -= feats_grad_val*0.005
131 | # if loss_val= self.data_num:
63 | i = 0
64 |
65 | if tgt_single_mesh == None or src_single_mesh == None:
66 | continue
67 |
68 | src_verts, src_tris = src_single_mesh
69 | tgt_verts, tgt_tris = tgt_single_mesh
70 |
71 | src_batch_verts[cnt,:len(src_verts),:] = src_verts
72 | src_batch_tris[cnt,:len(src_tris),:] = src_tris
73 | src_batch_nverts[cnt, 0] = len(src_verts)
74 | src_batch_ntris[cnt, 0] = len(src_tris)
75 | tgt_batch_verts[cnt,:len(tgt_verts),:] = tgt_verts
76 | tgt_batch_tris[cnt,:len(tgt_tris),:] = tgt_tris
77 | tgt_batch_nverts[cnt, 0] = len(tgt_verts)
78 | tgt_batch_ntris[cnt, 0] = len(tgt_tris)
79 |
80 | cnt += 1
81 |
82 | src_batch_data = {}
83 | src_batch_data['verts'] = src_batch_verts
84 | src_batch_data['nverts'] = src_batch_nverts
85 | src_batch_data['tris'] = src_batch_tris
86 | src_batch_data['ntris'] = src_batch_ntris
87 | tgt_batch_data = {}
88 | tgt_batch_data['verts'] = tgt_batch_verts
89 | tgt_batch_data['nverts'] = tgt_batch_nverts
90 | tgt_batch_data['tris'] = tgt_batch_tris
91 | tgt_batch_data['ntris'] = tgt_batch_ntris
92 |
93 | return src_batch_data, tgt_batch_data
94 |
95 | def pc_normalize(self, pc, centroid=None):
96 |
97 | """ pc: NxC, return NxC """
98 | l = pc.shape[0]
99 |
100 | if centroid is None:
101 | centroid = np.mean(pc, axis=0)
102 |
103 | pc = pc - centroid
104 | m = np.max(np.sqrt(np.sum(pc ** 2, axis=1)))
105 |
106 | pc = pc / m
107 |
108 | return pc, centroid
109 |
110 | def get_one(self, path, subsamplemesh=False):
111 | if path in self.cache:
112 | return self.cache[path]
113 | else:
114 | try:
115 | h5_f = h5py.File(path)
116 | if (self.maxnverts != -1 and h5_f['verts'].shape[0] > self.maxnverts) or (self.maxntris != -1 and h5_f['tris'].shape[0] > self.maxntris):
117 | raise Exception()
118 |
119 | verts, tris = h5_f['verts'][:], h5_f['tris'][:]
120 | except:
121 | h5_f.close()
122 | self.cache[path] = None
123 | return None
124 |
125 | if self.normalize:
126 | centroid = None
127 | verts, _ = self.pc_normalize(verts, centroid)
128 |
129 | if subsamplemesh:
130 | mesh = pymesh.form_mesh(verts, tris)
131 | mesh, _ = pymesh.split_long_edges(mesh, 0.05)
132 | verts, tris = mesh.vertices, mesh.faces
133 | if (self.maxnverts != -1 and verts.shape[0] > self.maxnverts) or (self.maxntris != -1 and tris.shape[0] > self.maxntris):
134 | return None
135 |
136 | if len(self.cache) < self.cache_size:
137 | self.cache[path] = (verts, tris)
138 | h5_f.close()
139 |
140 | return verts, tris
141 |
142 |
143 | def __len__(self):
144 | return self.data_num
145 |
146 | if __name__ == '__main__':
147 | MAX_NVERTS = MAX_NTRIS = 5000
148 | d = H5Dataset('/media/hdd2/data/ShapeNet/filelists/ShapeNetCore.v2.h5/03001627_obj_5000.lst', maxnverts=MAX_NVERTS, maxntris=MAX_NTRIS)
149 |
150 | batch_size = 20
151 | tic = time.time()
152 | for i in range(10):
153 | i = i * batch_size
154 | batch = d.get_batch(i)
155 | print (time.time() - tic)
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/shapenet/data/data_img.py:
--------------------------------------------------------------------------------
1 | '''
2 | Dataset for shapenet part segmentaion.
3 | '''
4 |
5 | import os
6 | import json
7 | import numpy as np
8 | import sys
9 | import time
10 | import random
11 | from PIL import Image
12 | import tensorflow as tf
13 | import numpy as np
14 | import h5py
15 | import cv2
16 |
17 |
18 | def pc_normalize(pc):
19 | """ pc: NxC, return NxC """
20 | l = pc.shape[0]
21 | centroid = np.mean(pc, axis=0)
22 | pc = pc - centroid
23 | m = np.max(np.sqrt(np.sum(pc ** 2, axis=1)))
24 | pc = pc / m
25 | centroid = np.mean(pc, axis=0)
26 | pc = pc - centroid
27 | return pc
28 |
29 |
30 | def rotate_point_cloud(batch_data):
31 | """ Randomly rotate the point clouds to augument the dataset
32 | rotation is per shape based along up direction
33 | Input:
34 | BxNx3 array, original batch of point clouds
35 | Return:
36 | BxNx3 array, rotated batch of point clouds
37 | """
38 | rotated_data = np.zeros(batch_data.shape, dtype=np.float32)
39 | for k in np.arange(batch_data.shape[0]):
40 | rotation_angle = np.random.uniform() * 2 * np.pi
41 | cosval = np.cos(rotation_angle)
42 | sinval = np.sin(rotation_angle)
43 | rotation_matrix = np.array([[cosval, 0, sinval],
44 | [0, 1, 0],
45 | [-sinval, 0, cosval]])
46 | shape_pc = batch_data[k, ...]
47 | rotated_data[k, ...] = np.dot(shape_pc.reshape((-1, 3)), rotation_matrix)
48 | return rotated_data
49 |
50 | class ImgDataset_test():
51 | def __init__(self, listfile):
52 |
53 | self.inputlistfile = listfile
54 |
55 | if isinstance(self.inputlistfile, str):
56 | with open(self.inputlistfile, 'r') as f:
57 | lines = f.read().splitlines()
58 | self.datapath = [line.strip() for line in lines]
59 | else:
60 | self.datapath = listfile
61 |
62 | self.order = list(range(len(self.datapath)))
63 |
64 | def __getitem__(self, index):
65 |
66 | batch_img = np.ones([1, 600, 600, 3], dtype=np.float32)
67 | img = Image.open(self.datapath[index])#
68 |
69 | if img.size[0] > img.size[1]:
70 | img.thumbnail((400, int(400.*img.size[0]/img.size[1])), Image.ANTIALIAS)
71 | else:
72 | img.thumbnail((int(400.*img.size[1]/img.size[0]), 400), Image.ANTIALIAS)
73 |
74 | img = np.asarray(img, dtype=np.float32)
75 | print(img.shape)
76 | if len(img.shape) == 2:
77 | img = np.transpose(np.asarray([img,img,img]), (1,2,0))
78 |
79 | if img.shape[2] == 4:
80 | mask = img[:,:,3]
81 | img = img[:,:,:3] / 255.
82 | img[mask==0,:] = 1.
83 | else:
84 | img /= 255.
85 | offsetx = int((600. - img.shape[0]) / 2)
86 | offsety = int((600. - img.shape[1]) / 2)
87 | batch_img[:,offsetx:offsetx+img.shape[0],offsety:offsety+img.shape[1], :] = img
88 |
89 | return batch_img
90 |
91 |
92 | def __len__(self):
93 | return len(self.datapath)
94 |
95 |
96 | if __name__ == '__main__':
97 | path = '/mnt/ilcompf8d0/user/weiyuewa/dataset/shapenet/ShapeNetCore.v2.render_img/03001627/a06c400e070343cfd8a56a98f4d239c3/image/r_000.png'
98 | img = np.asarray(Image.open(path), dtype=np.float32)
99 | mask = img[:,:,3]
100 | img = img[:,:,:3] / 255.
101 | img[mask==0,:] = 1.
102 | cv2.imwrite('tmp.png', (img * 255).astype(np.uint8))
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/shapenet/data/data_obj.py:
--------------------------------------------------------------------------------
1 | '''
2 | Dataset for shapenet part segmentaion.
3 | '''
4 |
5 | import os
6 | import os.path
7 | import json
8 | import numpy as np
9 | import sys
10 | import tensorflow as tf
11 | import numpy as np
12 | import obj
13 |
14 |
15 | def pc_normalize(pc):
16 | """ pc: NxC, return NxC """
17 | l = pc.shape[0]
18 | centroid = np.mean(pc, axis=0)
19 | pc = pc - centroid
20 | m = np.max(np.sqrt(np.sum(pc ** 2, axis=1)))
21 | pc = pc / m
22 | centroid = np.mean(pc, axis=0)
23 | pc = pc - centroid
24 | return pc
25 |
26 | def write_obj(filepath, verts, tris):
27 | with open(filepath, 'w') as f:
28 | f.write("# OBJ file\n")
29 | for v in verts:
30 | f.write("v %.4f %.4f %.4f\n" % (v[0], v[1], v[2]))
31 | for p in tris:
32 | f.write("f")
33 | for i in p:
34 | f.write(" %d" % (i + 1))
35 | f.write("\n")
36 |
37 | def rotate_point_cloud(batch_data):
38 | """ Randomly rotate the point clouds to augument the dataset
39 | rotation is per shape based along up direction
40 | Input:
41 | BxNx3 array, original batch of point clouds
42 | Return:
43 | BxNx3 array, rotated batch of point clouds
44 | """
45 | rotated_data = np.zeros(batch_data.shape, dtype=np.float32)
46 | for k in np.arange(batch_data.shape[0]):
47 | rotation_angle = np.random.uniform() * 2 * np.pi
48 | cosval = np.cos(rotation_angle)
49 | sinval = np.sin(rotation_angle)
50 | rotation_matrix = np.array([[cosval, 0, sinval],
51 | [0, 1, 0],
52 | [-sinval, 0, cosval]])
53 | shape_pc = batch_data[k, ...]
54 | rotated_data[k, ...] = np.dot(shape_pc.reshape((-1, 3)), rotation_matrix)
55 | return rotated_data
56 |
57 | class ObjDataset():
58 | def __init__(self, listfile, maxnverts=10000, maxntris=10000, normalize = True, texture=0):
59 | self.maxnverts = maxnverts
60 | self.maxntris = maxntris
61 | self.inputlistfile = listfile
62 | self.normalize = normalize
63 | self.texture = texture
64 |
65 | if isinstance(self.inputlistfile, basestring):
66 | with open(self.inputlistfile, 'r') as f:
67 | lines = f.read().splitlines()
68 | self.datapath = [line.strip() for line in lines]
69 | else:
70 | self.datapath = listfile
71 |
72 | self.cache = {} # from index to (point_set, cls, seg) tuple
73 | self.cache_size = 18000
74 |
75 | def __getitem__(self, index):
76 |
77 | if self.texture == 0:
78 | if index in self.cache:
79 | verts, tris = self.cache[index]
80 | else:
81 | obj_fn = self.datapath[index]+'.obj'
82 | try:
83 | loadobj = obj.load_obj(obj_fn, maxnverts=self.maxnverts, maxntris=self.maxntris)
84 | except:
85 | loadobj = None
86 |
87 | if loadobj == None:
88 | if (index + 1) < len(self.datapath):
89 | return self.__getitem__(index+1)
90 | else:
91 | return self.__getitem__(0)
92 |
93 | verts, tris = loadobj
94 | if self.normalize:
95 | verts = pc_normalize(verts)
96 |
97 | if len(self.cache) < self.cache_size:
98 | self.cache[index] = (verts, tris)
99 |
100 | return verts, tris
101 | else:
102 | if index in self.cache:
103 | verts, tris, textures = self.cache[index]
104 | else:
105 | obj_fn = self.datapath[index]+'.obj'
106 | try:
107 | loadobj = obj.load_obj(obj_fn, texture_size=self.texture, load_texture=True, maxnverts=self.maxnverts, maxntris=self.maxntris)
108 | except:
109 | loadobj = None
110 | if loadobj == None:
111 | if (index + 1) < len(self.datapath):
112 | return self.__getitem__(index+1)
113 | else:
114 | return self.__getitem__(0)
115 |
116 | verts, tris, textures = loadobj
117 | if self.normalize:
118 | verts = pc_normalize(verts)
119 |
120 | if len(self.cache) < self.cache_size:
121 | self.cache[index] = (verts, tris, textures)
122 |
123 | return verts, tris, textures
124 |
125 |
126 | def __len__(self):
127 | return len(self.datapath)
128 |
129 |
130 | if __name__ == '__main__':
131 |
132 | d = ObjDataset('/mnt/ilcompf8d0/user/weiyuewa/dataset/shapenet/part_mesh/Models/filelists/chair.lst')
133 |
134 |
--------------------------------------------------------------------------------
/shapenet/data/data_pc.py:
--------------------------------------------------------------------------------
1 | '''
2 | Dataset for shapenet part segmentaion.
3 | '''
4 |
5 | import os
6 | import os.path
7 | import json
8 | import numpy as np
9 | import sys
10 | import tensorflow as tf
11 | # import matplotlib.pyplot as plt
12 | import numpy as np
13 | # from matplotlib import colors
14 | # from matplotlib.ticker import PercentFormatter
15 |
16 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
17 | ROOT_DIR = os.path.dirname(BASE_DIR)
18 | sys.path.append(os.path.join(ROOT_DIR))
19 | sys.path.append(os.path.join(ROOT_DIR,'..'))
20 | try:
21 | import models.tf_ops.approxmatch.tf_approxmatch as tf_approxmatch
22 | import models.tf_ops.nn_distance.tf_nndistance as tf_nndistance
23 | import models.tf_ops.mesh_sampling.tf_meshsampling as tf_meshsampling
24 | import models.tf_ops.mesh_laplacian.tf_meshlaplacian as tf_meshlaplacian
25 | except:
26 | import models.tf_ops_server.approxmatch.tf_approxmatch as tf_approxmatch
27 | import models.tf_ops_server.nn_distance.tf_nndistance as tf_nndistance
28 | import models.tf_ops_server.mesh_sampling.tf_meshsampling as tf_meshsampling
29 | import models.tf_ops_server.mesh_laplacian.tf_meshlaplacian as tf_meshlaplacian
30 |
31 |
32 | def pc_normalize(pc):
33 | """ pc: NxC, return NxC """
34 | l = pc.shape[0]
35 | centroid = np.mean(pc, axis=0)
36 | pc = pc - centroid
37 | m = np.max(np.sqrt(np.sum(pc ** 2, axis=1)))
38 | pc = pc / m
39 | return pc
40 |
41 |
42 | def rotate_point_cloud(batch_data):
43 | """ Randomly rotate the point clouds to augument the dataset
44 | rotation is per shape based along up direction
45 | Input:
46 | BxNx3 array, original batch of point clouds
47 | Return:
48 | BxNx3 array, rotated batch of point clouds
49 | """
50 | rotated_data = np.zeros(batch_data.shape, dtype=np.float32)
51 | for k in np.arange(batch_data.shape[0]):
52 | rotation_angle = np.random.uniform() * 2 * np.pi
53 | cosval = np.cos(rotation_angle)
54 | sinval = np.sin(rotation_angle)
55 | rotation_matrix = np.array([[cosval, 0, sinval],
56 | [0, 1, 0],
57 | [-sinval, 0, cosval]])
58 | shape_pc = batch_data[k, ...]
59 | rotated_data[k, ...] = np.dot(shape_pc.reshape((-1, 3)), rotation_matrix)
60 | return rotated_data
61 |
62 |
63 |
64 | class PartPcDataset():
65 | def __init__(self, listfile, npoints, normalize = True):
66 | self.inputlistfile = listfile
67 | self.normalize = normalize
68 |
69 | with open(self.inputlistfile, 'r') as f:
70 | lines = f.read().splitlines()
71 | self.datapath = [line.strip() for line in lines]
72 |
73 | self.cache = {} # from index to (point_set, cls, seg) tuple
74 | self.cache_size = 18000
75 | self.npoints = npoints
76 |
77 | def __getitem__(self, index):
78 | if index in self.cache:
79 | points, label = self.cache[index]
80 | else:
81 | fn = self.datapath[index]+'.pts'
82 | points = np.loadtxt(fn)
83 | fn_label = self.datapath[index].replace("points", "points_label")+'.seg'
84 | label = np.loadtxt(fn_label) - 1
85 | choice = np.random.choice(len(points), self.npoints, replace=True)
86 | # resample
87 | try:
88 | points = points[choice, :]
89 | label = label[choice]
90 | except:
91 | if (index + 1) < len(self.datapath):
92 | # print 'exceed max nverts', index+1
93 | return self.__getitem__(index+1)
94 | else:
95 | return self.__getitem__(0)
96 | if self.normalize:
97 | points = pc_normalize(points)
98 |
99 | if len(self.cache) < self.cache_size:
100 | self.cache[index] = (points, label)
101 |
102 | return points, label#, index
103 |
104 | def __len__(self):
105 | return len(self.datapath)
106 |
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/laughtervv/3DN/81e3651d780478139c3b8dee5e737ce565813900/utils/__init__.py
--------------------------------------------------------------------------------
/utils/output_utils.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | import sys
4 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
5 | sys.path.append(os.path.dirname(os.path.abspath(__file__))) # model
6 | import numpy as np
7 | import matplotlib as mpl
8 | import matplotlib.pyplot as plt
9 | mpl.use('Agg')
10 | ############################
11 | ## Visualize Results ##
12 | ############################
13 |
14 | color_map = json.load(open(os.path.join(BASE_DIR, 'part_color_mapping.json'), 'r'))
15 |
16 | def output_bounding_box_withcorners(box_corners, seg, out_file):
17 | # ############## 0 1 2 3 4 5 6 7
18 | corner_indexes = [[0, 1, 2], [0, 1, 5], [0, 4, 2], [0, 4, 5], [3, 1, 2], [3, 1, 5], [3, 4, 2], [3, 4, 5]]
19 | line_indexes = [[0, 1], [0, 2], [0, 4], [1, 3], [1, 5], [2, 3], [2, 6], [3, 7], [4, 5], [4, 6], [5, 7], [6, 7]]
20 | with open(out_file, 'w') as f:
21 | l = box_corners.shape[0]
22 | for i in range(l):
23 | box = box_corners[i]
24 | color = color_map[seg[i]]
25 | for line_index in line_indexes:
26 | corner0 = box[line_index[0]]
27 | corner1 = box[line_index[1]]
28 | print corner0.shape
29 | dist = np.linalg.norm(corner0 - corner1)
30 | dot_num = int(dist / 0.005)
31 | delta = (corner1 - corner0) / dot_num
32 | for idot in range(dot_num):
33 | plotdot = corner0 + idot * delta
34 | f.write(
35 | 'v %f %f %f %f %f %f\n' % (plotdot[0], plotdot[1], plotdot[2], color[0], color[1], color[2]))
36 |
37 |
38 | def output_bounding_box(boxes, seg, out_file):
39 | # ############## 0 1 2 3 4 5 6 7
40 | #box:nx8x3
41 | corner_indexes = [[0, 1, 2], [0, 1, 5], [0, 4, 2], [0, 4, 5], [3, 1, 2], [3, 1, 5], [3, 4, 2], [3, 4, 5]]
42 | line_indexes = [[0, 1], [0, 2], [0, 4], [1, 3], [1, 5], [2, 3], [2, 6], [3, 7], [4, 5], [4, 6], [5, 7], [6, 7]]
43 | with open(out_file, 'w') as f:
44 | l = boxes.shape[0]
45 | for i in range(l):
46 | box = boxes[i]
47 | color = color_map[seg[i]]
48 | for line_index in line_indexes:
49 | corner0 = box[corner_indexes[line_index[0]]]
50 | corner1 = box[corner_indexes[line_index[1]]]
51 | dist = np.linalg.norm(corner0 - corner1)
52 | dot_num = int(dist / 0.005)
53 | delta = (corner1 - corner0) / dot_num
54 | for idot in range(dot_num):
55 | plotdot = corner0 + idot * delta
56 | f.write(
57 | 'v %f %f %f %f %f %f\n' % (plotdot[0], plotdot[1], plotdot[2], color[0], color[1], color[2]))
58 |
59 |
60 | def output_color_point_cloud(data, seg, out_file):
61 | with open(out_file, 'w') as f:
62 | l = len(seg)
63 | for i in range(l):
64 | color = color_map[seg[i]]
65 | f.write('v %f %f %f %f %f %f\n' % (data[i][0], data[i][1], data[i][2], color[0], color[1], color[2]))
66 |
67 |
68 | def output_point_cloud_rgb(data, rgb, out_file):
69 | with open(out_file, 'w') as f:
70 | l = len(data)
71 | for i in range(l):
72 | f.write('v %f %f %f %f %f %f\n' % (data[i][0], data[i][1], data[i][2], rgb[i][0], rgb[i][1], rgb[i][2]))
73 |
74 |
75 | def output_color_point_cloud_red_blue(data, seg, out_file):
76 | with open(out_file, 'w') as f:
77 | l = len(seg)
78 | for i in range(l):
79 | if seg[i] == 1:
80 | color = [0, 0, 1]
81 | elif seg[i] == 0:
82 | color = [1, 0, 0]
83 | else:
84 | color = [0, 0, 0]
85 | f.write('v %f %f %f %f %f %f\n' % (data[i][0], data[i][1], data[i][2], color[0], color[1], color[2]))
86 |
87 |
88 | ##define color heat map
89 | norm = mpl.colors.Normalize(vmin=0, vmax=255)
90 | magma_cmap = plt.cm.get_cmap('magma')
91 | magma_rgb = []
92 | for i in range(0, 255):
93 | k = mpl.colors.colorConverter.to_rgb(magma_cmap(norm(i)))
94 | magma_rgb.append(k)
95 |
96 |
97 | def output_scale_point_cloud(data, scales, out_file):
98 | with open(out_file, 'w') as f:
99 | l = len(scales)
100 | for i in range(l):
101 | scale = int(scales[i]*254)
102 | if scale > 254:
103 | scale = 254
104 | color = magma_rgb[scale]
105 | f.write('v %f %f %f %f %f %f\n' % (data[i][0], data[i][1], data[i][2], color[0], color[1], color[2]))
106 |
--------------------------------------------------------------------------------
/utils/part_color_mapping.json:
--------------------------------------------------------------------------------
1 | [[0.57, 0.15, 0.43], [0.85, 0.57, 0.29], [0.7100000000000001, 0.7100000000000001, 0.01], [0.01, 0.7100000000000001, 0.15], [0.01, 0.57, 0.85], [0.43, 0.01, 0.7100000000000001], [0.43, 0.7100000000000001, 0.57], [0.29, 0.29, 0.29], [0.29, 0.7100000000000001, 0.7100000000000001], [0.57, 0.57, 0.29], [0.57, 0.7100000000000001, 0.7100000000000001], [0.01, 0.01, 0.29], [0.29, 0.57, 0.7100000000000001], [0.29, 0.15, 0.57], [0.29, 0.7100000000000001, 0.43], [0.57, 0.29, 0.01], [0.29, 0.15, 0.15], [0.7100000000000001, 0.29, 0.01], [0.01, 0.85, 0.15], [0.85, 0.01, 0.01], [0.29, 0.15, 0.7100000000000001], [0.7100000000000001, 0.15, 0.43], [0.29, 0.43, 0.7100000000000001], [0.43, 0.43, 0.7100000000000001], [0.29, 0.57, 0.01], [0.57, 0.29, 0.29], [0.57, 0.85, 0.15], [0.15, 0.29, 0.29], [0.15, 0.7100000000000001, 0.15], [0.85, 0.01, 0.29], [0.43, 0.85, 0.29], [0.43, 0.29, 0.85], [0.57, 0.85, 0.85], [0.15, 0.57, 0.01], [0.57, 0.29, 0.15], [0.7100000000000001, 0.85, 0.57], [0.57, 0.01, 0.57], [0.01, 0.85, 0.43], [0.01, 0.01, 0.01], [0.85, 0.01, 0.43], [0.57, 0.43, 0.57], [0.85, 0.01, 0.57], [0.01, 0.43, 0.43], [0.01, 0.29, 0.85], [0.57, 0.57, 0.7100000000000001], [0.7100000000000001, 0.29, 0.57], [0.57, 0.7100000000000001, 0.43], [0.29, 0.15, 0.01], [0.57, 0.15, 0.15], [0.85, 0.57, 0.85], [0.85, 0.29, 0.85], [0.85, 0.15, 0.01], [0.85, 0.7100000000000001, 0.01], [0.01, 0.57, 0.15], [0.43, 0.01, 0.43], [0.57, 0.15, 0.85], [0.01, 0.29, 0.57], [0.29, 0.85, 0.43], [0.57, 0.29, 0.43], [0.43, 0.01, 0.29], [0.15, 0.85, 0.7100000000000001], [0.85, 0.57, 0.43], [0.01, 0.15, 0.57], [0.7100000000000001, 0.7100000000000001, 0.29], [0.7100000000000001, 0.15, 0.57], [0.43, 0.43, 0.29], [0.7100000000000001, 0.43, 0.43], [0.01, 0.43, 0.57], [0.57, 0.01, 0.15], [0.57, 0.57, 0.01], [0.29, 0.01, 0.29], [0.7100000000000001, 0.01, 0.29], [0.85, 0.85, 0.7100000000000001], [0.85, 0.15, 0.29], [0.43, 0.29, 0.57], [0.43, 0.43, 0.85], [0.85, 0.15, 0.85], [0.57, 0.85, 0.29], [0.57, 0.7100000000000001, 0.01], [0.7100000000000001, 0.85, 0.15], [0.85, 0.7100000000000001, 0.43], [0.01, 0.15, 0.01], [0.85, 0.29, 0.43], [0.43, 0.85, 0.15], [0.15, 0.01, 0.15], [0.7100000000000001, 0.7100000000000001, 0.85], [0.43, 0.29, 0.01], [0.15, 0.43, 0.29], [0.7100000000000001, 0.57, 0.15], [0.29, 0.85, 0.29], [0.29, 0.7100000000000001, 0.57], [0.57, 0.85, 0.7100000000000001], [0.15, 0.01, 0.85], [0.43, 0.15, 0.57], [0.57, 0.57, 0.15], [0.01, 0.57, 0.01], [0.15, 0.29, 0.57], [0.29, 0.57, 0.43], [0.15, 0.7100000000000001, 0.01], [0.15, 0.15, 0.15], [0.43, 0.29, 0.15], [0.7100000000000001, 0.29, 0.7100000000000001], [0.7100000000000001, 0.85, 0.43], [0.15, 0.29, 0.7100000000000001], [0.15, 0.43, 0.57], [0.01, 0.7100000000000001, 0.01], [0.85, 0.29, 0.01], [0.15, 0.01, 0.57], [0.29, 0.29, 0.7100000000000001], [0.15, 0.7100000000000001, 0.29], [0.01, 0.15, 0.43], [0.7100000000000001, 0.01, 0.15], [0.57, 0.43, 0.01], [0.85, 0.43, 0.01], [0.43, 0.85, 0.7100000000000001], [0.85, 0.43, 0.43], [0.85, 0.01, 0.15], [0.01, 0.43, 0.85], [0.15, 0.15, 0.7100000000000001], [0.29, 0.57, 0.85], [0.43, 0.15, 0.15], [0.29, 0.85, 0.85], [0.15, 0.57, 0.29], [0.85, 0.85, 0.85], [0.29, 0.43, 0.43], [0.01, 0.43, 0.29], [0.43, 0.15, 0.7100000000000001], [0.7100000000000001, 0.01, 0.57], [0.7100000000000001, 0.43, 0.15], [0.01, 0.85, 0.01], [0.85, 0.01, 0.7100000000000001], [0.57, 0.43, 0.43], [0.57, 0.85, 0.01], [0.01, 0.57, 0.43], [0.15, 0.15, 0.01], [0.85, 0.43, 0.85], [0.57, 0.15, 0.29], [0.7100000000000001, 0.7100000000000001, 0.57], [0.57, 0.01, 0.85], [0.29, 0.43, 0.15], [0.7100000000000001, 0.57, 0.7100000000000001], [0.43, 0.7100000000000001, 0.85], [0.01, 0.15, 0.15], [0.85, 0.85, 0.57], [0.43, 0.85, 0.01], [0.15, 0.15, 0.85], [0.29, 0.29, 0.43], [0.29, 0.43, 0.57], [0.7100000000000001, 0.29, 0.85], [0.15, 0.15, 0.43], [0.85, 0.7100000000000001, 0.85], [0.85, 0.15, 0.43], [0.43, 0.43, 0.15], [0.57, 0.7100000000000001, 0.15], [0.7100000000000001, 0.43, 0.57], [0.7100000000000001, 0.43, 0.01], [0.85, 0.29, 0.29], [0.85, 0.15, 0.15], [0.43, 0.57, 0.85], [0.01, 0.85, 0.29], [0.29, 0.7100000000000001, 0.15], [0.57, 0.85, 0.57], [0.43, 0.43, 0.57], [0.01, 0.7100000000000001, 0.7100000000000001], [0.57, 0.15, 0.57], [0.57, 0.57, 0.43], [0.85, 0.57, 0.57], [0.85, 0.7100000000000001, 0.7100000000000001], [0.57, 0.7100000000000001, 0.85], [0.15, 0.85, 0.85], [0.29, 0.57, 0.57], [0.15, 0.7100000000000001, 0.85], [0.57, 0.01, 0.29], [0.29, 0.7100000000000001, 0.01], [0.7100000000000001, 0.29, 0.15], [0.85, 0.01, 0.85], [0.29, 0.01, 0.57], [0.29, 0.01, 0.7100000000000001], [0.7100000000000001, 0.85, 0.29], [0.85, 0.29, 0.7100000000000001], [0.43, 0.15, 0.43], [0.01, 0.01, 0.15], [0.01, 0.7100000000000001, 0.57], [0.7100000000000001, 0.15, 0.01], [0.7100000000000001, 0.15, 0.15], [0.29, 0.29, 0.85], [0.01, 0.43, 0.7100000000000001], [0.57, 0.15, 0.01], [0.85, 0.15, 0.7100000000000001], [0.43, 0.43, 0.01], [0.29, 0.85, 0.57], [0.01, 0.29, 0.43], [0.57, 0.43, 0.29], [0.43, 0.29, 0.43], [0.85, 0.7100000000000001, 0.29], [0.7100000000000001, 0.85, 0.85], [0.43, 0.43, 0.43], [0.43, 0.29, 0.7100000000000001], [0.7100000000000001, 0.57, 0.57], [0.57, 0.29, 0.85], [0.01, 0.15, 0.7100000000000001], [0.7100000000000001, 0.7100000000000001, 0.15], [0.15, 0.85, 0.01], [0.43, 0.7100000000000001, 0.7100000000000001], [0.43, 0.57, 0.43], [0.7100000000000001, 0.01, 0.85], [0.29, 0.43, 0.29], [0.57, 0.15, 0.7100000000000001], [0.29, 0.57, 0.15], [0.15, 0.29, 0.43], [0.43, 0.85, 0.57], [0.43, 0.57, 0.57], [0.7100000000000001, 0.01, 0.01], [0.85, 0.85, 0.29], [0.15, 0.01, 0.29], [0.85, 0.29, 0.15], [0.15, 0.01, 0.01], [0.01, 0.01, 0.57], [0.15, 0.57, 0.15], [0.15, 0.43, 0.85], [0.01, 0.01, 0.7100000000000001], [0.85, 0.15, 0.57], [0.29, 0.15, 0.29], [0.15, 0.29, 0.15], [0.43, 0.85, 0.43], [0.01, 0.15, 0.29], [0.85, 0.7100000000000001, 0.15], [0.01, 0.01, 0.85], [0.7100000000000001, 0.57, 0.85], [0.01, 0.85, 0.57], [0.29, 0.85, 0.7100000000000001], [0.15, 0.01, 0.7100000000000001], [0.85, 0.57, 0.15], [0.15, 0.57, 0.85], [0.15, 0.43, 0.15], [0.15, 0.85, 0.57], [0.7100000000000001, 0.85, 0.01], [0.7100000000000001, 0.01, 0.7100000000000001], [0.15, 0.43, 0.43], [0.01, 0.57, 0.7100000000000001], [0.43, 0.01, 0.57], [0.01, 0.57, 0.57], [0.57, 0.43, 0.7100000000000001], [0.7100000000000001, 0.29, 0.29], [0.15, 0.43, 0.7100000000000001], [0.57, 0.43, 0.15], [0.01, 0.7100000000000001, 0.29], [0.7100000000000001, 0.57, 0.01], [0.01, 0.29, 0.15], [0.29, 0.85, 0.01], [0.57, 0.29, 0.57], [0.85, 0.43, 0.29], [0.7100000000000001, 0.43, 0.29], [0.29, 0.7100000000000001, 0.85], [0.85, 0.57, 0.01], [0.01, 0.29, 0.7100000000000001], [0.15, 0.57, 0.7100000000000001], [0.85, 0.57, 0.7100000000000001], [0.85, 0.43, 0.7100000000000001], [0.15, 0.57, 0.43], [0.15, 0.85, 0.29], [0.15, 0.29, 0.85], [0.7100000000000001, 0.29, 0.43], [0.15, 0.15, 0.29], [0.43, 0.7100000000000001, 0.01], [0.29, 0.7100000000000001, 0.29], [0.7100000000000001, 0.7100000000000001, 0.43], [0.29, 0.85, 0.15], [0.43, 0.15, 0.29], [0.29, 0.01, 0.15], [0.57, 0.01, 0.01], [0.85, 0.85, 0.15], [0.43, 0.7100000000000001, 0.15], [0.43, 0.7100000000000001, 0.29], [0.7100000000000001, 0.57, 0.43], [0.29, 0.29, 0.57], [0.29, 0.01, 0.43], [0.85, 0.7100000000000001, 0.57], [0.57, 0.29, 0.7100000000000001], [0.43, 0.29, 0.29], [0.7100000000000001, 0.43, 0.7100000000000001], [0.43, 0.57, 0.29], [0.43, 0.01, 0.15], [0.15, 0.7100000000000001, 0.57], [0.01, 0.29, 0.29], [0.29, 0.01, 0.01], [0.7100000000000001, 0.15, 0.85], [0.57, 0.7100000000000001, 0.29], [0.57, 0.7100000000000001, 0.57], [0.15, 0.29, 0.01], [0.29, 0.43, 0.01], [0.7100000000000001, 0.15, 0.7100000000000001], [0.85, 0.85, 0.43], [0.7100000000000001, 0.15, 0.29], [0.7100000000000001, 0.7100000000000001, 0.7100000000000001], [0.29, 0.57, 0.29], [0.85, 0.43, 0.57], [0.01, 0.57, 0.29], [0.57, 0.01, 0.43], [0.01, 0.29, 0.01], [0.29, 0.01, 0.85], [0.43, 0.57, 0.15], [0.85, 0.85, 0.01], [0.29, 0.15, 0.43], [0.29, 0.29, 0.15], [0.01, 0.43, 0.01], [0.43, 0.85, 0.85], [0.15, 0.7100000000000001, 0.7100000000000001], [0.15, 0.85, 0.43], [0.7100000000000001, 0.85, 0.7100000000000001], [0.7100000000000001, 0.01, 0.43], [0.15, 0.43, 0.01], [0.43, 0.57, 0.01], [0.7100000000000001, 0.57, 0.29], [0.01, 0.85, 0.85], [0.01, 0.85, 0.7100000000000001], [0.01, 0.7100000000000001, 0.85], [0.43, 0.7100000000000001, 0.43], [0.43, 0.15, 0.01], [0.57, 0.85, 0.43], [0.85, 0.43, 0.15], [0.01, 0.15, 0.85], [0.85, 0.29, 0.57], [0.01, 0.01, 0.43], [0.57, 0.01, 0.7100000000000001], [0.29, 0.29, 0.01], [0.57, 0.43, 0.85], [0.43, 0.15, 0.85], [0.01, 0.7100000000000001, 0.43], [0.15, 0.57, 0.57], [0.15, 0.15, 0.57], [0.29, 0.43, 0.85], [0.43, 0.01, 0.01], [0.57, 0.57, 0.85], [0.15, 0.7100000000000001, 0.43], [0.43, 0.01, 0.85], [0.15, 0.01, 0.43], [0.43, 0.57, 0.7100000000000001], [0.29, 0.15, 0.85], [0.15, 0.85, 0.15], [0.7100000000000001, 0.43, 0.85], [0.01, 0.43, 0.15], [0.57, 0.57, 0.57]]
2 |
--------------------------------------------------------------------------------
/utils/test_utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import os
3 | import pymesh
4 |
5 | BASE_DIR = os.path.dirname(os.path.abspath(__file__))
6 |
7 | def iou_pymesh(mesh1, mesh2, dim=110):
8 | # mesh1 = (vertices1, triangles1)
9 | # mesh2 = (vertices2, triangles2)
10 |
11 | mesh1 = pymesh.form_mesh(mesh1[0], mesh1[1])
12 | grid1 = pymesh.VoxelGrid(2./dim)
13 | grid1.insert_mesh(mesh1)
14 | grid1.create_grid()
15 |
16 | ind1 = ((grid1.mesh.vertices + 1.1) / 2.4 * dim).astype(np.int)
17 | v1 = np.zeros([dim, dim, dim])
18 | v1[ind1[:,0], ind1[:,1], ind1[:,2]] = 1
19 |
20 |
21 | mesh2 = pymesh.form_mesh(mesh2[0], mesh2[1])
22 | grid2 = pymesh.VoxelGrid(2./dim)
23 | grid2.insert_mesh(mesh2)
24 | grid2.create_grid()
25 |
26 | ind2 = ((grid2.mesh.vertices + 1.1) / 2.4 * dim).astype(np.int)
27 | v2 = np.zeros([dim, dim, dim])
28 | v2[ind2[:,0], ind2[:,1], ind2[:,2]] = 1
29 |
30 | intersection = np.sum(np.logical_and(v1, v2))
31 | union = np.sum(np.logical_or(v1, v2))
32 | return float(intersection) / union
33 |
34 | def iou_binvox(off_path1, off_path2):
35 |
36 | solidbinvoxpath1 = off_path1[:-4] + '.binvox'
37 | if not os.path.exists(solidbinvoxpath1):
38 | os.system("%s/binvox -cb -dc -aw -bb -1. -1. -1. 1. 1. 1. -d 128 %s -pb 2>&1 >/dev/null" % (BASE_DIR, off_path1))
39 | with open(solidbinvoxpath1, 'rb') as f:
40 | v1 = binvox_rw.read_as_3d_array(f)#.data
41 | pc1 = process_binvox(v1)
42 |
43 | solidbinvoxpath2 = off_path2[:-4] + '.binvox'
44 | if not os.path.exists(solidbinvoxpath2):
45 | os.system("%s/binvox -cb -dc -aw -bb -1. -1. -1. 1. 1. 1. -d 128 %s -pb 2>&1 >/dev/null" % (BASE_DIR, off_path2))
46 | with open(solidbinvoxpath2, 'rb') as f:
47 | v2 = binvox_rw.read_as_3d_array(f)#.data
48 | pc2 = process_binvox(v2)
49 |
50 | intersection = np.sum(np.logical_and(v1.data, v2.data))
51 | union = np.sum(np.logical_or(v1.data, v2.data))
52 | return float(intersection) / union
53 |
54 |
55 | if __name__ == "__main__":
56 |
57 | off_path1 = '/media/ssd/projects/Deformation/Sources/3DN/shapenet/3D/checkpoint/3DN_allcategories_ft/test_results/0_deformmesh.obj'
58 | off_path2 = '/media/ssd/projects/Deformation/Sources/3DN/shapenet/3D/checkpoint/3DN_allcategories_ft/test_results/0_refmesh.obj'
59 |
60 | mesh1 = pymesh.load_mesh('/media/ssd/projects/Deformation/Sources/3DN/shapenet/3D/checkpoint/3DN_allcategories_ft/test_results/0_deformmesh.obj');
61 | mesh2 = pymesh.load_mesh('/media/ssd/projects/Deformation/Sources/3DN/shapenet/3D/checkpoint/3DN_allcategories_ft/test_results/0_refmesh.obj');
62 | print(iou_pymesh((mesh1.vertices, mesh1.faces), (mesh2.vertices, mesh2.faces)))
63 | # grid = pymesh.VoxelGrid(0.01);
64 | # grid.insert_mesh(mesh);
65 | # grid.create_grid();
66 | # out_mesh = grid.mesh;
67 | # print(out_mesh.vertices)
68 | # pymesh.save_mesh('tmp.obj', out_mesh);
69 | # print(iou_off(off_path1, off_path2))
70 |
--------------------------------------------------------------------------------